mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-12-27 18:24:57 +00:00
Encapsulate tree depth
It only really gets used for zeroes and having one added to it.
This commit is contained in:
parent
8453f45f99
commit
c0a2cf50af
@ -70,7 +70,7 @@ use options::{FileFilter, RecurseOptions};
|
||||
use output::colours::Colours;
|
||||
use output::column::Columns;
|
||||
use output::cell::TextCell;
|
||||
use output::tree::{TreeTrunk, TreeParams};
|
||||
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
|
||||
use output::file_name::{FileName, LinkStyle, Classify};
|
||||
use output::table::{Table, Environment, Row as TableRow};
|
||||
|
||||
@ -153,14 +153,14 @@ impl<'a> Render<'a> {
|
||||
// This is weird, but I can't find a way around it:
|
||||
// https://internals.rust-lang.org/t/should-option-mut-t-implement-copy/3715/6
|
||||
let mut table = Some(table);
|
||||
self.add_files_to_table(&mut table, &mut rows, &self.files, 0);
|
||||
self.add_files_to_table(&mut table, &mut rows, &self.files, TreeDepth(0));
|
||||
|
||||
for row in self.iterate_with_table(table.unwrap(), rows) {
|
||||
writeln!(w, "{}", row.strings())?
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.add_files_to_table(&mut None, &mut rows, &self.files, 0);
|
||||
self.add_files_to_table(&mut None, &mut rows, &self.files, TreeDepth(0));
|
||||
|
||||
for row in self.iterate(rows) {
|
||||
writeln!(w, "{}", row.strings())?
|
||||
@ -172,7 +172,7 @@ impl<'a> Render<'a> {
|
||||
|
||||
/// Adds files to the table, possibly recursively. This is easily
|
||||
/// parallelisable, and uses a pool of threads.
|
||||
fn add_files_to_table<'dir>(&self, table: &mut Option<Table<'a>>, rows: &mut Vec<Row>, src: &Vec<File<'dir>>, depth: usize) {
|
||||
fn add_files_to_table<'dir>(&self, table: &mut Option<Table<'a>>, rows: &mut Vec<Row>, src: &Vec<File<'dir>>, depth: TreeDepth) {
|
||||
use num_cpus;
|
||||
use scoped_threadpool::Pool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -208,7 +208,7 @@ impl<'a> Render<'a> {
|
||||
let mut dir = None;
|
||||
|
||||
if let Some(r) = self.recurse {
|
||||
if file.is_directory() && r.tree && !r.is_too_deep(depth) {
|
||||
if file.is_directory() && r.tree && !r.is_too_deep(depth.0) {
|
||||
if let Ok(d) = file.to_dir(false) {
|
||||
dir = Some(d);
|
||||
}
|
||||
@ -252,33 +252,33 @@ impl<'a> Render<'a> {
|
||||
|
||||
if !files.is_empty() {
|
||||
for xattr in egg.xattrs {
|
||||
rows.push(self.render_xattr(xattr, TreeParams::new(depth + 1, false)));
|
||||
rows.push(self.render_xattr(xattr, TreeParams::new(depth.deeper(), false)));
|
||||
}
|
||||
|
||||
for (error, path) in errors {
|
||||
rows.push(self.render_error(&error, TreeParams::new(depth + 1, false), path));
|
||||
rows.push(self.render_error(&error, TreeParams::new(depth.deeper(), false), path));
|
||||
}
|
||||
|
||||
self.add_files_to_table(table, rows, &files, depth + 1);
|
||||
self.add_files_to_table(table, rows, &files, depth.deeper());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let count = egg.xattrs.len();
|
||||
for (index, xattr) in egg.xattrs.into_iter().enumerate() {
|
||||
rows.push(self.render_xattr(xattr, TreeParams::new(depth + 1, errors.is_empty() && index == count - 1)));
|
||||
rows.push(self.render_xattr(xattr, TreeParams::new(depth.deeper(), errors.is_empty() && index == count - 1)));
|
||||
}
|
||||
|
||||
let count = errors.len();
|
||||
for (index, (error, path)) in errors.into_iter().enumerate() {
|
||||
rows.push(self.render_error(&error, TreeParams::new(depth + 1, index == count - 1), path));
|
||||
rows.push(self.render_error(&error, TreeParams::new(depth.deeper(), index == count - 1), path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_header(&self, header: TableRow) -> Row {
|
||||
Row {
|
||||
tree: TreeParams::new(0, false),
|
||||
tree: TreeParams::new(TreeDepth(0), false),
|
||||
cells: Some(header),
|
||||
name: TextCell::paint_str(self.colours.header, "Name"),
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use output::details::{Options as DetailsOptions, Row as DetailsRow, Render as De
|
||||
use output::grid::Options as GridOptions;
|
||||
use output::file_name::{FileName, LinkStyle, Classify};
|
||||
use output::table::{Table, Environment, Row as TableRow};
|
||||
use output::tree::TreeParams;
|
||||
use output::tree::{TreeParams, TreeDepth};
|
||||
|
||||
|
||||
pub struct Render<'a> {
|
||||
@ -120,7 +120,7 @@ impl<'a> Render<'a> {
|
||||
|
||||
let (ref mut table, ref mut rows) = tables[index];
|
||||
table.add_widths(&row);
|
||||
let details_row = drender.render_file(row, file_name.clone(), TreeParams::new(0, false));
|
||||
let details_row = drender.render_file(row, file_name.clone(), TreeParams::new(TreeDepth(0), false));
|
||||
rows.push(details_row);
|
||||
}
|
||||
|
||||
|
@ -88,12 +88,15 @@ pub struct TreeParams {
|
||||
|
||||
/// How many directories deep into the tree structure this is. Directories
|
||||
/// on top have depth 0.
|
||||
depth: usize,
|
||||
depth: TreeDepth,
|
||||
|
||||
/// Whether this is the last entry in the directory.
|
||||
last: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TreeDepth(pub usize);
|
||||
|
||||
impl TreeTrunk {
|
||||
|
||||
/// Calculates the tree parts for an entry at the given depth and
|
||||
@ -108,40 +111,45 @@ impl TreeTrunk {
|
||||
// If this isn’t our first iteration, then update the tree parts thus
|
||||
// far to account for there being another row after it.
|
||||
if let Some(last) = self.last_params {
|
||||
self.stack[last.depth] = if last.last { TreePart::Blank } else { TreePart::Line };
|
||||
self.stack[last.depth.0] = if last.last { TreePart::Blank } else { TreePart::Line };
|
||||
}
|
||||
|
||||
// Make sure the stack has enough space, then add or modify another
|
||||
// part into it.
|
||||
self.stack.resize(params.depth + 1, TreePart::Edge);
|
||||
self.stack[params.depth] = if params.last { TreePart::Corner } else { TreePart::Edge };
|
||||
self.stack.resize(params.depth.0 + 1, TreePart::Edge);
|
||||
self.stack[params.depth.0] = if params.last { TreePart::Corner } else { TreePart::Edge };
|
||||
self.last_params = Some(params);
|
||||
|
||||
// Return the tree parts as a slice of the stack.
|
||||
//
|
||||
// Ignoring the first component is specific to exa: when a user prints
|
||||
// a tree view for multiple directories, we don’t want there to be a
|
||||
// ‘zeroth level’ connecting the initial directories. Otherwise, not
|
||||
// only are unrelated directories seemingly connected to each other,
|
||||
// but the tree part of the first row doesn’t connect to anything:
|
||||
// Ignore the first element here to prevent a 'zeroth level' from
|
||||
// appearing before the very first directory. This level would
|
||||
// join unrelated directories without connecting to anything:
|
||||
//
|
||||
// with [0..] with [1..]
|
||||
// ========== ==========
|
||||
// ├── folder folder
|
||||
// │ └── file └── file
|
||||
// └── folder folder
|
||||
// └── file └──file
|
||||
//
|
||||
// with [0..] with [1..]
|
||||
// ========== ==========
|
||||
// ├──folder folder
|
||||
// │ └──file └──file
|
||||
// └──folder folder
|
||||
// └──file └──file
|
||||
&self.stack[1..]
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeParams {
|
||||
pub fn new(depth: usize, last: bool) -> TreeParams {
|
||||
pub fn new(depth: TreeDepth, last: bool) -> TreeParams {
|
||||
TreeParams { depth, last }
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.depth == 0
|
||||
self.depth.0 == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeDepth {
|
||||
pub fn deeper(self) -> TreeDepth {
|
||||
TreeDepth(self.0 + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,50 +158,54 @@ impl TreeParams {
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
fn params(depth: usize, last: bool) -> TreeParams {
|
||||
TreeParams::new(TreeDepth(depth), last)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_at_first() {
|
||||
let mut tt = TreeTrunk::default();
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(params(0, true)), &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_child() {
|
||||
let mut tt = TreeTrunk::default();
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_children() {
|
||||
let mut tt = TreeTrunk::default();
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_times_two_children() {
|
||||
let mut tt = TreeTrunk::default();
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, false)), &[]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(0, false)), &[]);
|
||||
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
|
||||
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_times_two_nested_children() {
|
||||
let mut tt = TreeTrunk::default();
|
||||
assert_eq!(tt.new_row(TreeParams::new(0, true)), &[]);
|
||||
assert_eq!(tt.new_row(params(0, true)), &[]);
|
||||
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(2, false)), &[ TreePart::Line, TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(2, true)), &[ TreePart::Line, TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(1, false)), &[ TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(2, false)), &[ TreePart::Line, TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(2, true)), &[ TreePart::Line, TreePart::Corner ]);
|
||||
|
||||
assert_eq!(tt.new_row(TreeParams::new(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(2, false)), &[ TreePart::Blank, TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(TreeParams::new(2, true)), &[ TreePart::Blank, TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(1, true)), &[ TreePart::Corner ]);
|
||||
assert_eq!(tt.new_row(params(2, false)), &[ TreePart::Blank, TreePart::Edge ]);
|
||||
assert_eq!(tt.new_row(params(2, true)), &[ TreePart::Blank, TreePart::Corner ]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user