diff options
author | Canop <cano.petrole@gmail.com> | 2020-06-28 15:33:43 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-06-28 15:33:43 +0200 |
commit | 3accec2a8ea0827b84b7014744cfe94834cc18d5 (patch) | |
tree | 33455c638391102566c2c3db8d4bed876b7cd2a7 /src | |
parent | 6ae4cc421ef3db9f6f458a023780af899313f821 (diff) |
new `cols_order` attribute in configurationv0.18.1
Allows setting the order of columns, most notably the position
of the branch (left of the tree, just before the name, or in
between).
Fix #127
Diffstat (limited to 'src')
-rw-r--r-- | src/app/context.rs | 22 | ||||
-rw-r--r-- | src/browser/browser_state.rs | 3 | ||||
-rw-r--r-- | src/cli.rs | 4 | ||||
-rw-r--r-- | src/conf/conf.rs | 6 | ||||
-rw-r--r-- | src/conf/default_conf.rs | 30 | ||||
-rw-r--r-- | src/display/col.rs | 70 | ||||
-rw-r--r-- | src/display/displayable_tree.rs | 318 | ||||
-rw-r--r-- | src/display/mod.rs | 2 | ||||
-rw-r--r-- | src/errors.rs | 3 | ||||
-rw-r--r-- | src/launchable.rs | 9 | ||||
-rw-r--r-- | src/print.rs | 8 | ||||
-rw-r--r-- | src/skin/app_skin.rs | 7 | ||||
-rw-r--r-- | src/skin/style_map.rs | 2 | ||||
-rw-r--r-- | src/tree/tree_options.rs | 4 |
14 files changed, 319 insertions, 169 deletions
diff --git a/src/app/context.rs b/src/app/context.rs index ffd9e14..d5fe915 100644 --- a/src/app/context.rs +++ b/src/app/context.rs @@ -1,6 +1,7 @@ use crate::{ cli::AppLaunchArgs, conf::Conf, + display::{Cols, DEFAULT_COLS}, pattern::SearchModeMap, tree::SpecialPath, verb::VerbStore, @@ -9,27 +10,40 @@ use crate::{ /// The immutable container that can be passed around /// to provide the configuration things pub struct AppContext { + + /// where's the config file we're using pub config_path: String, + + /// all the arguments specified at launch pub launch_args: AppLaunchArgs, + + /// the verbs in use (builtins and configured ones) pub verb_store: VerbStore, + + /// the paths for which there's a special behavior to follow (come from conf) pub special_paths: Vec<SpecialPath>, + + /// the map between search prefixes and the search mode to apply pub search_modes: SearchModeMap, + + /// order of columns in tree display + pub cols: Cols, } impl AppContext { pub fn from( launch_args: AppLaunchArgs, verb_store: VerbStore, - special_paths: Vec<SpecialPath>, - search_modes: SearchModeMap, + config: &Conf, ) -> Self { let config_path = Conf::default_location().to_string_lossy().to_string(); Self { config_path, launch_args, verb_store, - special_paths, - search_modes, + special_paths: config.special_paths.clone(), + search_modes: config.search_modes.clone(), + cols: config.cols_order.unwrap_or(DEFAULT_COLS).clone(), } } } diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index 0da7406..dab6c85 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -698,11 +698,12 @@ impl AppState for BrowserState { _screen: &Screen, area: Area, panel_skin: &PanelSkin, - _con: &AppContext, + con: &AppContext, ) -> Result<(), ProgramError> { let dp = DisplayableTree { tree: &self.displayed_tree(), skin: &panel_skin.styles, + cols: &con.cols, area, in_app: true, }; @@ -192,9 +192,7 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> { no_style, }; - let context = AppContext::from( - launch_args, verb_store, config.special_paths.clone(), config.search_modes.clone(), - ); + let context = AppContext::from(launch_args, verb_store, &config); let mut w = display::writer(); let mut screen = Screen::new(&context, &config)?; let app = App::new(&context, &screen)?; diff --git a/src/conf/conf.rs b/src/conf/conf.rs index 573963e..a17ce6a 100644 --- a/src/conf/conf.rs +++ b/src/conf/conf.rs @@ -6,6 +6,7 @@ use { default_conf::DEFAULT_CONF_FILE, }, crate::{ + display::{Col, Cols}, errors::ConfError, keys, pattern::{SearchModeMap, SearchModeMapEntry}, @@ -34,6 +35,7 @@ pub struct Conf { pub special_paths: Vec<SpecialPath>, pub search_modes: SearchModeMap, pub disable_mouse_capture: bool, + pub cols_order: Option<Cols>, } fn string_field(value: &Value, field_name: &str) -> Option<String> { @@ -116,6 +118,10 @@ impl Conf { if let Some(mouse_capture) = bool_field(&root, "capture_mouse") { self.disable_mouse_capture = !mouse_capture; } + // cols order + self.cols_order = string_field(&root, "cols_order") + .map(|s| Col::parse_cols(&s)) + .transpose()?; // reading verbs if let Some(Value::Array(verbs_value)) = &root.get("verbs") { for verb_value in verbs_value.iter() { diff --git a/src/conf/default_conf.rs b/src/conf/default_conf.rs index e24eff5..21d6c83 100644 --- a/src/conf/default_conf.rs +++ b/src/conf/default_conf.rs @@ -28,14 +28,6 @@ pub const DEFAULT_CONF_FILE: &str = r#" default_flags = "" ############################################################### -# Date/Time format -# If you want to change the format for date/time, uncomment the -# following line and change it according to -# https://docs.rs/chrono/0.4.11/chrono/format/strftime/index.html -# -# date_time_format = "%Y/%m/%d %R " - -############################################################### # Special paths # If some paths must be handled specially, uncomment (and change # this section as per the examples @@ -46,6 +38,28 @@ default_flags = "" # "/home/dys/my-link-I-want-to-explore" = "enter" ############################################################### +# Date/Time format +# If you want to change the format for date/time, uncomment the +# following line and change it according to +# https://docs.rs/chrono/0.4.11/chrono/format/strftime/index.html +# +# date_time_format = "%Y/%m/%d %R" + +############################################################### +# Column order +# cols_order, if specified, must be a permutation of "gbpdscn" +# where every char denotes a column: +# g : Git file info +# b : branch (shows the depth and parent in the tree) +# p : permissions (mode, user, group) +# d : last modification date +# s : size (with size bar when sorting) +# c : count, number of files in directories +# n : file name +# +# cols_order = "gbdscn" + +############################################################### # Verbs and shortcuts # You can define your own commands which would be applied to # the selection. diff --git a/src/display/col.rs b/src/display/col.rs new file mode 100644 index 0000000..df4957d --- /dev/null +++ b/src/display/col.rs @@ -0,0 +1,70 @@ +use { + crate::{ + errors::ConfError, + }, +}; + +// number of columns in enum +const COLS_COUNT: usize = 7; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Col { + Git, + Branch, + Permission, + Date, + Size, // includes the size bar in sort mode + Count, + Name, // name or subpath, depending on sort +} +impl Col { + pub fn parse(c: char) -> Result<Self, ConfError> { + Ok(match c { + 'g' => Self::Git, + 'b' => Self::Branch, + 'd' => Self::Date, + 's' => Self::Size, + 'c' => Self::Count, + 'n' => Self::Name, + _ => Err(ConfError::InvalidCols { details: format!("column not recognized : {}", c) })?, + }) + } + pub fn index_in(self, cols: &Cols) -> Option<usize> { + for (idx, col) in cols.iter().enumerate() { + if *col==self { + return Some(idx); + } + } + None + } + /// return a Cols which tries to take the s setting into account + /// but is guaranteed to have every Col exactly once. + pub fn parse_cols(s: &str) -> Result<Cols, ConfError> { + let mut cols = DEFAULT_COLS.clone(); + for (idx, c) in s.chars().enumerate() { + if idx >= COLS_COUNT { + return Err(ConfError::InvalidCols { details: format!("too long: {:?}", s) }); + } + // we swap the cols, to ensure both keeps being present + let col = Col::parse(c)?; + let dest_idx = col.index_in(&cols).unwrap(); // can't be none by construct + cols[dest_idx] = cols[idx]; + cols[idx] = col; + } + Ok(cols) + } +} + +pub type Cols = [Col;COLS_COUNT]; + +/// Default column order +pub static DEFAULT_COLS: Cols = [ + Col::Git, + Col::Size, + Col::Count, + Col::Permission, + Col::Date, + Col::Branch, + Col::Name, +]; + diff --git a/src/display/displayable_tree.rs b/src/display/displayable_tree.rs index 99ae99d..8b71183 100644 --- a/src/display/displayable_tree.rs +++ b/src/display/displayable_tree.rs @@ -1,5 +1,7 @@ use { super::{ + Col, + Cols, CropWriter, GitStatusDisplay, MatchedString, @@ -40,14 +42,21 @@ 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, } impl<'s, 't> DisplayableTree<'s, 't> { - pub fn out_of_app(tree: &'t Tree, skin: &'s StyleMap, width: u16) -> DisplayableTree<'s, 't> { + pub fn out_of_app( + tree: &'t Tree, + skin: &'s StyleMap, + cols: &'s Cols, + width: u16, + ) -> DisplayableTree<'s, 't> { DisplayableTree { tree, skin, + cols, area: termimad::Area { left: 0, top: 0, @@ -73,113 +82,102 @@ impl<'s, 't> DisplayableTree<'s, 't> { } } - fn write_line_count<'w, W>( + fn write_line_count<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, line: &TreeLine, selected: bool, - ) -> Result<(), termimad::Error> - where - W: Write, - { - if let Some(s) = line.sum { + ) -> Result<usize, termimad::Error> { + Ok(if let Some(s) = line.sum { cond_bg!(count_style, self, selected, self.skin.count); cw.queue_string(&count_style, format!("{:>8}", s.to_count()))?; - cw.queue_char(&self.skin.default, ' ') + 1 } else { - cw.queue_str(&self.skin.tree, "─────────") - } + 9 + }) } - fn write_line_size<'w, W>( + fn write_line_size<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, line: &TreeLine, selected: bool, - ) -> Result<(), termimad::Error> - where - W: Write, - { - if let Some(s) = line.sum { + ) -> Result<usize, termimad::Error> { + Ok(if let Some(s) = line.sum { cond_bg!(size_style, self, selected, self.name_style(&line)); - cw.queue_string(&size_style, s.to_size_string())?; - cw.queue_char(&self.skin.default, ' ') + cw.queue_string(&size_style, format!("{:>5}", s.to_size_string()))?; + 1 } else { - cw.queue_str(&self.skin.tree, "─────") - } + 6 + }) } /// only makes sense when there's only one level /// (so in sort mode) - fn write_line_size_with_bar<'w, W>( + fn write_line_size_with_bar<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, line: &TreeLine, total_size: FileSum, selected: bool, - ) -> Result<(), termimad::Error> - where - W: Write, - { - if let Some(s) = line.sum { + ) -> Result<usize, termimad::Error> { + Ok(if let Some(s) = line.sum { let pb = ProgressBar::new(s.part_of_size(total_size), 10); cond_bg!(size_style, self, selected, self.name_style(&line)); cond_bg!(sparse_style, self, selected, self.skin.sparse); cw.queue_string(&size_style, format!("{:>5}", s.to_size_string()))?; cw.queue_char(&sparse_style, if s.is_sparse() { 's' } else { ' ' })?; - cw.queue_string(&size_style, format!("{:<10} ", pb)) + cw.queue_string(&size_style, format!("{:<10}", pb))?; + 1 } else { - cw.queue_str(&self.skin.tree, "─────────────────") - } + 17 + }) } - fn write_line_git_status<'w, W>( + fn write_line_git_status<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, line: &TreeLine, - ) -> Result<(), termimad::Error> - where - W: Write, - { + selected: bool, + ) -> Result<usize, termimad::Error> { + let (style, char) = if !line.is_selectable() { - cw.queue_char(&self.skin.tree, ' ') + (&self.skin.tree, ' ') } else { match line.git_status.map(|s| s.status) { - Some(Status::CURRENT) => cw.queue_char(&self.skin.git_status_current, ' '), - Some(Status::WT_NEW) => cw.queue_char(&self.skin.git_status_new, 'N'), - Some(Status::CONFLICTED) => cw.queue_char(&self.skin.git_status_conflicted, 'C'), - Some(Status::WT_MODIFIED) => cw.queue_char(&self.skin.git_status_modified, 'M'), - Some(Status::IGNORED) => cw.queue_char(&self.skin.git_status_ignored, 'I'), - None => cw.queue_char(&self.skin.tree, ' '), - _ => cw.queue_char(&self.skin.git_status_other, '?'), + Some(Status::CURRENT) => (&self.skin.git_status_current, ' '), + Some(Status::WT_NEW) => (&self.skin.git_status_new, 'N'), + Some(Status::CONFLICTED) => (&self.skin.git_status_conflicted, 'C'), + Some(Status::WT_MODIFIED) => (&self.skin.git_status_modified, 'M'), + Some(Status::IGNORED) => (&self.skin.git_status_ignored, 'I'), + None => (&self.skin.tree, ' '), + _ => (&self.skin.git_status_other, '?'), } - } + }; + cond_bg!(git_style, self, selected, style); + cw.queue_char(git_style, char)?; + Ok(0) } - fn write_date<'w, W>( + fn write_date<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, seconds: i64, selected: bool, - ) -> Result<(), termimad::Error> - where - W: Write, - { + ) -> Result<usize, termimad::Error> { let date_time: DateTime<Local> = Local.timestamp(seconds, 0); cond_bg!(date_style, self, selected, self.skin.dates); - cw.queue_string(date_style, date_time.format(self.tree.options.date_time_format).to_string()) + cw.queue_string(date_style, date_time.format(self.tree.options.date_time_format).to_string())?; + Ok(1) } #[cfg(unix)] - fn write_mode<'w, W>( + fn write_mode<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, mode: Mode, selected: bool, - ) -> Result<(), termimad::Error> - where - W: Write, - { + ) -> Result<(), termimad::Error> { cond_bg!(n_style, self, selected, self.skin.perm__); cond_bg!(r_style, self, selected, self.skin.perm_r); cond_bg!(w_style, self, selected, self.skin.perm_w); @@ -236,18 +234,71 @@ impl<'s, 't> DisplayableTree<'s, 't> { Ok(()) } + #[cfg(unix)] + fn write_permissions<'w, W: Write>( + &self, + cw: &mut CropWriter<'w, W>, + line: &TreeLine, + user_group_max_lengths: (usize, usize), + selected: bool, + ) -> Result<usize, ProgramError> { + Ok(if line.is_selectable() { + self.write_mode(cw, line.mode(), selected)?; + let owner = permissions::user_name(line.metadata.uid()); + cond_bg!(owner_style, self, selected, self.skin.owner); + cw.queue_string( + &owner_style, + format!(" {:w$}", &owner, w = user_group_max_lengths.0), + )?; + let group = permissions::group_name(line.metadata.gid()); + cond_bg!(group_style, self, selected, self.skin.group); + cw.queue_string( + &group_style, + format!(" {:w$}", &group, w = user_group_max_lengths.1), + )?; + 1 + } else { + 9 + 1 + user_group_max_lengths.0 + 1 + user_group_max_lengths.1 + 1 + }) + } + + fn write_branch<'w, W: Write>( + &self, + cw: &mut CropWriter<'w, W>, + line_index: usize, + line: &TreeLine, + selected: bool, + ) -> Result<usize, ProgramError> { + cond_bg!(branch_style, self, selected, self.skin.tree); + for depth in 0..line.depth { + cw.queue_str( + &branch_style, + if line.left_branchs[depth as usize] { + if self.tree.has_branch(line_index + 1, depth as usize) { + if depth == line.depth - 1 { + "├──" + } else { + "│ " + } + } else { + "└──" + } + } else { + " " + }, + )?; + } + Ok(0) + } /// write the name or subpath, depending on the pattern_object - fn write_line_label<'w, W>( + fn write_line_label<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, line: &TreeLine, pattern_object: PatternObject, selected: bool, - ) -> Result<(), ProgramError> - where - W: Write, - { + ) -> Result<usize, ProgramError> { let style = match &line.line_type { TreeLineType::Dir => &self.skin.directory, TreeLineType::File => { @@ -297,18 +348,15 @@ impl<'s, 't> DisplayableTree<'s, 't> { } _ => {} } - Ok(()) + Ok(1) } - fn write_content_extract<'w, W>( + fn write_content_extract<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, extract: ContentMatch, selected: bool, - ) -> Result<(), ProgramError> - where - W: Write, - { + ) -> Result<(), ProgramError> { cond_bg!(extract_style, self, selected, self.skin.content_extract); cond_bg!(match_style, self, selected, self.skin.content_match); cw.queue_str(&extract_style, " ")?; @@ -322,14 +370,11 @@ impl<'s, 't> DisplayableTree<'s, 't> { Ok(()) } - pub fn write_root_line<'w, W>( + pub fn write_root_line<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, selected: bool, - ) -> Result<(), ProgramError> - where - W: Write, - { + ) -> Result<(), ProgramError> { cond_bg!(style, self, selected, self.skin.directory); let title = self.tree.lines[0].path.to_string_lossy(); cw.queue_str(&style, &title)?; @@ -351,14 +396,11 @@ impl<'s, 't> DisplayableTree<'s, 't> { } /// if in app, extend the background till the end of screen row - pub fn extend_line_bg<'w, W>( + pub fn extend_line_bg<'w, W: Write>( &self, cw: &mut CropWriter<'w, W>, selected: bool, - ) -> Result<(), ProgramError> - where - W: Write, - { + ) -> Result<(), ProgramError> { if self.in_app { if selected { cw.queue_bg(&self.skin.selected_line)?; @@ -371,10 +413,7 @@ impl<'s, 't> DisplayableTree<'s, 't> { } /// write the whole tree on the given `W` - pub fn write_on<W>(&self, f: &mut W) -> Result<(), ProgramError> - where - W: Write, - { + pub fn write_on<W: Write>(&self, f: &mut W) -> Result<(), ProgramError> { let tree = self.tree; #[cfg(unix)] let user_group_max_lengths = user_group_max_lengths(&tree); @@ -392,6 +431,15 @@ impl<'s, 't> DisplayableTree<'s, 't> { let pattern_object = tree.options.pattern.pattern.object(); self.write_root_line(&mut cw, tree.selection == 0)?; f.queue(SetBackgroundColor(Color::Reset))?; + + // 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(); + date_time.format(tree.options.date_time_format).to_string().len() + } else { + 0 // we don't care + }; + for y in 1..self.area.height { if self.in_app { f.queue(cursor::MoveTo(self.area.left, y + self.area.top))?; @@ -408,72 +456,66 @@ impl<'s, 't> DisplayableTree<'s, 't> { if line_index < tree.lines.len() { let line = &tree.lines[line_index]; selected = self.in_app && line_index == tree.selection; - if !tree.git_status.is_none() { - self.write_line_git_status(cw, line)?; - } - for depth in 0..line.depth { - cw.queue_str( - &self.skin.tree, - if line.left_branchs[depth as usize] { - if self.tree.has_branch(line_index + 1, depth as usize) { - if depth == line.depth - 1 { - "├──" - } else { - "│ " - } + let mut in_branch = false; + for col in self.cols { + let void_len = match col { + + Col::Git if !tree.git_status.is_none() => { + self.write_line_git_status(cw, line, selected)? + } + + Col::Branch => { + in_branch = true; + self.write_branch(cw, line_index, line, selected)? + } + + #[cfg(unix)] + Col::Permission if tree.options.show_permissions => { + self.write_permissions(cw, line, user_group_max_lengths, selected)? + } + + Col::Date if tree.options.show_dates => { + if let Some(seconds) = line.sum.and_then(|sum| sum.to_valid_seconds()) { + self.write_date(cw, seconds, selected)? } else { - "└──" + date_len + 1 } - } else { - " " - }, - )?; - } - #[cfg(unix)] - { - if tree.options.show_permissions { - if line.is_selectable() { - self.write_mode(cw, line.mode(), selected)?; - let owner = permissions::user_name(line.metadata.uid()); - cond_bg!(owner_style, self, selected, self.skin.owner); - cw.queue_string( - &owner_style, - format!(" {:w$}", &owner, w = user_group_max_lengths.0,), - )?; - let group = permissions::group_name(line.metadata.gid()); - cond_bg!(group_style, self, selected, self.skin.group); - cw.queue_string( - &group_style, - format!(" {:w$} ", &group, w = user_group_max_lengths.1,), - )?; - } else { - let length = - 9 + 1 + user_group_max_lengths.0 + 1 + user_group_max_lengths.1 + 1; - for _ in 0..length { - cw.queue_char(&self.skin.tree, '─')?; + } + + Col::Size if tree.options.show_sizes => { + 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, total_size, selected)? + } else { + self.write_line_size(cw, line, selected)? } } - } - } - if tree.options.show_dates { - if let Some(seconds) = line.sum.and_then(|sum| sum.to_valid_seconds()) { - self.write_date(cw, seconds, selected)?; - } else { - cw.queue_str(&self.skin.tree, "─────────────────")?; - } - } - if tree.options.show_sizes { - 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, total_size, selected)?; + + Col::Count if tree.options.show_counts => { + self.write_line_count(cw, line, selected)? + } + + Col::Name => { + in_branch = false; + self.write_line_label(cw, line, pattern_object, selected)? + } + + _ => { + 0 // we don't write the intercol + } + }; + // void: intercol & replacing missing cells + let (void_base_style, void_char) = if in_branch && void_len > 2 { + (&self.skin.tree, '─') } else { - self.write_line_size(cw, line, selected)?; + (&self.skin.default, ' ') + }; + cond_bg!(void_style, self, selected, void_base_style); + for _ in 0..void_len { + cw.queue_char(void_style, void_char)?; } } - if tree.options.show_counts { - self.write_line_count(cw, line, selected)?; - } - self.write_line_label(cw, line, pattern_object, selected)?; + if cw.allowed > 8 && pattern_object.content { let extract = tree.options.pattern.pattern.search_content(&line.path, cw.allowed - 2); if let Some(extract) = extract { diff --git a/src/display/mod.rs b/src/display/mod.rs index f073a73..97424ca 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -21,6 +21,7 @@ macro_rules! cond_bg { } mod areas; +mod col; mod crop_writer; mod displayable_tree; mod flags_display; @@ -33,6 +34,7 @@ use std::io::BufWriter; pub use { areas::Areas, + col::{Col, Cols, DEFAULT_COLS}, crop_writer::CropWriter, displayable_tree::DisplayableTree, flags_display::write_flags, diff --git a/src/errors.rs b/src/errors.rs index 37bcb8e..640fb0e 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -38,7 +38,8 @@ custom_error! {pub ConfError InvalidSearchMode {details: String} = "invalid search mode: {}", InvalidKey {raw: String} = "not a valid key: {}", ReservedKey {key: String} = "reserved key: {}", - UnexpectedInternalArg { invocation: String} = "unexpected argument for internal: {}", + UnexpectedInternalArg {invocation: String} = "unexpected argument for internal: {}", + InvalidCols {details: String} = "invalid cols definition: {}", } // error which can be raised when parsing a pattern the user typed diff --git a/src/launchable.rs b/src/launchable.rs index 6c99796..0c81b22 100644 --- a/src/launchable.rs +++ b/src/launchable.rs @@ -1,6 +1,6 @@ use { crate::{ - display::{DisplayableTree, Screen, W}, + display::{Cols, DisplayableTree, Screen, W}, errors::ProgramError, skin::StyleMap, tree::Tree, @@ -30,6 +30,7 @@ pub enum Launchable { // print the tree on end of broot tree: Box<Tree>, skin: Box<StyleMap>, + cols: Cols, width: u16, }, Program { @@ -70,10 +71,12 @@ impl Launchable { tree: &Tree, screen: &Screen, style_map: StyleMap, + cols: Cols, ) -> Launchable { Launchable::TreePrinter { tree: Box::new(tree.clone()), skin: Box::new(style_map), + cols, width: screen.width, } } @@ -95,8 +98,8 @@ impl Launchable { println!("{}", to_print); Ok(()) } - Launchable::TreePrinter { tree, skin, width } => { - let dp = DisplayableTree::out_of_app(&tree, &skin, *width); + Launchable::TreePrinter { tree, skin, cols, width } => { + let dp = DisplayableTree::out_of_app(&tree, &skin, &cols, *width); dp.write_on(&mut std::io::stdout()) } Launchable::Program { exe, args } => { diff --git a/src/print.rs b/src/print.rs index ea5552e..04b3352 100644 --- a/src/print.rs +++ b/src/print.rs @@ -3,7 +3,7 @@ use { crate::{ app::{AppContext, AppStateCmdResult}, - display::{DisplayableTree, Screen}, + display::{Cols, DisplayableTree, Screen}, errors::ProgramError, launchable::Launchable, skin::{PanelSkin, StyleMap}, @@ -56,9 +56,10 @@ fn print_tree_to_file( tree: &Tree, screen: &mut Screen, file_path: &str, + cols: &Cols, ) -> Result<AppStateCmdResult, ProgramError> { let no_style_skin = StyleMap::no_term(); - let dp = DisplayableTree::out_of_app(tree, &no_style_skin, screen.width); + let dp = DisplayableTree::out_of_app(tree, &no_style_skin, cols, screen.width); let mut f = OpenOptions::new() .create(true) .append(true) @@ -75,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) + print_tree_to_file(tree, screen, output_path, &con.cols) } else { // no output path provided. We write on stdout, but we must // do it after app closing to have the normal terminal @@ -88,6 +89,7 @@ pub fn print_tree( tree, screen, styles, + con.cols.clone(), ))) } } diff --git a/src/skin/app_skin.rs b/src/skin/app_skin.rs index 6196e1e..a0f85c4 100644 --- a/src/skin/app_skin.rs +++ b/src/skin/app_skin.rs @@ -15,18 +15,15 @@ pub struct AppSkin { /// the skin used in unfocused panels pub unfocused: PanelSkin, - } impl AppSkin { pub fn new(conf: &Conf) -> Self { let StyleMaps { focused, unfocused } = StyleMaps::create(&conf.skin); - let focused = PanelS |