Skip to main content

tldr_cli/commands/
structure.rs

1//! Structure command - Show code structure
2//!
3//! Extracts and displays functions, classes, and imports from source files.
4//! Auto-routes through daemon when available for ~35x speedup.
5
6use std::path::PathBuf;
7
8use anyhow::Result;
9use clap::Args;
10
11use tldr_core::types::CodeStructure;
12use tldr_core::{get_code_structure, IgnoreSpec, Language};
13
14use crate::commands::daemon_router::{params_with_path_lang, try_daemon_route};
15use crate::output::{format_structure_text, OutputFormat, OutputWriter};
16
17/// Extract code structure (functions, classes, imports)
18#[derive(Debug, Args)]
19pub struct StructureArgs {
20    /// Directory to scan (default: current directory)
21    #[arg(default_value = ".")]
22    pub path: PathBuf,
23
24    /// Programming language (auto-detected if not specified)
25    #[arg(long, short = 'l')]
26    pub lang: Option<Language>,
27
28    /// Maximum number of files to process (0 = unlimited)
29    #[arg(long, short = 'm', default_value = "0")]
30    pub max_results: usize,
31}
32
33impl StructureArgs {
34    /// Run the structure command
35    pub fn run(&self, format: OutputFormat, quiet: bool) -> Result<()> {
36        let writer = OutputWriter::new(format, quiet);
37
38        // Determine language (auto-detect from directory, default to Python)
39        let language = self
40            .lang
41            .unwrap_or_else(|| Language::from_directory(&self.path).unwrap_or(Language::Python));
42
43        // Try daemon first for cached result
44        if let Some(structure) = try_daemon_route::<CodeStructure>(
45            &self.path,
46            "structure",
47            params_with_path_lang(&self.path, Some(language.as_str())),
48        ) {
49            // Output based on format
50            if writer.is_text() {
51                let text = format_structure_text(&structure);
52                writer.write_text(&text)?;
53                return Ok(());
54            } else {
55                writer.write(&structure)?;
56                return Ok(());
57            }
58        }
59
60        // Fallback to direct compute
61        writer.progress(&format!(
62            "Extracting structure from {} ({:?})...",
63            self.path.display(),
64            language
65        ));
66
67        // Get code structure
68        let structure = get_code_structure(
69            &self.path,
70            language,
71            self.max_results,
72            Some(&IgnoreSpec::default()),
73        )?;
74
75        // Output based on format
76        if writer.is_text() {
77            let text = format_structure_text(&structure);
78            writer.write_text(&text)?;
79        } else {
80            writer.write(&structure)?;
81        }
82
83        Ok(())
84    }
85}