Skip to main content

torrust_linting/
cli.rs

1use anyhow::Result;
2use clap::{Parser, Subcommand};
3use tracing::{error, info, Level};
4
5use crate::linters::{
6    run_clippy_linter, run_cspell_linter, run_markdown_linter, run_rustfmt_linter, run_shellcheck_linter, run_toml_linter,
7    run_yaml_linter,
8};
9
10/// Initialize tracing with default configuration
11pub fn init_tracing() {
12    tracing_subscriber::fmt()
13        .with_target(true)
14        .with_thread_ids(false)
15        .with_thread_names(false)
16        .with_level(true)
17        .with_max_level(Level::INFO)
18        .init();
19}
20
21/// Run the complete linter CLI application
22///
23/// This function initializes tracing, parses CLI arguments, and executes the appropriate linting commands.
24///
25/// # Errors
26///
27/// Returns an error if any linter fails or if CLI parsing fails.
28pub fn run_cli() -> Result<()> {
29    init_tracing();
30
31    let cli = Cli::parse();
32    execute_command(cli.command.as_ref())?;
33
34    Ok(())
35}
36
37#[derive(Parser)]
38#[command(name = "linter")]
39#[command(about = "Unified linting tool")]
40#[command(version)]
41pub struct Cli {
42    #[command(subcommand)]
43    pub command: Option<Commands>,
44}
45
46#[derive(Subcommand)]
47pub enum Commands {
48    /// Run markdown linter
49    #[command(alias = "md")]
50    Markdown,
51
52    /// Run YAML linter
53    Yaml,
54
55    /// Run TOML linter using Taplo
56    Toml,
57
58    /// Run `CSpell` spell checker
59    #[command(alias = "spell")]
60    Cspell,
61
62    /// Run Rust clippy linter
63    Clippy,
64
65    /// Run Rust formatter check
66    #[command(alias = "fmt")]
67    Rustfmt,
68
69    /// Run `ShellCheck` linter
70    #[command(alias = "shell")]
71    Shellcheck,
72
73    /// Run all linters
74    All,
75}
76
77/// Run all linters and collect results
78///
79/// # Errors
80///
81/// Returns an error if any linter fails.
82pub fn run_all_linters() -> Result<()> {
83    info!("Running All Linters");
84
85    let mut failed = false;
86
87    // Run markdown linter
88    match run_markdown_linter() {
89        Ok(()) => {}
90        Err(e) => {
91            error!("Markdown linting failed: {e}");
92            failed = true;
93        }
94    }
95
96    // Run YAML linter
97    match run_yaml_linter() {
98        Ok(()) => {}
99        Err(e) => {
100            error!("YAML linting failed: {e}");
101            failed = true;
102        }
103    }
104
105    // Run TOML linter
106    match run_toml_linter() {
107        Ok(()) => {}
108        Err(e) => {
109            error!("TOML linting failed: {e}");
110            failed = true;
111        }
112    }
113
114    // Run CSpell spell checker
115    match run_cspell_linter() {
116        Ok(()) => {}
117        Err(e) => {
118            error!("Spell checking failed: {e}");
119            failed = true;
120        }
121    }
122
123    // Run Rust clippy linter
124    match run_clippy_linter() {
125        Ok(()) => {}
126        Err(e) => {
127            error!("Rust clippy linting failed: {e}");
128            failed = true;
129        }
130    }
131
132    // Run Rust formatter check
133    match run_rustfmt_linter() {
134        Ok(()) => {}
135        Err(e) => {
136            error!("Rust formatting failed: {e}");
137            failed = true;
138        }
139    }
140
141    // Run ShellCheck linter
142    match run_shellcheck_linter() {
143        Ok(()) => {}
144        Err(e) => {
145            error!("Shell script linting failed: {e}");
146            failed = true;
147        }
148    }
149
150    if failed {
151        error!("Some linters failed");
152        return Err(anyhow::anyhow!("Some linters failed"));
153    }
154    info!("All linters passed");
155    Ok(())
156}
157
158/// Execute the linting command
159///
160/// # Errors
161///
162/// Returns an error if any linter fails.
163pub fn execute_command(command: Option<&Commands>) -> Result<()> {
164    match command {
165        Some(Commands::Markdown) => {
166            run_markdown_linter()?;
167        }
168        Some(Commands::Yaml) => {
169            run_yaml_linter()?;
170        }
171        Some(Commands::Toml) => {
172            run_toml_linter()?;
173        }
174        Some(Commands::Cspell) => {
175            run_cspell_linter()?;
176        }
177        Some(Commands::Clippy) => {
178            run_clippy_linter()?;
179        }
180        Some(Commands::Rustfmt) => {
181            run_rustfmt_linter()?;
182        }
183        Some(Commands::Shellcheck) => {
184            run_shellcheck_linter()?;
185        }
186        Some(Commands::All) | None => {
187            run_all_linters()?;
188        }
189    }
190
191    Ok(())
192}