use clap::{Args, Parser, Subcommand, ValueEnum};
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum ParseOutput {
Summary,
Text,
Json,
}
#[derive(Clone, Copy, Default, ValueEnum)]
pub(crate) enum FmtOutput {
#[default]
Formatted,
Bytecode,
DocTree,
}
#[derive(Clone, Copy, Default, ValueEnum)]
pub(crate) enum LineageOutput {
#[default]
Json,
Text,
}
#[derive(Clone, Copy, Default, ValueEnum)]
pub(crate) enum AnalysisOutput {
#[default]
Text,
Json,
}
#[derive(Clone, Copy, Default, ValueEnum)]
pub(crate) enum IntrospectOutput {
#[default]
Text,
Json,
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum KeywordCasing {
Upper,
Lower,
}
#[derive(Clone, Copy, ValueEnum)]
pub(crate) enum HostLanguage {
Python,
Typescript,
Shell,
}
impl From<HostLanguage> for syntaqlite::embedded::HostLanguage {
fn from(lang: HostLanguage) -> Self {
match lang {
HostLanguage::Python => syntaqlite::embedded::HostLanguage::Python,
HostLanguage::Typescript => syntaqlite::embedded::HostLanguage::Typescript,
HostLanguage::Shell => syntaqlite::embedded::HostLanguage::Shell,
}
}
}
#[derive(Parser)]
#[command(about = "SQL formatting and analysis tools")]
pub(crate) struct Cli {
#[arg(short = 'c', long = "config", global = true)]
pub(crate) config: Option<String>,
#[arg(long = "no-config", global = true, conflicts_with = "config")]
pub(crate) no_config: bool,
#[cfg(feature = "dynload")]
#[arg(long = "dialect", global = true)]
pub(crate) dialect_path: Option<String>,
#[cfg(feature = "dynload")]
#[arg(long, requires = "dialect_path", global = true)]
pub(crate) dialect_name: Option<String>,
#[arg(long, global = true)]
pub(crate) sqlite_version: Option<String>,
#[arg(long, global = true)]
pub(crate) sqlite_cflag: Vec<String>,
#[command(subcommand)]
pub(crate) command: Command,
}
#[derive(Subcommand)]
pub(crate) enum Command {
Parse(ParseArgs),
Fmt(FmtArgs),
Analyze(AnalyzeArgs),
Lineage(LineageArgs),
Lsp,
#[cfg(feature = "mcp")]
Mcp,
Serve {
#[command(subcommand)]
protocol: ServeProtocol,
},
Tokenize(TokenizeArgs),
#[cfg(feature = "codegen")]
Dialect {
#[command(subcommand)]
command: DialectSubcommand,
},
Version,
#[cfg(feature = "codegen")]
#[command(flatten)]
DialectTool(crate::commands::codegen::ToolCommand),
}
#[derive(Args)]
pub(crate) struct ParseArgs {
pub(crate) files: Vec<String>,
#[arg(short = 'e', long = "expression", conflicts_with = "files")]
pub(crate) expression: Option<String>,
#[arg(short, long, value_enum, default_value_t = ParseOutput::Text)]
pub(crate) output: ParseOutput,
#[arg(long = "experimental-lang")]
pub(crate) lang: Option<HostLanguage>,
}
#[derive(Args)]
pub(crate) struct FmtArgs {
pub(crate) files: Vec<String>,
#[arg(short = 'e', long = "expression", conflicts_with = "files")]
pub(crate) expression: Option<String>,
#[arg(short = 'w', long)]
pub(crate) line_width: Option<usize>,
#[arg(short = 't', long)]
pub(crate) indent_width: Option<usize>,
#[arg(short = 'k', long, value_enum)]
pub(crate) keyword_case: Option<KeywordCasing>,
#[arg(short = 'i', long)]
pub(crate) in_place: bool,
#[arg(long, conflicts_with = "in_place")]
pub(crate) check: bool,
#[arg(long)]
pub(crate) semicolons: Option<bool>,
#[arg(short, long, value_enum, default_value_t = FmtOutput::Formatted)]
pub(crate) output: FmtOutput,
#[arg(long = "experimental-lang")]
pub(crate) lang: Option<HostLanguage>,
}
#[derive(Args)]
pub(crate) struct AnalyzeArgs {
pub(crate) files: Vec<String>,
#[arg(short = 'e', long = "expression", conflicts_with = "files")]
pub(crate) expression: Option<String>,
#[arg(long)]
pub(crate) schema: Vec<String>,
#[arg(short = 'A', long = "allow")]
pub(crate) allow: Vec<String>,
#[arg(short = 'W', long = "warn")]
pub(crate) warn: Vec<String>,
#[arg(short = 'D', long = "deny")]
pub(crate) deny: Vec<String>,
#[arg(long = "experimental-lang")]
pub(crate) lang: Option<HostLanguage>,
#[arg(short, long, value_enum, default_value_t = AnalysisOutput::Text)]
pub(crate) output: AnalysisOutput,
}
#[derive(Args)]
pub(crate) struct LineageArgs {
pub(crate) files: Vec<String>,
#[arg(short = 'e', long = "expression", conflicts_with = "files")]
pub(crate) expression: Option<String>,
#[arg(long)]
pub(crate) schema: Vec<String>,
#[arg(short, long, value_enum, default_value_t = LineageOutput::Json)]
pub(crate) output: LineageOutput,
#[arg(long = "experimental-lang")]
pub(crate) lang: Option<HostLanguage>,
#[command(subcommand)]
pub(crate) scope: Option<LineageScope>,
}
#[derive(Args)]
pub(crate) struct TokenizeArgs {
pub(crate) files: Vec<String>,
#[arg(short = 'e', long = "expression", conflicts_with = "files")]
pub(crate) expression: Option<String>,
#[arg(short, long, value_enum, default_value_t = IntrospectOutput::Text)]
pub(crate) output: IntrospectOutput,
#[arg(long = "experimental-lang")]
pub(crate) lang: Option<HostLanguage>,
}
#[derive(Clone, Copy, Subcommand)]
pub(crate) enum LineageScope {
Tables,
Columns,
}
#[cfg(feature = "codegen")]
#[derive(Subcommand)]
pub(crate) enum DialectSubcommand {
Generate(crate::commands::codegen::DialectArgs),
}
#[derive(Subcommand)]
pub(crate) enum ServeProtocol {
Json,
}