From 96fb9b02acfa2466b459bd3ef9f311fbd9f5f66b Mon Sep 17 00:00:00 2001 From: tobinio Date: Sat, 4 May 2024 09:28:07 +0200 Subject: [PATCH] replace scroll_selector with filter_view --- src/project/dependency/mod.rs | 37 ----- src/project/document.rs | 28 +--- src/project/package.rs | 30 ---- src/rendering/display.rs | 44 +++--- .../item.rs} | 42 +----- src/rendering/filter_view/mod.rs | 138 ++++++++++++++++++ src/rendering/mod.rs | 3 +- 7 files changed, 167 insertions(+), 155 deletions(-) rename src/rendering/{scroll_selector.rs => filter_view/item.rs} (63%) create mode 100644 src/rendering/filter_view/mod.rs diff --git a/src/project/dependency/mod.rs b/src/project/dependency/mod.rs index b4fbadd..ef49f02 100644 --- a/src/project/dependency/mod.rs +++ b/src/project/dependency/mod.rs @@ -1,14 +1,11 @@ use color_eyre::eyre::{eyre, ContextCompat, Result}; -use std::cmp::Ordering; use std::collections::HashMap; use cargo_platform::Platform; use crate::project::dependency::feature::{EnabledState, FeatureData, SubFeatureType}; -use crate::rendering::scroll_selector::SelectorItem; use cargo_metadata::DependencyKind; use console::{style, Emoji}; -use fuzzy_matcher::skim::SkimMatcherV2; use itertools::Itertools; pub mod feature; @@ -69,40 +66,6 @@ impl Dependency { self.version.to_string() } - //todo move to something in rendering - pub fn get_features_filtered_view(&self, filter: &str) -> Vec { - let features = self - .features - .iter() - .filter(|feature| feature.0 != "default"); - - if filter.is_empty() { - features - .sorted_by(|(name_a, data_a), (name_b, data_b)| { - if data_a.is_default && !data_b.is_default { - return Ordering::Less; - } - - if data_b.is_default && !data_a.is_default { - return Ordering::Greater; - } - - name_a.cmp(name_b) - }) - .map(|(name, _)| SelectorItem::from_feature(name, vec![])) - .collect() - } else { - let matcher = SkimMatcherV2::default(); - - features - .filter_map(|(name, _)| matcher.fuzzy(name, filter, true).map(|some| (name, some))) - .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) - .map(|(name, fuzzy)| (name, fuzzy.1)) - .map(|(name, indexes)| SelectorItem::from_feature(name, indexes)) - .collect() - } - } - pub fn get_feature(&self, feature_name: &str) -> Option<&FeatureData> { self.features.get(feature_name) } diff --git a/src/project/document.rs b/src/project/document.rs index 71f18cb..55133e5 100644 --- a/src/project/document.rs +++ b/src/project/document.rs @@ -3,7 +3,6 @@ use std::cmp::PartialEq; use std::fs; use color_eyre::Result; -use fuzzy_matcher::skim::SkimMatcherV2; use itertools::Itertools; use toml_edit::{Array, Formatted, InlineTable, Item, Value}; @@ -13,7 +12,6 @@ use crate::project::dependency::feature::EnabledState; use crate::project::dependency::util::{get_mut_item_from_doc, get_path}; use crate::project::package::Package; -use crate::rendering::scroll_selector::SelectorItem; use crate::util::toml_document_from_path; pub struct Document { @@ -107,30 +105,8 @@ impl Document { Ok(()) } - pub fn get_package_names_filtered_view(&self, filter: &str) -> Result> { - let packages = if filter.is_empty() { - self.packages - .iter() - .sorted_by(|package_a, package_b| package_a.name.cmp(&package_b.name)) - .map(|package| SelectorItem::from_package(package, vec![])) - .collect() - } else { - let matcher = SkimMatcherV2::default(); - - self.packages - .iter() - .filter_map(|package| { - matcher - .fuzzy(&package.name, filter, true) - .map(|fuzzy_result| (package, fuzzy_result)) - }) - .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) - .map(|(package, fuzzy)| (package, fuzzy.1)) - .map(|(package, indexes)| SelectorItem::from_package(package, indexes)) - .collect() - }; - - Ok(packages) + pub fn get_packages(&self) -> &Vec { + &self.packages } pub fn get_packages_names(&self) -> Vec { diff --git a/src/project/package.rs b/src/project/package.rs index 902f2df..44682f9 100644 --- a/src/project/package.rs +++ b/src/project/package.rs @@ -1,8 +1,5 @@ use crate::project::dependency::Dependency; -use crate::rendering::scroll_selector::SelectorItem; use color_eyre::eyre::{bail, eyre}; -use fuzzy_matcher::skim::SkimMatcherV2; -use itertools::Itertools; pub struct Package { pub dependencies: Vec, @@ -16,33 +13,6 @@ impl Package { &self.dependencies } - //todo in rendering function - pub fn get_deps_filtered_view(&self, filter: &str) -> color_eyre::Result> { - let deps = if filter.is_empty() { - self.dependencies - .iter() - .sorted_by(|dependency_a, dependency_b| dependency_a.name.cmp(&dependency_b.name)) - .map(|dependency| SelectorItem::from_dependency(dependency, vec![])) - .collect() - } else { - let matcher = SkimMatcherV2::default(); - - self.dependencies - .iter() - .filter_map(|dependency| { - matcher - .fuzzy(&dependency.get_name(), filter, true) - .map(|fuzzy_result| (dependency, fuzzy_result)) - }) - .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) - .map(|(dependency, fuzzy)| (dependency, fuzzy.1)) - .map(|(dependency, indexes)| SelectorItem::from_dependency(dependency, indexes)) - .collect() - }; - - Ok(deps) - } - pub fn get_dep(&self, name: &str) -> color_eyre::Result<&Dependency> { let dep = self.dependencies.iter().find(|dep| dep.get_name().eq(name)); diff --git a/src/rendering/display.rs b/src/rendering/display.rs index 9654a14..524397d 100644 --- a/src/rendering/display.rs +++ b/src/rendering/display.rs @@ -1,21 +1,20 @@ use crate::project::dependency::feature::EnabledState; use crate::project::document::Document; +use crate::rendering::filter_view::FilterView; use color_eyre::eyre::{Context, ContextCompat}; use color_eyre::Result; use console::{style, Emoji, Key, Term}; use std::io::Write; use std::ops::{Not, Range}; -use crate::rendering::scroll_selector::ScrollSelector; - pub struct Display { term: Term, document: Document, - package_selector: ScrollSelector, - dep_selector: ScrollSelector, - feature_selector: ScrollSelector, + package_selector: FilterView, + dep_selector: FilterView, + feature_selector: FilterView, state: DisplayState, @@ -26,15 +25,15 @@ impl Display { pub fn new(document: Document) -> Result { Ok(Display { term: Term::buffered_stdout(), - package_selector: ScrollSelector { + package_selector: FilterView { selected_index: 0, - data: document.get_package_names_filtered_view("")?, + data: FilterView::data_from_document(&document, "")?, }, - dep_selector: ScrollSelector { + dep_selector: FilterView { selected_index: 0, - data: document.get_package_by_id(0)?.get_deps_filtered_view("")?, + data: FilterView::data_from_package(document.get_package_by_id(0)?, "")?, }, - feature_selector: ScrollSelector { + feature_selector: FilterView { selected_index: 0, data: vec![], }, @@ -52,10 +51,11 @@ impl Display { self.state = DisplayState::Dep; // update selector - self.dep_selector.data = self - .document - .get_package(self.package_selector.get_selected()?.name())? - .get_deps_filtered_view("")?; + self.dep_selector.data = FilterView::data_from_package( + self.document + .get_package(self.package_selector.get_selected()?.name())?, + "", + )?; Ok(()) } @@ -85,7 +85,7 @@ impl Display { .get_dep(self.dep_selector.get_selected()?.name())?; // update selector - self.feature_selector.data = dep.get_features_filtered_view(&self.search_text); + self.feature_selector.data = FilterView::data_from_dependency(dep, &self.search_text); Ok(()) } @@ -440,15 +440,15 @@ impl Display { fn update_selected_data(&mut self) -> Result<()> { match self.state { DisplayState::Package => { - self.package_selector.data = self - .document - .get_package_names_filtered_view(&self.search_text)?; + self.package_selector.data = + FilterView::data_from_document(&self.document, &self.search_text)?; } DisplayState::Dep => { - self.dep_selector.data = self + let package = self .document - .get_package(self.package_selector.get_selected()?.name())? - .get_deps_filtered_view(&self.search_text)?; + .get_package(self.package_selector.get_selected()?.name())?; + + self.dep_selector.data = FilterView::data_from_package(package, &self.search_text)?; } DisplayState::Feature => { let dep = self @@ -456,7 +456,7 @@ impl Display { .get_package(self.package_selector.get_selected()?.name())? .get_dep(self.dep_selector.get_selected()?.name())?; - self.feature_selector.data = dep.get_features_filtered_view(&self.search_text); + self.dep_selector.data = FilterView::data_from_dependency(dep, &self.search_text); } } diff --git a/src/rendering/scroll_selector.rs b/src/rendering/filter_view/item.rs similarity index 63% rename from src/rendering/scroll_selector.rs rename to src/rendering/filter_view/item.rs index 95a68e8..8fbfb20 100644 --- a/src/rendering/scroll_selector.rs +++ b/src/rendering/filter_view/item.rs @@ -1,50 +1,14 @@ -use color_eyre::eyre::ContextCompat; -use color_eyre::Result; -use console::style; - use crate::project::dependency::Dependency; use crate::project::package::Package; use crate::rendering::search::highlight_search; +use console::style; -pub struct ScrollSelector { - pub selected_index: usize, - pub data: Vec, -} - -impl ScrollSelector { - pub fn shift(&mut self, shift: isize) { - if !self.has_data() { - self.selected_index = 0; - return; - } - - let mut selected_temp = self.selected_index as isize; - - selected_temp += self.data.len() as isize; - selected_temp += shift; - - selected_temp %= self.data.len() as isize; - - self.selected_index = selected_temp as usize; - } - - pub fn get_selected(&self) -> Result<&SelectorItem> { - self.data - .get(self.selected_index) - .context("nothing selected") - } - - pub fn has_data(&self) -> bool { - !self.data.is_empty() - } -} - -pub struct SelectorItem { +pub struct FilterViewItem { name: String, display_name: String, } -impl SelectorItem { +impl FilterViewItem { pub fn from_package(dep: &Package, highlighted_letters: Vec) -> Self { Self { name: dep.name.to_string(), diff --git a/src/rendering/filter_view/mod.rs b/src/rendering/filter_view/mod.rs new file mode 100644 index 0000000..07f7d80 --- /dev/null +++ b/src/rendering/filter_view/mod.rs @@ -0,0 +1,138 @@ +use crate::project::dependency::Dependency; +use crate::project::document::Document; +use crate::project::package::Package; +use crate::rendering::filter_view::item::FilterViewItem; +use color_eyre::eyre::ContextCompat; +use fuzzy_matcher::skim::SkimMatcherV2; +use itertools::Itertools; +use std::cmp::Ordering; + +pub mod item; + +pub struct FilterView { + pub selected_index: usize, + pub data: Vec, +} + +impl FilterView { + pub fn shift(&mut self, shift: isize) { + if !self.has_data() { + self.selected_index = 0; + return; + } + + let mut selected_temp = self.selected_index as isize; + + selected_temp += self.data.len() as isize; + selected_temp += shift; + + selected_temp %= self.data.len() as isize; + + self.selected_index = selected_temp as usize; + } + + pub fn get_selected(&self) -> color_eyre::Result<&FilterViewItem> { + self.data + .get(self.selected_index) + .context("nothing selected") + } + + pub fn has_data(&self) -> bool { + !self.data.is_empty() + } + + pub fn data_from_dependency(dependency: &Dependency, filter: &str) -> Vec { + let features = dependency + .features + .iter() + .filter(|feature| feature.0 != "default"); + + if filter.is_empty() { + features + .sorted_by(|(name_a, data_a), (name_b, data_b)| { + if data_a.is_default && !data_b.is_default { + return Ordering::Less; + } + + if data_b.is_default && !data_a.is_default { + return Ordering::Greater; + } + + name_a.cmp(name_b) + }) + .map(|(name, _)| FilterViewItem::from_feature(name, vec![])) + .collect() + } else { + let matcher = SkimMatcherV2::default(); + + features + .filter_map(|(name, _)| matcher.fuzzy(name, filter, true).map(|some| (name, some))) + .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) + .map(|(name, fuzzy)| (name, fuzzy.1)) + .map(|(name, indexes)| FilterViewItem::from_feature(name, indexes)) + .collect() + } + } + + pub fn data_from_package( + package: &Package, + filter: &str, + ) -> color_eyre::Result> { + let deps = if filter.is_empty() { + package + .dependencies + .iter() + .sorted_by(|dependency_a, dependency_b| dependency_a.name.cmp(&dependency_b.name)) + .map(|dependency| FilterViewItem::from_dependency(dependency, vec![])) + .collect() + } else { + let matcher = SkimMatcherV2::default(); + + package + .dependencies + .iter() + .filter_map(|dependency| { + matcher + .fuzzy(&dependency.get_name(), filter, true) + .map(|fuzzy_result| (dependency, fuzzy_result)) + }) + .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) + .map(|(dependency, fuzzy)| (dependency, fuzzy.1)) + .map(|(dependency, indexes)| FilterViewItem::from_dependency(dependency, indexes)) + .collect() + }; + + Ok(deps) + } + + pub fn data_from_document( + document: &Document, + filter: &str, + ) -> color_eyre::Result> { + let packages = if filter.is_empty() { + document + .get_packages() + .iter() + .sorted_by(|package_a, package_b| package_a.name.cmp(&package_b.name)) + .map(|package| FilterViewItem::from_package(package, vec![])) + .collect() + } else { + let matcher = SkimMatcherV2::default(); + + document + .get_packages() + .iter() + .filter_map(|package| { + matcher + .fuzzy(&package.name, filter, true) + .map(|fuzzy_result| (package, fuzzy_result)) + }) + .sorted_by(|(_, fuzzy_a), (_, fuzzy_b)| fuzzy_a.0.cmp(&fuzzy_b.0).reverse()) + .map(|(package, fuzzy)| (package, fuzzy.1)) + .map(|(package, indexes)| FilterViewItem::from_package(package, indexes)) + .collect() + }; + + Ok(packages) + } +} diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs index 72eab63..adb5411 100644 --- a/src/rendering/mod.rs +++ b/src/rendering/mod.rs @@ -1,3 +1,4 @@ pub mod display; -pub mod scroll_selector; pub mod search; + +pub mod filter_view; -- 2.51.2