From b60bab1bddc1a48335eb854dc3ff02fa7e2557cd Mon Sep 17 00:00:00 2001 From: Peltoche Date: Tue, 4 Dec 2018 14:54:56 +0100 Subject: [PATCH] Handle the --tree option --- Cargo.lock | 2 +- README.md | 2 +- src/batch.rs | 4 ++++ src/core.rs | 48 +++++++++++++++++++++++++++++++++++++++--------- src/display.rs | 23 +++++++++++++++++++++++ src/main.rs | 3 +++ 6 files changed, 71 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5656458..d2f0d99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,7 +47,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lsd" -version = "0.5.0" +version = "0.5.1-pre" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/README.md b/README.md index 7579cfd..4cd123a 100644 --- a/README.md +++ b/README.md @@ -45,5 +45,5 @@ Result from `hyperfine --warmup 10 'lsd -la /etc/*' 'colorls -la /etc/*' --expor - [x] Handle the `-a` option - [x] Add icons before the files names - [x] Handle all the file types (block/char/pipe/etc) -- [ ] Handle the tree (`--tree`) output option +- [x] Handle the tree (`--tree`) output option - [ ] Handle the json (`--json`) output option diff --git a/src/batch.rs b/src/batch.rs index c6ff3cc..b7b10d2 100644 --- a/src/batch.rs +++ b/src/batch.rs @@ -23,6 +23,10 @@ impl IntoIterator for Batch { } impl Batch { + pub fn len(&self) -> usize { + self.0.len() + } + pub fn sort(&mut self) { self.0.sort_unstable_by(sort_by_meta); } diff --git a/src/core.rs b/src/core.rs index 4312b2d..0f6bd23 100644 --- a/src/core.rs +++ b/src/core.rs @@ -6,16 +6,22 @@ use Options; pub struct Core<'a> { options: &'a Options, + display: Display<'a>, } impl<'a> Core<'a> { pub fn new(options: &'a Options) -> Core<'a> { - Core { options } + Core { + options, + display: Display::new(options), + } } - pub fn run(&self, paths: Vec) { - let display = Display::new(self.options); + pub fn run(self, paths: Vec) { + self.run_inner(paths, 0); + } + fn run_inner(&self, paths: Vec, depth: usize) { let mut dirs = Vec::new(); let mut files = Vec::new(); @@ -29,23 +35,27 @@ impl<'a> Core<'a> { let print_folder_name: bool = dirs.len() + files.len() > 1; - if !files.is_empty() { + if !files.is_empty() && !self.options.display_tree { let mut file_batch = Batch::from(files); file_batch.sort(); - display.print_outputs(self.get_batch_outputs(&file_batch)); + self.display + .print_outputs(self.get_batch_outputs(&file_batch)); } dirs.sort_unstable(); for dir in dirs { if let Some(folder_batch) = self.list_folder_content(dir.as_path()) { - if print_folder_name || self.options.recursive { + if (print_folder_name || self.options.recursive) && !self.options.display_tree { println!("\n{}:", dir.display()) } - display.print_outputs(self.get_batch_outputs(&folder_batch)); + if self.options.display_tree { + self.display_as_tree(folder_batch, depth); + } else if self.options.recursive { + self.display + .print_outputs(self.get_batch_outputs(&folder_batch)); - if self.options.recursive { let folder_dirs = folder_batch .into_iter() .filter_map(|x| { @@ -56,12 +66,32 @@ impl<'a> Core<'a> { } }).collect(); - self.run(folder_dirs); + self.run_inner(folder_dirs, depth); + } else { + self.display + .print_outputs(self.get_batch_outputs(&folder_batch)); } } } } + pub fn display_as_tree(&self, batch: Batch, depth: usize) { + let last_idx = batch.len(); + + for (idx, elem) in batch.into_iter().enumerate() { + let last = !(idx + 1 == last_idx); + + if elem.file_type == FileType::Directory { + self.display + .print_tree_row(elem.name.render().to_string(), depth, last); + self.run_inner(vec![elem.path], depth + 1); + } else { + self.display + .print_tree_row(elem.name.render().to_string(), depth, last); + } + } + } + pub fn get_batch_outputs<'b>(&self, batch: &'b Batch) -> Vec { if self.options.display_long { batch.get_long_output() diff --git a/src/display.rs b/src/display.rs index 0ce1f0f..7380e76 100644 --- a/src/display.rs +++ b/src/display.rs @@ -2,6 +2,10 @@ use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; use terminal_size::terminal_size; use Options; +const EDGE: &'static str = "├──"; +const LINE: &'static str = "│ "; +const CORNER: &'static str = "└──"; + pub struct Display<'a> { options: &'a Options, } @@ -44,6 +48,25 @@ impl<'a> Display<'a> { ); } + pub fn print_tree_row(&self, output: String, depth: usize, last: bool) { + let mut res = String::new(); + + for _ in 0..depth { + res += LINE; + } + + if last { + res += EDGE; + } else { + res += CORNER; + } + + res += " "; + res += &output; + + println!("{}", res); + } + fn print_one_per_line(&self, outputs: &[String]) { let mut res = String::new(); for output in outputs { diff --git a/src/main.rs b/src/main.rs index 41e30b0..42a72ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,6 +23,7 @@ pub struct Options { pub display_all: bool, pub display_long: bool, pub display_online: bool, + pub display_tree: bool, pub recursive: bool, } @@ -34,12 +35,14 @@ fn main() { .arg(Arg::with_name("long").short("l").long("long")) .arg(Arg::with_name("oneline").short("1").long("oneline")) .arg(Arg::with_name("recursive").short("R").long("recursive")) + .arg(Arg::with_name("tree").long("tree")) .get_matches(); let options = Options { display_all: matches.is_present("all"), display_long: matches.is_present("long"), display_online: matches.is_present("oneline"), + display_tree: matches.is_present("tree"), recursive: matches.is_present("recursive"), };