use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
#[derive(Clone, Copy, Debug, Default, ValueEnum)]
pub enum ColorChoice {
#[default]
Auto,
Always,
Never,
}
impl ColorChoice {
pub fn should_colorize(self) -> bool {
match self {
ColorChoice::Always => true,
ColorChoice::Never => false,
ColorChoice::Auto => std::io::IsTerminal::is_terminal(&std::io::stderr()),
}
}
}
#[derive(Parser)]
#[command(name = "plotnik", bin_name = "plotnik")]
#[command(about = "Query language for tree-sitter AST with type inference")]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand)]
pub enum Command {
#[command(after_help = r#"EXAMPLES:
plotnik debug -q '(identifier) @id'
plotnik debug -q '(identifier) @id' --only-symbols
plotnik debug -s app.ts
plotnik debug -s app.ts --raw
plotnik debug -q '(function_declaration) @fn' -s app.ts -l typescript"#)]
Debug {
#[command(flatten)]
query: QueryArgs,
#[command(flatten)]
source: SourceArgs,
#[arg(long, short = 'l', value_name = "LANG")]
lang: Option<String>,
#[command(flatten)]
output: OutputArgs,
},
Docs {
topic: Option<String>,
},
Langs,
#[command(after_help = r#"EXAMPLES:
plotnik exec -q '(identifier) @id' -s app.js
plotnik exec -q '(identifier) @id' -s app.js --pretty
plotnik exec -q '(function_declaration) @fn' -s app.ts -l typescript --verbose-nodes
plotnik exec -q '(identifier) @id' -s app.js --check
plotnik exec --query-file query.plnk -s app.js --entry FunctionDef"#)]
Exec {
#[command(flatten)]
query: QueryArgs,
#[command(flatten)]
source: SourceArgs,
#[arg(long, short = 'l', value_name = "LANG")]
lang: Option<String>,
#[command(flatten)]
output: ExecOutputArgs,
},
#[command(after_help = r#"EXAMPLES:
plotnik types -q '(identifier) @id' -l javascript
plotnik types --query-file query.plnk -l typescript
plotnik types -q '(function_declaration) @fn' -l js --format ts
plotnik types -q '(identifier) @id' -l js --verbose-nodes
plotnik types -q '(identifier) @id' -l js -o types.d.ts
NOTE: Use --verbose-nodes to match `exec --verbose-nodes` output shape."#)]
Types {
#[command(flatten)]
query: QueryArgs,
#[arg(long, short = 'l', value_name = "LANG")]
lang: Option<String>,
#[command(flatten)]
output: TypesOutputArgs,
},
}
#[derive(Args)]
pub struct ExecOutputArgs {
#[arg(long)]
pub pretty: bool,
#[arg(long)]
pub verbose_nodes: bool,
#[arg(long)]
pub check: bool,
#[arg(long, value_name = "NAME")]
pub entry: Option<String>,
}
#[derive(Args)]
pub struct TypesOutputArgs {
#[arg(long, default_value = "typescript", value_name = "FORMAT")]
pub format: String,
#[arg(long, default_value = "Query", value_name = "NAME")]
pub root_type: String,
#[arg(long)]
pub verbose_nodes: bool,
#[arg(long)]
pub no_node_type: bool,
#[arg(long)]
pub no_export: bool,
#[arg(short = 'o', long, value_name = "FILE")]
pub output: Option<PathBuf>,
}
#[derive(Args)]
#[group(id = "query_input", multiple = false)]
pub struct QueryArgs {
#[arg(short = 'q', long = "query", value_name = "QUERY")]
pub query_text: Option<String>,
#[arg(long = "query-file", value_name = "FILE")]
pub query_file: Option<PathBuf>,
}
#[derive(Args)]
#[group(id = "source_input", multiple = false)]
pub struct SourceArgs {
#[arg(long = "source", value_name = "SOURCE")]
pub source_text: Option<String>,
#[arg(short = 's', long = "source-file", value_name = "FILE")]
pub source_file: Option<PathBuf>,
}
#[derive(Args)]
pub struct OutputArgs {
#[arg(long, default_value = "auto", value_name = "WHEN")]
pub color: ColorChoice,
#[arg(long = "only-symbols")]
pub symbols: bool,
#[arg(long)]
pub cst: bool,
#[arg(long)]
pub raw: bool,
#[arg(long)]
pub spans: bool,
#[arg(long)]
pub cardinalities: bool,
#[arg(long)]
pub graph: bool,
#[arg(long)]
pub graph_raw: bool,
#[arg(long)]
pub types: bool,
}