-
-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7e398a6
commit c593044
Showing
6 changed files
with
279 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,11 +47,10 @@ mod test; | |
|
||
/// Defines the CLI. | ||
#[derive(Parser, Debug)] | ||
#[command(name = env!("CARGO_PKG_NAME", "The Package Name is missing!"))] | ||
#[command(author = env!("CARGO_PKG_AUTHORS", "The Author of the Package is missing!"))] | ||
#[command(version = env!("CARGO_PKG_VERSION_MAJOR", "The Package version is missing!"))] | ||
#[command(about = "erdtree (erd) is a cross-platform multi-threaded filesystem and disk usage analysis tool.", | ||
long_about = env!("CARGO_PKG_DESCRIPTION", "The Long Package Description is missing!"))] | ||
#[command(name = "erdtree")] | ||
#[command(author = "Benjamin Nguyen. <[email protected]>")] | ||
#[command(version = "2.0.0")] | ||
#[command(about = "erdtree (erd) is a cross-platform multi-threaded filesystem and disk usage analysis tool.", long_about = None)] | ||
pub struct Context { | ||
/// Directory to traverse; defaults to current working directory | ||
dir: Option<PathBuf>, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use crate::{ | ||
render::Engine, | ||
tree::{count::FileCount, Tree}, | ||
}; | ||
use std::fmt::{self, Display}; | ||
|
||
pub struct Flat; | ||
|
||
impl Display for Engine<Flat> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
let ctx = self.context(); | ||
let tree = self.tree(); | ||
let arena = tree.arena(); | ||
let root_id = tree.root_id(); | ||
let max_depth = ctx.level(); | ||
let mut file_count_data = vec![]; | ||
|
||
let descendants = root_id.descendants(arena); | ||
|
||
for node_id in descendants { | ||
let node = arena[node_id].get(); | ||
|
||
if node.depth() > max_depth { | ||
continue; | ||
} | ||
|
||
node.flat_display(f, ctx)?; | ||
file_count_data.push(Tree::compute_file_count(node_id, arena)); | ||
} | ||
|
||
if !file_count_data.is_empty() { | ||
write!(f, "\n{}", FileCount::from(file_count_data))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use crate::{ | ||
render::{Engine, theme}, | ||
styles, | ||
tree::{count::FileCount, node::Node, Tree}, | ||
}; | ||
use indextree::NodeId; | ||
use std::fmt::{self, Display}; | ||
|
||
pub struct Inverted; | ||
|
||
impl Display for Engine<Inverted> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
let ctx = self.context(); | ||
let tree = self.tree(); | ||
|
||
let root_id = tree.root_id(); | ||
let arena = tree.arena(); | ||
let level = ctx.level(); | ||
let mut file_count_data = vec![]; | ||
|
||
let mut descendants = root_id.descendants(arena).skip(1).peekable(); | ||
|
||
let mut display_node = |node_id: NodeId, node: &Node, prefix: &str| -> fmt::Result { | ||
node.tree_display(f, prefix, ctx)?; | ||
file_count_data.push(Tree::compute_file_count(node_id, arena)); | ||
writeln!(f) | ||
}; | ||
|
||
display_node(root_id, arena[root_id].get(), "")?; | ||
|
||
let mut get_theme = if ctx.follow { | ||
theme::link_theme_getter() | ||
} else { | ||
theme::regular_theme_getter() | ||
}; | ||
|
||
let mut base_prefix_components = vec![""]; | ||
|
||
while let Some(current_node_id) = descendants.next() { | ||
let current_node = arena[current_node_id].get(); | ||
|
||
let current_depth = current_node.depth(); | ||
|
||
let mut siblings = current_node_id.following_siblings(arena).skip(1).peekable(); | ||
|
||
let last_sibling = siblings.peek().is_none(); | ||
|
||
let theme = get_theme(current_node); | ||
|
||
if current_depth <= level { | ||
let prefix_part = if last_sibling { | ||
theme.get("uprt").unwrap() | ||
} else { | ||
theme.get("vtrt").unwrap() | ||
}; | ||
|
||
let mut current_prefix_components = base_prefix_components.clone(); | ||
|
||
current_prefix_components.push(prefix_part); | ||
|
||
let prefix = current_prefix_components.join(""); | ||
|
||
display_node(current_node_id, current_node, &prefix)?; | ||
} | ||
|
||
if let Some(next_id) = descendants.peek() { | ||
let next_node = arena[*next_id].get(); | ||
|
||
let next_depth = next_node.depth(); | ||
|
||
if next_depth == current_depth + 1 { | ||
if last_sibling { | ||
base_prefix_components.push(styles::SEP); | ||
} else { | ||
let prefix = theme.get("vt").unwrap(); | ||
base_prefix_components.push(prefix); | ||
} | ||
} else if next_depth < current_depth { | ||
let depth_delta = current_depth - next_depth; | ||
|
||
base_prefix_components.truncate(base_prefix_components.len() - depth_delta); | ||
} | ||
} | ||
} | ||
|
||
if !file_count_data.is_empty() { | ||
write!(f, "\n{}", FileCount::from(file_count_data))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub mod regular; | ||
|
||
pub mod flat; | ||
|
||
pub mod inverted; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use crate::{ | ||
render::{Engine, theme}, | ||
styles, | ||
tree::{count::FileCount, node::Node, Tree}, | ||
}; | ||
use indextree::{NodeEdge, NodeId}; | ||
use std::fmt::{self, Display}; | ||
|
||
pub struct Regular; | ||
|
||
impl Display for Engine<Regular> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
let ctx = self.context(); | ||
let tree = self.tree(); | ||
let root_id = tree.root_id(); | ||
let arena = tree.arena(); | ||
let max_depth = ctx.level(); | ||
let mut file_count_data = vec![]; | ||
|
||
let mut display_node = |node_id: NodeId, node: &Node, prefix: &str| -> fmt::Result { | ||
node.tree_display(f, prefix, ctx)?; | ||
file_count_data.push(Tree::compute_file_count(node_id, arena)); | ||
writeln!(f) | ||
}; | ||
|
||
let mut get_theme = if ctx.follow { | ||
theme::link_theme_getter() | ||
} else { | ||
theme::regular_theme_getter() | ||
}; | ||
|
||
let mut base_prefix_components = vec![""]; | ||
|
||
let mut tree_edges = root_id.reverse_traverse(arena).skip(1).peekable(); | ||
|
||
while let Some(node_edge) = tree_edges.next() { | ||
let current_node_id = match node_edge { | ||
NodeEdge::Start(id) => id, | ||
|
||
NodeEdge::End(id) => { | ||
let current_node = arena[id].get(); | ||
|
||
if !current_node.is_dir() || id.children(arena).count() == 0 { | ||
continue; | ||
} | ||
|
||
let theme = get_theme(current_node); | ||
|
||
let topmost_sibling = id.following_siblings(arena).nth(1).is_none(); | ||
|
||
if topmost_sibling { | ||
base_prefix_components.push(styles::SEP); | ||
} else { | ||
base_prefix_components.push(theme.get("vt").unwrap()); | ||
} | ||
|
||
continue; | ||
} | ||
}; | ||
|
||
let current_node = arena[current_node_id].get(); | ||
|
||
let node_depth = current_node.depth(); | ||
|
||
let topmost_sibling = current_node_id.following_siblings(arena).nth(1).is_none(); | ||
|
||
let theme = get_theme(current_node); | ||
|
||
if node_depth <= max_depth { | ||
if node_depth == 0 { | ||
display_node(current_node_id, current_node, "")?; | ||
} else { | ||
let prefix_part = if topmost_sibling { | ||
theme.get("drt").unwrap() | ||
} else { | ||
theme.get("vtrt").unwrap() | ||
}; | ||
|
||
let mut current_prefix_components = base_prefix_components.clone(); | ||
|
||
current_prefix_components.push(prefix_part); | ||
|
||
let prefix = current_prefix_components.join(""); | ||
|
||
display_node(current_node_id, current_node, &prefix)?; | ||
} | ||
} | ||
|
||
if let Some(NodeEdge::Start(next_id)) = tree_edges.peek() { | ||
let next_node = arena[*next_id].get(); | ||
|
||
if next_node.depth() < node_depth { | ||
base_prefix_components.pop(); | ||
} | ||
} | ||
} | ||
|
||
if !file_count_data.is_empty() { | ||
write!(f, "\n{}", FileCount::from(file_count_data))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use crate::{ | ||
styles::{self, ThemesMap}, | ||
tree::node::Node, | ||
}; | ||
|
||
type Theme = Box<dyn FnMut(&Node) -> &'static ThemesMap>; | ||
|
||
/// Returns a closure that retrieves the regular theme. | ||
pub fn regular_theme_getter() -> Theme { | ||
Box::new(|_node: &Node| styles::get_tree_theme().unwrap()) | ||
} | ||
|
||
/// Returns a closure that can smartly determine when a symlink is being followed and when it is | ||
/// not being followed. When a symlink is being followed, all of its descendents should have tree | ||
/// branches that are colored differently. | ||
pub fn link_theme_getter() -> Theme { | ||
let mut link_depth = None; | ||
|
||
Box::new(move |node: &Node| { | ||
let current_depth = node.depth(); | ||
|
||
if let Some(ldepth) = link_depth { | ||
if current_depth == ldepth { | ||
link_depth = None; | ||
} | ||
} | ||
|
||
if link_depth.is_some() || node.is_symlink() { | ||
if node.is_dir() && link_depth.is_none() { | ||
link_depth = Some(current_depth); | ||
} | ||
styles::get_link_theme().unwrap() | ||
} else { | ||
styles::get_tree_theme().unwrap() | ||
} | ||
}) | ||
} |