tldr_cli/commands/
tree.rs1use std::collections::HashSet;
7use std::path::PathBuf;
8
9use anyhow::Result;
10use clap::Args;
11
12use tldr_core::types::FileTree;
13use tldr_core::{get_file_tree, IgnoreSpec};
14
15use crate::commands::daemon_router::{params_with_path, try_daemon_route};
16use crate::output::{format_file_tree_text, OutputFormat, OutputWriter};
17
18#[derive(Debug, Args)]
20pub struct TreeArgs {
21 #[arg(default_value = ".")]
23 pub path: PathBuf,
24
25 #[arg(long = "ext", short = 'e')]
27 pub extensions: Vec<String>,
28
29 #[arg(long, short = 'H')]
31 pub include_hidden: bool,
32}
33
34impl TreeArgs {
35 pub fn run(&self, format: OutputFormat, quiet: bool) -> Result<()> {
37 let writer = OutputWriter::new(format, quiet);
38
39 if let Some(tree) =
41 try_daemon_route::<FileTree>(&self.path, "tree", params_with_path(Some(&self.path)))
42 {
43 if writer.is_text() {
45 let text = format_file_tree_text(&tree, 0);
46 writer.write_text(&text)?;
47 return Ok(());
48 } else {
49 writer.write(&tree)?;
50 return Ok(());
51 }
52 }
53
54 let extensions: Option<HashSet<String>> = if self.extensions.is_empty() {
58 None
59 } else {
60 Some(
61 self.extensions
62 .iter()
63 .map(|s| {
64 if s.starts_with('.') {
65 s.clone()
66 } else {
67 format!(".{}", s)
68 }
69 })
70 .collect(),
71 )
72 };
73
74 let tree = get_file_tree(
76 &self.path,
77 extensions.as_ref(),
78 !self.include_hidden,
79 Some(&IgnoreSpec::default()),
80 )?;
81
82 if writer.is_text() {
84 let text = format_file_tree_text(&tree, 0);
85 writer.write_text(&text)?;
86 } else {
87 writer.write(&tree)?;
88 }
89
90 Ok(())
91 }
92}