mod analysis;
mod complete_cmd;
mod explain_cmd;
mod fix_cmd;
mod format_cmd;
mod init_cmd;
mod io;
mod lint_cmd;
mod parse_cmd;
mod render;
mod rules_cmd;
mod schema;
mod schema_cmd;
use std::path::PathBuf;
use std::process::ExitCode;
use banshee_config::BansheeConfig;
use clap::{Parser, Subcommand, ValueEnum};
pub mod exit {
pub const OK: u8 = 0;
pub const FINDINGS: u8 = 1;
pub const ERROR: u8 = 2;
}
const LONG_VERSION: &str = concat!(
env!("CARGO_PKG_VERSION"),
" (",
env!("BANSHEE_GIT_SHA"),
" ",
env!("BANSHEE_BUILD_DATE"),
")"
);
#[derive(Parser, Debug)]
#[command(name = "banshee", version = LONG_VERSION, about, long_about = None)]
pub struct Cli {
#[arg(long, global = true, value_name = "FILE")]
config: Option<PathBuf>,
#[arg(long, global = true)]
no_color: bool,
#[command(subcommand)]
command: Command,
}
impl Cli {
pub fn use_color(&self) -> bool {
render::use_color(self.no_color)
}
}
#[derive(Subcommand, Debug)]
enum Command {
Format(format_cmd::FormatArgs),
Lint(lint_cmd::LintArgs),
Fix(fix_cmd::FixArgs),
Parse(parse_cmd::ParseArgs),
Rules(rules_cmd::RulesArgs),
Schema(schema_cmd::SchemaArgs),
Init(init_cmd::InitArgs),
Explain(explain_cmd::ExplainArgs),
Complete(complete_cmd::CompleteArgs),
Lsp,
}
#[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq)]
pub enum ReportFormat {
Human,
Json,
Github,
Sarif,
}
impl Cli {
pub fn run() -> ExitCode {
let cli = Cli::parse();
let result = match &cli.command {
Command::Format(args) => format_cmd::run(args, &cli),
Command::Lint(args) => lint_cmd::run(args, &cli),
Command::Fix(args) => fix_cmd::run(args, &cli),
Command::Parse(args) => parse_cmd::run(args, &cli),
Command::Rules(args) => rules_cmd::run(args),
Command::Schema(args) => schema_cmd::run(args, &cli),
Command::Init(args) => init_cmd::run(args),
Command::Explain(args) => explain_cmd::run(args),
Command::Complete(args) => complete_cmd::run(args, &cli),
Command::Lsp => run_lsp(&cli),
};
match result {
Ok(code) => ExitCode::from(code),
Err(err) => {
eprintln!("error: {err:#}");
ExitCode::from(exit::ERROR)
}
}
}
fn load_config(&self, near: &std::path::Path) -> anyhow::Result<BansheeConfig> {
match &self.config {
Some(path) => Ok(BansheeConfig::load(path)?),
None => Ok(BansheeConfig::discover(near)?),
}
}
}
fn run_lsp(cli: &Cli) -> anyhow::Result<u8> {
let config = cli.load_config(&PathBuf::from("."))?;
let schema = schema::resolve(&config)?;
banshee_lsp::run_stdio(config, schema)?;
Ok(exit::OK)
}