Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 39 additions & 21 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# Documentation

[docs/README.md](docs/README.md) | [Language Reference](docs/lang-reference.md) | [Type System](docs/type-system.md) | [Runtime Engine](docs/runtime-engine.md) | [Binary Format](docs/binary-format/01-overview.md)
[docs/README.md](docs/README.md) | [CLI Guide](docs/cli.md) | [Language Reference](docs/lang-reference.md) | [Type System](docs/type-system.md) | [Runtime Engine](docs/runtime-engine.md) | [Binary Format](docs/binary-format/01-overview.md)

# Query Syntax Quick Reference

Expand Down Expand Up @@ -187,38 +187,56 @@ docs/

Run: `cargo run -p plotnik-cli -- <command>`

| Command | Purpose | Status |
| ------- | ------------------------------- | ------- |
| `debug` | Inspect queries and source ASTs | Working |
| `types` | Generate TypeScript types | Working |
| `langs` | List supported languages | Working |
| `exec` | Execute query, output JSON | Not yet |
| Command | Purpose | Status |
| ------- | -------------------------- | ------- |
| `tree` | Explore tree-sitter AST | Working |
| `check` | Validate query | Working |
| `dump` | Show compiled bytecode | Working |
| `infer` | Generate TypeScript types | Working |
| `langs` | List supported languages | Working |
| `exec` | Execute query, output JSON | Not yet |

## debug
## tree

Inspect query AST/CST or parse source files with tree-sitter.
Explore a source file's tree-sitter AST.

```sh
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id'
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --only-symbols
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --types
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --bytecode
cargo run -p plotnik-cli -- debug -s app.ts
cargo run -p plotnik-cli -- debug -s app.ts --raw
cargo run -p plotnik-cli -- tree app.ts
cargo run -p plotnik-cli -- tree app.ts --raw
cargo run -p plotnik-cli -- tree app.ts --spans
```

Options: `--only-symbols`, `--cst`, `--raw`, `--spans`, `--arities`, `--types`, `--bytecode`
## check

## types
Validate a query (silent on success, like `cargo check`).

Generate TypeScript type definitions from a query. Requires `-l/--lang` to validate node types against grammar.
```sh
cargo run -p plotnik-cli -- check query.ptk -l typescript
cargo run -p plotnik-cli -- check queries.ts/ # workspace with lang inference
cargo run -p plotnik-cli -- check -q '(identifier) @id' -l javascript
```

## dump

Show compiled bytecode.

```sh
cargo run -p plotnik-cli -- dump query.ptk # unlinked
cargo run -p plotnik-cli -- dump query.ptk -l typescript # linked
cargo run -p plotnik-cli -- dump -q '(identifier) @id'
```

## infer

Generate TypeScript type definitions from a query.

```sh
cargo run -p plotnik-cli -- types -q 'Test = (identifier) @id' -l javascript
cargo run -p plotnik-cli -- types --query-file query.ptk -l typescript -o types.d.ts
cargo run -p plotnik-cli -- infer query.ptk -l javascript
cargo run -p plotnik-cli -- infer queries.ts/ -o types.d.ts
cargo run -p plotnik-cli -- infer -q '(identifier) @id' -l typescript
```

Options: `--root-type <N>`, `--verbose-nodes`, `--no-node-type`, `--no-export`, `-o <F>`
Options: `--verbose-nodes`, `--no-node-type`, `--no-export`, `-o <FILE>`

## langs

