diff options
author | Canop <cano.petrole@gmail.com> | 2020-12-14 08:42:58 +0100 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-12-14 08:42:58 +0100 |
commit | 1480427fefc1f96c7b6c8aace861024d7da753a3 (patch) | |
tree | cf3320957e946321515f356b8a4a0c37feec651b | |
parent | 2c06c7ca0a580618d932325e15d8d40e7640f24d (diff) |
improve determination of whether a space is needed left of the tree
Cols order setting has been moved from context to tree options
which is both more logical and simpler to deal with.
-rw-r--r-- | src/app/context.rs | 11 | ||||
-rw-r--r-- | src/browser/browser_state.rs | 2 | ||||
-rw-r--r-- | src/cli.rs | 12 | ||||
-rw-r--r-- | src/display/col.rs | 43 | ||||
-rw-r--r-- | src/display/displayable_tree.rs | 28 | ||||
-rw-r--r-- | src/launchable.rs | 8 | ||||
-rw-r--r-- | src/print.rs | 8 | ||||
-rw-r--r-- | src/task_sync.rs | 3 | ||||
-rw-r--r-- | src/tree/tree.rs | 10 | ||||
-rw-r--r-- | src/tree/tree_options.rs | 38 |
10 files changed, 103 insertions, 60 deletions
diff --git a/src/app/context.rs b/src/app/context.rs index 67e2a2e..ac4772d 100644 --- a/src/app/context.rs +++ b/src/app/context.rs @@ -3,7 +3,6 @@ use { crate::{ cli::AppLaunchArgs, conf::Conf, - display::*, errors::ConfError, icon::*, pattern::SearchModeMap, @@ -38,9 +37,6 @@ pub struct AppContext { /// the map between search prefixes and the search mode to apply pub search_modes: SearchModeMap, - /// order of columns in tree display - pub cols: Cols, - /// whether to show a triangle left to selected lines pub show_selection_mark: bool, @@ -87,12 +83,6 @@ impl AppContext { .map(|map| map.try_into()) .transpose()? .unwrap_or_default(); - let cols = config - .cols_order - .as_ref() - .map(Cols::try_from) - .transpose()? - .unwrap_or(DEFAULT_COLS); let ext_colors = ExtColorMap::try_from(&config.ext_colors)?; Ok(Self { config_paths, @@ -100,7 +90,6 @@ impl AppContext { verb_store, special_paths, search_modes, - cols, show_selection_mark: config.show_selection_mark.unwrap_or(false), ext_colors, syntax_theme: config.syntax_theme.clone(), diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index 218ffd8..71efe55 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -523,8 +523,6 @@ impl AppState for BrowserState { let dp = DisplayableTree { tree: &self.displayed_tree(), skin: &panel_skin.styles, - cols: &con.cols, - show_selection_mark: con.show_selection_mark, ext_colors: &con.ext_colors, area, in_app: true, @@ -177,16 +177,8 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> { // found in the config file(s) (if any) then overriden // by the cli args let mut tree_options = TreeOptions::default(); - if let Some(default_flags) = &config.default_flags { - let clap_app = crate::clap::clap_app().setting(clap::AppSettings::NoBinaryName); - let flags_args = format!("-{}", default_flags); - let conf_matches = clap_app.get_matches_from(vec![&flags_args]); - tree_options.apply(&conf_matches); - } - tree_options.apply(&cli_matches); - if let Some(format) = &config.date_time_format { - tree_options.set_date_time_format(format.clone()); - } + tree_options.apply_config(&config)?; + tree_options.apply_launch_args(&cli_matches); // verb store is completed from the config file(s) let mut verb_store = VerbStore::default(); diff --git a/src/display/col.rs b/src/display/col.rs index 04edb57..270a2f2 100644 --- a/src/display/col.rs +++ b/src/display/col.rs @@ -1,5 +1,8 @@ use { - crate::errors::ConfError, + crate::{ + errors::ConfError, + tree::Tree, + }, serde::Deserialize, std::{ convert::TryFrom, @@ -38,7 +41,7 @@ pub enum Col { Name, } -pub type Cols = [Col;COLS_COUNT]; +pub type Cols = [Col; COLS_COUNT]; #[derive(Debug, Clone, Deserialize)] #[serde(untagged)] @@ -67,8 +70,8 @@ impl FromStr for Col { let s = s.to_lowercase(); match s.as_ref() { "m" | "mark" => Ok(Self::Mark), - "g" | "git" => Ok(Self::Git), - "b" | "branch" => Ok(Self::Branch), + "g" | "git" => Ok(Self::Git), + "b" | "branch" => Ok(Self::Branch), "p" | "permission" => Ok(Self::Permission), "d" | "date" => Ok(Self::Date), "s" | "size" => Ok(Self::Size), @@ -76,20 +79,48 @@ impl FromStr for Col { "n" | "name" => Ok(Self::Name), _ => Err(ConfError::InvalidCols { details: format!("column not recognized : {}", s), - }) + }), } } } impl Col { + /// return the index of the column among the complete Cols ordered list pub fn index_in(self, cols: &Cols) -> Option<usize> { for (idx, col) in cols.iter().enumerate() { - if *col==self { + if *col == self { return Some(idx); } } None } + /// tell whether this column should have an empty character left + pub fn needs_left_margin(self) -> bool { + match self { + Col::Mark => false, + Col::Git => false, + Col::Size => true, + Col::Date => true, + Col::Permission => true, + Col::Count => false, + Col::Branch => false, + Col::Name => false, + } + } + pub fn is_visible(self, tree: &Tree) -> bool { + let tree_options = &tree.options; + match self { + Col::Mark => tree_options.show_selection_mark, + Col::Git => tree.git_status.is_some(), + Col::Size => tree_options.show_sizes, + Col::Date => tree_options.show_dates, + Col::Permission => tree_options.show_permissions, + Col::Count => tree_options.show_counts, + Col::Branch => true, + Col::Name => true, + } + + } } impl TryFrom<&ColsConf> for Cols { diff --git a/src/display/displayable_tree.rs b/src/display/displayable_tree.rs index fcb1a3e..09c54d9 100644 --- a/src/display/displayable_tree.rs +++ b/src/display/displayable_tree.rs @@ -1,7 +1,6 @@ use { super::{ Col, - Cols, CropWriter, GitStatusDisplay, SPACE_FILLING, BRANCH_FILLING, @@ -40,8 +39,6 @@ pub struct DisplayableTree<'s, 't> { pub skin: &'s StyleMap, pub area: termimad::Area, pub in_app: bool, // if true we show the selection and scrollbar - pub cols: &'s Cols, - pub show_selection_mark: bool, pub ext_colors: &'s ExtColorMap, } @@ -50,15 +47,12 @@ impl<'s, 't> DisplayableTree<'s, 't> { pub fn out_of_app( tree: &'t Tree, skin: &'s StyleMap, - cols: &'s Cols, ext_colors: &'s ExtColorMap, width: u16, ) -> DisplayableTree<'s, 't> { DisplayableTree { tree, skin, - cols, - show_selection_mark: false, ext_colors, area: termimad::Area { left: 0, @@ -402,6 +396,8 @@ impl<'s, 't> DisplayableTree<'s, 't> { self.write_root_line(&mut cw, self.in_app && tree.selection == 0)?; f.queue(SetBackgroundColor(Color::Reset))?; + let visible_cols = tree.visible_cols(); + // we compute the length of the dates, depending on the format let date_len = if tree.options.show_dates { let date_time: DateTime<Local> = Local::now(); @@ -423,7 +419,6 @@ impl<'s, 't> DisplayableTree<'s, 't> { let mut selected = false; let mut cw = CropWriter::new(f, self.area.width as usize); let cw = &mut cw; - let add_left_margin = self.cols[0] != Col::Mark || !self.show_selection_mark; if line_index < tree.lines.len() { let line = &tree.lines[line_index]; selected = self.in_app && line_index == tree.selection; @@ -434,17 +429,17 @@ impl<'s, 't> DisplayableTree<'s, 't> { } else { &self.skin.default }; - if add_left_margin { + if visible_cols[0].needs_left_margin() { cw.queue_char(space_style, ' ')?; } - for col in self.cols { + for col in &visible_cols { let void_len = match col { - Col::Mark if self.show_selection_mark => { + Col::Mark => { self.write_line_selection_mark(cw, &label_style, selected)? } - Col::Git if !tree.git_status.is_none() => { + Col::Git => { self.write_line_git_status(cw, line, selected)? } @@ -454,11 +449,11 @@ impl<'s, 't> DisplayableTree<'s, 't> { } #[cfg(not(any(target_family = "windows", target_os = "android")))] - Col::Permission if tree.options.show_permissions => { + Col::Permission => { perm_writer.write_permissions(cw, line, selected)? } - Col::Date if tree.options.show_dates => { + Col::Date => { if let Some(seconds) = line.sum.and_then(|sum| sum.to_valid_seconds()) { self.write_date(cw, seconds, selected)? } else { @@ -466,7 +461,7 @@ impl<'s, 't> DisplayableTree<'s, 't> { } } - Col::Size if tree.options.show_sizes => { + Col::Size => { if tree.options.sort.is_some() { // as soon as there's only one level displayed we can show the size bars self.write_line_size_with_bar(cw, line, &label_style, total_size, selected)? @@ -475,7 +470,7 @@ impl<'s, 't> DisplayableTree<'s, 't> { } } - Col::Count if tree.options.show_counts => { + Col::Count => { self.write_line_count(cw, line, selected)? } @@ -484,9 +479,6 @@ impl<'s, 't> DisplayableTree<'s, 't> { self.write_line_label(cw, line, &label_style, pattern_object, selected)? } - _ => { - 0 // we don't write the intercol - } }; // void: intercol & replacing missing cells if in_branch && void_len > 2 { diff --git a/src/launchable.rs b/src/launchable.rs index 8794d82..b7af6c1 100644 --- a/src/launchable.rs +++ b/src/launchable.rs @@ -1,7 +1,6 @@ use { crate::{ display::{ - Cols, DisplayableTree, Screen, W, @@ -41,7 +40,6 @@ pub enum Launchable { TreePrinter { tree: Box<Tree>, skin: Box<StyleMap>, - cols: Cols, ext_colors: ExtColorMap, width: u16, }, @@ -86,13 +84,11 @@ impl Launchable { tree: &Tree, screen: Screen, style_map: StyleMap, - cols: Cols, ext_colors: ExtColorMap, ) -> Launchable { Launchable::TreePrinter { tree: Box::new(tree.clone()), skin: Box::new(style_map), - cols, ext_colors, width: screen.width, } @@ -119,8 +115,8 @@ impl Launchable { println!("{}", to_print); Ok(()) } - Launchable::TreePrinter { tree, skin, cols, ext_colors, width } => { - let dp = DisplayableTree::out_of_app(&tree, &skin, &cols, &ext_colors, *width); + Launchable::TreePrinter { tree, skin, ext_colors, width } => { + let dp = DisplayableTree::out_of_app(&tree, &skin, &ext_colors, *width); dp.write_on(&mut std::io::stdout()) } Launchable::Program { working_dir, exe, args } => { diff --git a/src/print.rs b/src/print.rs index 0409e7d..85e04b4 100644 --- a/src/print.rs +++ b/src/print.rs @@ -3,7 +3,7 @@ use { crate::{ app::{AppContext, AppStateCmdResult}, - display::{Cols, DisplayableTree, Screen}, + display::{DisplayableTree, Screen}, errors::ProgramError, launchable::Launchable, skin::{ExtColorMap, PanelSkin, StyleMap}, @@ -56,11 +56,10 @@ fn print_tree_to_file( tree: &Tree, screen: Screen, file_path: &str, - cols: &Cols, ext_colors: &ExtColorMap, ) -> Result<AppStateCmdResult, ProgramError> { let no_style_skin = StyleMap::no_term(); - let dp = DisplayableTree::out_of_app(tree, &no_style_skin, cols, ext_colors, screen.width); + let dp = DisplayableTree::out_of_app(tree, &no_style_skin, ext_colors, screen.width); let mut f = OpenOptions::new() .create(true) .append(true) @@ -77,7 +76,7 @@ pub fn print_tree( ) -> Result<AppStateCmdResult, ProgramError> { if let Some(ref output_path) = con.launch_args.file_export_path { // an output path was provided, we write to it - print_tree_to_file(tree, screen, output_path, &con.cols, &con.ext_colors) + print_tree_to_file(tree, screen, output_path, &con.ext_colors) } else { // no output path provided. We write on stdout, but we must // do it after app closing to have the normal terminal @@ -90,7 +89,6 @@ pub fn print_tree( tree, screen, styles, - con.cols, con.ext_colors.clone(), ))) } diff --git a/src/task_sync.rs b/src/task_sync.rs index 09a0900..f270e8a 100644 --- a/src/task_sync.rs +++ b/src/task_sync.rs @@ -22,6 +22,9 @@ impl<V> ComputationResult<V> { pub fn is_not_computed(&self) -> bool { matches!(&self, Self::NotComputed) } + pub fn is_some(&self) -> bool { + !matches!(&self, Self::None) + } pub fn is_none(&self) -> bool { matches!(&self, Self::None) } diff --git a/src/tree/tree.rs b/src/tree/tree.rs index 97144fc..4599296 100644 --- a/src/tree/tree.rs +++ b/src/tree/tree.rs @@ -2,6 +2,7 @@ use { super::*, crate::{ app::AppContext, + display::Col, errors, file_sum::FileSum, git::TreeGitStatus, @@ -436,4 +437,13 @@ impl Tree { sum } } + /// compute the ordered list of columns that should be displayed + /// for current tree state and options + pub fn visible_cols(&self) -> Vec<Col> { + self.options.cols_order + .iter() + .filter(|col| col.is_visible(&self)) + .cloned() + .collect() + } } diff --git a/src/tree/tree_options.rs b/src/tree/tree_options.rs index 16f75a0..862b8f9 100644 --- a/src/tree/tree_options.rs +++ b/src/tree/tree_options.rs @@ -1,12 +1,19 @@ use { super::Sort, - crate::pattern::*, + crate::{ + conf::Conf, + display::{Cols, DEFAULT_COLS}, + errors::ConfError, + pattern::*, + }, clap::ArgMatches, + std::convert::TryFrom, }; /// Options defining how the tree should be build and|or displayed #[derive(Debug, Clone)] pub struct TreeOptions { + pub show_selection_mark: bool, // whether to have a triangle left of selected line pub show_hidden: bool, // whether files whose name starts with a dot should be shown pub only_folders: bool, // whether to hide normal files and links pub show_counts: bool, // whether to show the number of files (> 1 only for dirs) @@ -21,12 +28,14 @@ pub struct TreeOptions { pub pattern: InputPattern, // an optional filtering/scoring pattern pub date_time_format: &'static str, pub sort: Sort, + pub cols_order: Cols, // order of columns } impl TreeOptions { /// clone self but without the pattern (if any) pub fn without_pattern(&self) -> Self { TreeOptions { + show_selection_mark: self.show_selection_mark, show_hidden: self.show_hidden, only_folders: self.only_folders, show_counts: self.show_counts, @@ -41,6 +50,7 @@ impl TreeOptions { pattern: InputPattern::none(), date_time_format: self.date_time_format, sort: self.sort, + cols_order: self.cols_order, } } /// counts must be computed, either for sorting or just for display @@ -63,8 +73,30 @@ impl TreeOptions { pub fn set_date_time_format(&mut self, format: String) { self.date_time_format = Box::leak(format.into_boxed_str()); } + /// change tree options according to configuration + pub fn apply_config(&mut self, config: &Conf) -> Result<(), ConfError> { + if let Some(default_flags) = &config.default_flags { + let clap_app = crate::clap::clap_app().setting(clap::AppSettings::NoBinaryName); + let flags_args = format!("-{}", default_flags); + let conf_matches = clap_app.get_matches_from(vec![&flags_args]); + self.apply_launch_args(&conf_matches); + } + if let Some(b) = &config.show_selection_mark { + self.show_selection_mark = *b; + } + if let Some(format) = &config.date_time_format { + self.set_date_time_format(format.clone()); + } + self.cols_order = config + .cols_order + .as_ref() + .map(Cols::try_from) + .transpose()? + .unwrap_or(DEFAULT_COLS); + Ok(()) + } /// change tree options according to broot launch arguments - pub fn apply(&mut self, cli_args: &ArgMatches<'_>) { + pub fn apply_launch_args(&mut self, cli_args: &ArgMatches<'_>) { if cli_args.is_present("sizes") { self.show_sizes = true; self.show_root_fs = true; @@ -141,6 +173,7 @@ impl TreeOptions { impl Default for TreeOptions { fn default() -> Self { Self { + show_selection_mark: false, show_hidden: false, only_folders: false, show_counts: false, @@ -155,6 +188,7 @@ impl Default for TreeOptions { pattern: InputPattern::none(), date_time_format: "%Y/%m/%d %R", sort: Sort::None, + cols_order: DEFAULT_COLS, } } } |