mod commands;
mod error;
mod input;
mod output;
use clap::{Parser, Subcommand, ValueEnum, error::ErrorKind};
use std::path::PathBuf;
#[derive(Debug, Parser, Clone)]
#[command(name = "compactp", about = "Compact language parser", version)]
pub struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(long, default_value = "human", global = true)]
format: OutputFormat,
#[arg(long, global = true)]
pretty: bool,
#[arg(long, default_value = "auto", global = true)]
color: ColorChoice,
#[arg(long, global = true)]
timing: bool,
#[arg(long, global = true)]
stdin_filename: Option<String>,
#[arg(long, global = true)]
max_diagnostics: Option<usize>,
#[arg(long, global = true)]
max_errors: Option<usize>,
#[arg(long, global = true)]
no_recover: bool,
}
#[derive(Debug, Subcommand, Clone)]
pub enum Commands {
Lex { paths: Vec<PathBuf> },
Parse { paths: Vec<PathBuf> },
Cst { paths: Vec<PathBuf> },
Ast {
paths: Vec<PathBuf>,
#[arg(long)]
include_bodies: bool,
},
Diag { paths: Vec<PathBuf> },
Stats { paths: Vec<PathBuf> },
Watch {
#[command(subcommand)]
command: WatchableCommand,
},
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum OutputFormat {
Human,
Json,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ColorChoice {
Auto,
Always,
Never,
}
#[derive(Debug, Subcommand, Clone)]
pub enum WatchableCommand {
Lex { paths: Vec<PathBuf> },
Parse { paths: Vec<PathBuf> },
Cst { paths: Vec<PathBuf> },
Ast {
paths: Vec<PathBuf>,
#[arg(long)]
include_bodies: bool,
},
Diag { paths: Vec<PathBuf> },
Stats { paths: Vec<PathBuf> },
}
impl WatchableCommand {
pub fn paths(&self) -> &[PathBuf] {
match self {
WatchableCommand::Lex { paths }
| WatchableCommand::Parse { paths }
| WatchableCommand::Cst { paths }
| WatchableCommand::Diag { paths }
| WatchableCommand::Stats { paths } => paths,
WatchableCommand::Ast { paths, .. } => paths,
}
}
}
fn main() {
reset_sigpipe_to_default();
let cli = match Cli::try_parse() {
Ok(cli) => cli,
Err(err) => {
err.print().ok();
let code = match err.kind() {
ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => 0,
_ => 3,
};
std::process::exit(code);
}
};
match commands::run(cli) {
Ok(code) => std::process::exit(code),
Err(err) => {
let _ = writeln!(std::io::stderr(), "{}", err.message());
std::process::exit(err.exit_code());
}
}
}
#[cfg(unix)]
fn reset_sigpipe_to_default() {
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
}
}
#[cfg(not(unix))]
fn reset_sigpipe_to_default() {}
use std::io::Write;