use std::path::PathBuf;
use clap::Args;
use eyre::Result;
use itertools::Itertools;
use lux_lib::{config::Config, operations::Exec, workspace::Workspace};
use path_slash::PathExt;
use crate::utils::path::{classify_path, PathTarget};
use crate::workspace::top_level_ignored_files;
#[derive(Args)]
pub struct Lint {
path: Option<PathBuf>,
args: Option<Vec<String>>,
#[arg(long)]
no_ignore: bool,
}
pub async fn lint(lint_args: Lint, config: Config) -> Result<()> {
let target = match lint_args.path.as_deref() {
Some(path) => classify_path(path)?,
None => match Workspace::current()? {
Some(workspace) => PathTarget::Workspace(Box::new(workspace)),
None => PathTarget::Directory(std::env::current_dir()?),
},
};
let (target_path, workspace) = match target {
PathTarget::Workspace(ws) => (ws.root().to_slash_lossy().to_string(), Some(*ws)),
PathTarget::Directory(dir) => {
let ws = Workspace::from(&dir)?;
(dir.to_slash_lossy().to_string(), ws)
}
PathTarget::File(file) => {
let ws = match file.parent() {
Some(parent) => Workspace::from(parent)?,
None => None,
};
(file.to_slash_lossy().to_string(), ws)
}
};
let check_args: Vec<String> = match lint_args.args {
Some(args) => args,
None if lint_args.no_ignore => Vec::new(),
None => {
let ignored_files = workspace.iter().flat_map(|workspace| {
top_level_ignored_files(workspace)
.into_iter()
.map(|file| file.to_slash_lossy().to_string())
});
std::iter::once("--exclude-files".into())
.chain(ignored_files)
.collect_vec()
}
};
Exec::new("luacheck", None, &config)
.arg(target_path)
.args(check_args)
.disable_loader(true)
.exec()
.await?;
Ok(())
}