Expand Down
248 changes: 130 additions & 118 deletions crates/plotnik-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,97 +30,157 @@ pub struct Cli {

#[derive(Subcommand)]
pub enum Command {
/// Debug and inspect queries and source files
/// Explore a source file's tree-sitter AST
#[command(after_help = r#"EXAMPLES:
plotnik debug -q 'Q = (identifier) @id'
plotnik debug -q 'Q = (identifier) @id' --only-symbols
plotnik debug -q 'Q = (identifier) @id' --bytecode
plotnik debug -s app.ts
plotnik debug -s app.ts --raw
plotnik debug -q 'Q = (function_declaration) @fn' -s app.ts -l typescript"#)]
Debug {
#[command(flatten)]
query: QueryArgs,
plotnik tree app.ts
plotnik tree app.ts --raw
plotnik tree app.ts --spans"#)]
Tree {
/// Source file to parse (use "-" for stdin)
#[arg(value_name = "SOURCE")]
source: PathBuf,

/// Language (inferred from extension if not specified)
#[arg(short = 'l', long, value_name = "LANG")]
lang: Option<String>,

#[command(flatten)]
source: SourceArgs,
/// Include anonymous nodes (literals, punctuation)
#[arg(long)]
raw: bool,

/// Language for source (required for inline text, inferred from extension otherwise)
#[arg(long, short = 'l', value_name = "LANG")]
/// Show source positions
#[arg(long)]
spans: bool,
},

/// Validate a query
#[command(after_help = r#"EXAMPLES:
plotnik check query.ptk
plotnik check query.ptk -l typescript
plotnik check queries.ts/
plotnik check -q '(identifier) @id' -l javascript"#)]
Check {
/// Query file or workspace directory
#[arg(value_name = "QUERY")]
query_path: Option<PathBuf>,

/// Inline query text
#[arg(short = 'q', long = "query", value_name = "TEXT")]
query_text: Option<String>,

/// Language for grammar validation (inferred from workspace name if possible)
#[arg(short = 'l', long, value_name = "LANG")]
lang: Option<String>,

/// Treat warnings as errors
#[arg(long)]
strict: bool,

#[command(flatten)]
output: OutputArgs,
},

/// List supported languages
Langs,

/// Execute a query against source code and output JSON
/// Show compiled bytecode
#[command(after_help = r#"EXAMPLES:
plotnik exec -q 'Q = (identifier) @id' -s app.js
plotnik exec -q 'Q = (identifier) @id' -s app.js --pretty
plotnik exec -q 'Q = (function_declaration) @fn' -s app.ts -l typescript --verbose-nodes
plotnik exec -q 'Q = (identifier) @id' -s app.js --check
plotnik exec --query-file query.ptk -s app.js --entry FunctionDef"#)]
Exec {
#[command(flatten)]
query: QueryArgs,

#[command(flatten)]
source: SourceArgs,

/// Language for source (required for inline text, inferred from extension otherwise)
#[arg(long, short = 'l', value_name = "LANG")]
plotnik dump query.ptk
plotnik dump query.ptk -l typescript
plotnik dump -q '(identifier) @id'"#)]
Dump {
/// Query file or workspace directory
#[arg(value_name = "QUERY")]
query_path: Option<PathBuf>,

/// Inline query text
#[arg(short = 'q', long = "query", value_name = "TEXT")]
query_text: Option<String>,

/// Language for linking (inferred from workspace name if possible)
#[arg(short = 'l', long, value_name = "LANG")]
lang: Option<String>,

#[command(flatten)]
output: ExecOutputArgs,
output: OutputArgs,
},

/// Generate type definitions from a query
#[command(after_help = r#"EXAMPLES:
plotnik types -q 'Q = (identifier) @id' -l javascript
plotnik types --query-file query.ptk -l typescript
plotnik types -q 'Q = (function_declaration) @fn' -l js --format ts
plotnik types -q 'Q = (identifier) @id' -l js --verbose-nodes
plotnik types -q 'Q = (identifier) @id' -l js -o types.d.ts
plotnik infer query.ptk -l javascript
plotnik infer queries.ts/ -o types.d.ts
plotnik infer -q '(function_declaration) @fn' -l typescript
plotnik infer query.ptk -l js --verbose-nodes

NOTE: Use --verbose-nodes to match `exec --verbose-nodes` output shape."#)]
Types {
#[command(flatten)]
query: QueryArgs,
Infer {
/// Query file or workspace directory
#[arg(value_name = "QUERY")]
query_path: Option<PathBuf>,

/// Inline query text
#[arg(short = 'q', long = "query", value_name = "TEXT")]
query_text: Option<String>,

/// Target language (required)
#[arg(long, short = 'l', value_name = "LANG")]
/// Target language (required, or inferred from workspace name)
#[arg(short = 'l', long, value_name = "LANG")]
lang: Option<String>,

#[command(flatten)]
output: TypesOutputArgs,
infer_output: InferOutputArgs,

#[command(flatten)]
output: OutputArgs,
},
}

#[derive(Args)]
pub struct ExecOutputArgs {
/// Pretty-print JSON output
#[arg(long)]
pub pretty: bool,
/// Execute a query against source code and output JSON
#[command(after_help = r#"EXAMPLES:
plotnik exec query.ptk app.js
plotnik exec -q '(identifier) @id' -s app.js
plotnik exec query.ptk app.ts --pretty
plotnik exec query.ptk app.ts --verbose-nodes"#)]
Exec {
/// Query file or workspace directory
#[arg(value_name = "QUERY")]
query_path: Option<PathBuf>,

/// Include verbose node information (line/column positions)
#[arg(long)]
pub verbose_nodes: bool,
/// Source file to execute against
#[arg(value_name = "SOURCE")]
source_path: Option<PathBuf>,

/// Validate output against inferred types
#[arg(long)]
pub check: bool,
/// Inline query text
#[arg(short = 'q', long = "query", value_name = "TEXT")]
query_text: Option<String>,

/// Entry point name (definition to match from)
#[arg(long, value_name = "NAME")]
pub entry: Option<String>,
/// Source code as inline text
#[arg(long = "source", value_name = "TEXT")]
source_text: Option<String>,

/// Source file (alternative to positional)
#[arg(short = 's', long = "source-file", value_name = "FILE")]
source_file: Option<PathBuf>,

/// Language (inferred from source extension if not specified)
#[arg(short = 'l', long, value_name = "LANG")]
lang: Option<String>,

#[command(flatten)]
exec_output: ExecOutputArgs,

#[command(flatten)]
output: OutputArgs,
},

/// List supported languages
Langs,
}

#[derive(Args)]
pub struct OutputArgs {
/// Colorize output
#[arg(long, default_value = "auto", value_name = "WHEN")]
pub color: ColorChoice,
}

#[derive(Args)]
pub struct TypesOutputArgs {
pub struct InferOutputArgs {
/// Output format (typescript, ts)
#[arg(long, default_value = "typescript", value_name = "FORMAT")]
pub format: String,
Expand All @@ -143,68 +203,20 @@ pub struct TypesOutputArgs {
}

#[derive(Args)]
#[group(id = "query_input", multiple = false)]
pub struct QueryArgs {
/// Query as inline text
#[arg(short = 'q', long = "query", value_name = "QUERY")]
pub query_text: Option<String>,

/// Query from file (use "-" for stdin)
#[arg(long = "query-file", value_name = "FILE")]
pub query_file: Option<PathBuf>,
}

#[derive(Args)]
#[group(id = "source_input", multiple = false)]
pub struct SourceArgs {
/// Source code as inline text
#[arg(long = "source", value_name = "SOURCE")]
pub source_text: Option<String>,

/// Source code from file (use "-" for stdin)
#[arg(short = 's', long = "source-file", value_name = "FILE")]
pub source_file: Option<PathBuf>,
}

#[derive(Args)]
pub struct OutputArgs {
/// Colorize output (auto-detected by default)
#[arg(long, default_value = "auto", value_name = "WHEN")]
pub color: ColorChoice,

/// Show only symbol table (instead of query AST)
#[arg(long = "only-symbols")]
pub symbols: bool,

/// Show query CST instead of AST (no effect on source)
#[arg(long)]
pub cst: bool,

/// Include trivia tokens (whitespace, comments)
#[arg(long)]
pub raw: bool,

/// Show source spans
#[arg(long)]
pub spans: bool,

/// Show inferred arities
#[arg(long)]
pub arities: bool,

/// Show compiled graph
pub struct ExecOutputArgs {
/// Pretty-print JSON output
#[arg(long)]
pub graph: bool,
pub pretty: bool,

/// Show unoptimized graph (before epsilon elimination)
/// Include verbose node information (line/column positions)
#[arg(long)]
pub graph_raw: bool,
pub verbose_nodes: bool,

/// Show inferred types
/// Validate output against inferred types
#[arg(long)]
pub types: bool,
pub check: bool,

/// Show bytecode dump
#[arg(long)]
pub bytecode: bool,
/// Entry point name (definition to match from)
#[arg(long, value_name = "NAME")]
pub entry: Option<String>,
}
Loading