lux_cli/
lint.rs

1use clap::Args;
2use eyre::Result;
3use itertools::Itertools;
4use lux_lib::{
5    config::Config,
6    operations::{Exec, Install, PackageInstallSpec},
7    progress::MultiProgress,
8    project::Project,
9    tree,
10};
11use path_slash::PathBufExt;
12
13use crate::project::top_level_ignored_files;
14
15#[derive(Args)]
16pub struct Lint {
17    /// Arguments to pass to the luacheck command.{n}
18    /// If you pass arguments to luacheck, Lux will not pass any default arguments.
19    args: Option<Vec<String>>,
20    /// By default, Lux will add top-level ignored files and directories{n}
21    /// (like those in .gitignore) to luacheck's exclude files.{n}
22    /// This flag disables that behaviour.{n}
23    #[arg(long)]
24    no_ignore: bool,
25}
26
27pub async fn lint(lint_args: Lint, config: Config) -> Result<()> {
28    let project = Project::current_or_err()?;
29
30    let luacheck =
31        PackageInstallSpec::new("luacheck".parse()?, tree::EntryType::Entrypoint).build();
32
33    Install::new(&config)
34        .package(luacheck)
35        .project(&project)?
36        .progress(MultiProgress::new_arc())
37        .install()
38        .await?;
39
40    let check_args: Vec<String> = match lint_args.args {
41        Some(args) => args,
42        None if lint_args.no_ignore => Vec::new(),
43        None => {
44            let ignored_files = top_level_ignored_files(&project)
45                .into_iter()
46                .map(|file| file.to_slash_lossy().to_string());
47            std::iter::once("--exclude-files".into())
48                .chain(ignored_files)
49                .collect_vec()
50        }
51    };
52
53    Exec::new("luacheck", Some(&project), &config)
54        .arg(project.root().to_slash_lossy())
55        .args(check_args)
56        .exec()
57        .await?;
58
59    Ok(())
60}