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 /src | |
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.
Diffstat (limited to 'src')
-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, } } } |