Skip to content

Commit a2fc4f9

Browse files
authored
refactor: restructure CLI commands (#203)
1 parent 659e158 commit a2fc4f9

13 files changed

Lines changed: 818 additions & 553 deletions

File tree

AGENTS.md

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
# Documentation
99

10-
[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)
10+
[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)
1111

1212
# Query Syntax Quick Reference
1313

@@ -187,38 +187,56 @@ docs/
187187

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

190-
| Command | Purpose | Status |
191-
| ------- | ------------------------------- | ------- |
192-
| `debug` | Inspect queries and source ASTs | Working |
193-
| `types` | Generate TypeScript types | Working |
194-
| `langs` | List supported languages | Working |
195-
| `exec` | Execute query, output JSON | Not yet |
190+
| Command | Purpose | Status |
191+
| ------- | -------------------------- | ------- |
192+
| `tree` | Explore tree-sitter AST | Working |
193+
| `check` | Validate query | Working |
194+
| `dump` | Show compiled bytecode | Working |
195+
| `infer` | Generate TypeScript types | Working |
196+
| `langs` | List supported languages | Working |
197+
| `exec` | Execute query, output JSON | Not yet |
196198

197-
## debug
199+
## tree
198200

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

201203
```sh
202-
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id'
203-
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --only-symbols
204-
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --types
205-
cargo run -p plotnik-cli -- debug -q 'Test = (identifier) @id' --bytecode
206-
cargo run -p plotnik-cli -- debug -s app.ts
207-
cargo run -p plotnik-cli -- debug -s app.ts --raw
204+
cargo run -p plotnik-cli -- tree app.ts
205+
cargo run -p plotnik-cli -- tree app.ts --raw
206+
cargo run -p plotnik-cli -- tree app.ts --spans
208207
```
209208

210-
Options: `--only-symbols`, `--cst`, `--raw`, `--spans`, `--arities`, `--types`, `--bytecode`
209+
## check
211210

212-
## types
211+
Validate a query (silent on success, like `cargo check`).
213212

214-
Generate TypeScript type definitions from a query. Requires `-l/--lang` to validate node types against grammar.
213+
```sh
214+
cargo run -p plotnik-cli -- check query.ptk -l typescript
215+
cargo run -p plotnik-cli -- check queries.ts/ # workspace with lang inference
216+
cargo run -p plotnik-cli -- check -q '(identifier) @id' -l javascript
217+
```
218+
219+
## dump
220+
221+
Show compiled bytecode.
222+
223+
```sh
224+
cargo run -p plotnik-cli -- dump query.ptk # unlinked
225+
cargo run -p plotnik-cli -- dump query.ptk -l typescript # linked
226+
cargo run -p plotnik-cli -- dump -q '(identifier) @id'
227+
```
228+
229+
## infer
230+
231+
Generate TypeScript type definitions from a query.
215232

216233
```sh
217-
cargo run -p plotnik-cli -- types -q 'Test = (identifier) @id' -l javascript
218-
cargo run -p plotnik-cli -- types --query-file query.ptk -l typescript -o types.d.ts
234+
cargo run -p plotnik-cli -- infer query.ptk -l javascript
235+
cargo run -p plotnik-cli -- infer queries.ts/ -o types.d.ts
236+
cargo run -p plotnik-cli -- infer -q '(identifier) @id' -l typescript
219237
```
220238

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

223241
## langs
224242

crates/plotnik-cli/src/cli.rs

Lines changed: 130 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -30,97 +30,157 @@ pub struct Cli {
3030

3131
#[derive(Subcommand)]
3232
pub enum Command {
33-
/// Debug and inspect queries and source files
33+
/// Explore a source file's tree-sitter AST
3434
#[command(after_help = r#"EXAMPLES:
35-
plotnik debug -q 'Q = (identifier) @id'
36-
plotnik debug -q 'Q = (identifier) @id' --only-symbols
37-
plotnik debug -q 'Q = (identifier) @id' --bytecode
38-
plotnik debug -s app.ts
39-
plotnik debug -s app.ts --raw
40-
plotnik debug -q 'Q = (function_declaration) @fn' -s app.ts -l typescript"#)]
41-
Debug {
42-
#[command(flatten)]
43-
query: QueryArgs,
35+
plotnik tree app.ts
36+
plotnik tree app.ts --raw
37+
plotnik tree app.ts --spans"#)]
38+
Tree {
39+
/// Source file to parse (use "-" for stdin)
40+
#[arg(value_name = "SOURCE")]
41+
source: PathBuf,
42+
43+
/// Language (inferred from extension if not specified)
44+
#[arg(short = 'l', long, value_name = "LANG")]
45+
lang: Option<String>,
4446

45-
#[command(flatten)]
46-
source: SourceArgs,
47+
/// Include anonymous nodes (literals, punctuation)
48+
#[arg(long)]
49+
raw: bool,
4750

48-
/// Language for source (required for inline text, inferred from extension otherwise)
49-
#[arg(long, short = 'l', value_name = "LANG")]
51+
/// Show source positions
52+
#[arg(long)]
53+
spans: bool,
54+
},
55+
56+
/// Validate a query
57+
#[command(after_help = r#"EXAMPLES:
58+
plotnik check query.ptk
59+
plotnik check query.ptk -l typescript
60+
plotnik check queries.ts/
61+
plotnik check -q '(identifier) @id' -l javascript"#)]
62+
Check {
63+
/// Query file or workspace directory
64+
#[arg(value_name = "QUERY")]
65+
query_path: Option<PathBuf>,
66+
67+
/// Inline query text
68+
#[arg(short = 'q', long = "query", value_name = "TEXT")]
69+
query_text: Option<String>,
70+
71+
/// Language for grammar validation (inferred from workspace name if possible)
72+
#[arg(short = 'l', long, value_name = "LANG")]
5073
lang: Option<String>,
5174

75+
/// Treat warnings as errors
76+
#[arg(long)]
77+
strict: bool,
78+
5279
#[command(flatten)]
5380
output: OutputArgs,
5481
},
5582

56-
/// List supported languages
57-
Langs,
58-
59-
/// Execute a query against source code and output JSON
83+
/// Show compiled bytecode
6084
#[command(after_help = r#"EXAMPLES:
61-
plotnik exec -q 'Q = (identifier) @id' -s app.js
62-
plotnik exec -q 'Q = (identifier) @id' -s app.js --pretty
63-
plotnik exec -q 'Q = (function_declaration) @fn' -s app.ts -l typescript --verbose-nodes
64-
plotnik exec -q 'Q = (identifier) @id' -s app.js --check
65-
plotnik exec --query-file query.ptk -s app.js --entry FunctionDef"#)]
66-
Exec {
67-
#[command(flatten)]
68-
query: QueryArgs,
69-
70-
#[command(flatten)]
71-
source: SourceArgs,
72-
73-
/// Language for source (required for inline text, inferred from extension otherwise)
74-
#[arg(long, short = 'l', value_name = "LANG")]
85+
plotnik dump query.ptk
86+
plotnik dump query.ptk -l typescript
87+
plotnik dump -q '(identifier) @id'"#)]
88+
Dump {
89+
/// Query file or workspace directory
90+
#[arg(value_name = "QUERY")]
91+
query_path: Option<PathBuf>,
92+
93+
/// Inline query text
94+
#[arg(short = 'q', long = "query", value_name = "TEXT")]
95+
query_text: Option<String>,
96+
97+
/// Language for linking (inferred from workspace name if possible)
98+
#[arg(short = 'l', long, value_name = "LANG")]
7599
lang: Option<String>,
76100

77101
#[command(flatten)]
78-
output: ExecOutputArgs,
102+
output: OutputArgs,
79103
},
80104

81105
/// Generate type definitions from a query
82106
#[command(after_help = r#"EXAMPLES:
83-
plotnik types -q 'Q = (identifier) @id' -l javascript
84-
plotnik types --query-file query.ptk -l typescript
85-
plotnik types -q 'Q = (function_declaration) @fn' -l js --format ts
86-
plotnik types -q 'Q = (identifier) @id' -l js --verbose-nodes
87-
plotnik types -q 'Q = (identifier) @id' -l js -o types.d.ts
107+
plotnik infer query.ptk -l javascript
108+
plotnik infer queries.ts/ -o types.d.ts
109+
plotnik infer -q '(function_declaration) @fn' -l typescript
110+
plotnik infer query.ptk -l js --verbose-nodes
88111
89112
NOTE: Use --verbose-nodes to match `exec --verbose-nodes` output shape."#)]
90-
Types {
91-
#[command(flatten)]
92-
query: QueryArgs,
113+
Infer {
114+
/// Query file or workspace directory
115+
#[arg(value_name = "QUERY")]
116+
query_path: Option<PathBuf>,
117+
118+
/// Inline query text
119+
#[arg(short = 'q', long = "query", value_name = "TEXT")]
120+
query_text: Option<String>,
93121

94-
/// Target language (required)
95-
#[arg(long, short = 'l', value_name = "LANG")]
122+
/// Target language (required, or inferred from workspace name)
123+
#[arg(short = 'l', long, value_name = "LANG")]
96124
lang: Option<String>,
97125

98126
#[command(flatten)]
99-
output: TypesOutputArgs,
127+
infer_output: InferOutputArgs,
128+
129+
#[command(flatten)]
130+
output: OutputArgs,
100131
},
101-
}
102132

103-
#[derive(Args)]
104-
pub struct ExecOutputArgs {
105-
/// Pretty-print JSON output
106-
#[arg(long)]
107-
pub pretty: bool,
133+
/// Execute a query against source code and output JSON
134+
#[command(after_help = r#"EXAMPLES:
135+
plotnik exec query.ptk app.js
136+
plotnik exec -q '(identifier) @id' -s app.js
137+
plotnik exec query.ptk app.ts --pretty
138+
plotnik exec query.ptk app.ts --verbose-nodes"#)]
139+
Exec {
140+
/// Query file or workspace directory
141+
#[arg(value_name = "QUERY")]
142+
query_path: Option<PathBuf>,
108143

109-
/// Include verbose node information (line/column positions)
110-
#[arg(long)]
111-
pub verbose_nodes: bool,
144+
/// Source file to execute against
145+
#[arg(value_name = "SOURCE")]
146+
source_path: Option<PathBuf>,
112147

113-
/// Validate output against inferred types
114-
#[arg(long)]
115-
pub check: bool,
148+
/// Inline query text
149+
#[arg(short = 'q', long = "query", value_name = "TEXT")]
150+
query_text: Option<String>,
116151

117-
/// Entry point name (definition to match from)
118-
#[arg(long, value_name = "NAME")]
119-
pub entry: Option<String>,
152+
/// Source code as inline text
153+
#[arg(long = "source", value_name = "TEXT")]
154+
source_text: Option<String>,
155+
156+
/// Source file (alternative to positional)
157+
#[arg(short = 's', long = "source-file", value_name = "FILE")]
158+
source_file: Option<PathBuf>,
159+
160+
/// Language (inferred from source extension if not specified)
161+
#[arg(short = 'l', long, value_name = "LANG")]
162+
lang: Option<String>,
163+
164+
#[command(flatten)]
165+
exec_output: ExecOutputArgs,
166+
167+
#[command(flatten)]
168+
output: OutputArgs,
169+
},
170+
171+
/// List supported languages
172+
Langs,
173+
}
174+
175+
#[derive(Args)]
176+
pub struct OutputArgs {
177+
/// Colorize output
178+
#[arg(long, default_value = "auto", value_name = "WHEN")]
179+
pub color: ColorChoice,
120180
}
121181

122182
#[derive(Args)]
123-
pub struct TypesOutputArgs {
183+
pub struct InferOutputArgs {
124184
/// Output format (typescript, ts)
125185
#[arg(long, default_value = "typescript", value_name = "FORMAT")]
126186
pub format: String,
@@ -143,68 +203,20 @@ pub struct TypesOutputArgs {
143203
}
144204

145205
#[derive(Args)]
146-
#[group(id = "query_input", multiple = false)]
147-
pub struct QueryArgs {
148-
/// Query as inline text
149-
#[arg(short = 'q', long = "query", value_name = "QUERY")]
150-
pub query_text: Option<String>,
151-
152-
/// Query from file (use "-" for stdin)
153-
#[arg(long = "query-file", value_name = "FILE")]
154-
pub query_file: Option<PathBuf>,
155-
}
156-
157-
#[derive(Args)]
158-
#[group(id = "source_input", multiple = false)]
159-
pub struct SourceArgs {
160-
/// Source code as inline text
161-
#[arg(long = "source", value_name = "SOURCE")]
162-
pub source_text: Option<String>,
163-
164-
/// Source code from file (use "-" for stdin)
165-
#[arg(short = 's', long = "source-file", value_name = "FILE")]
166-
pub source_file: Option<PathBuf>,
167-
}
168-
169-
#[derive(Args)]
170-
pub struct OutputArgs {
171-
/// Colorize output (auto-detected by default)
172-
#[arg(long, default_value = "auto", value_name = "WHEN")]
173-
pub color: ColorChoice,
174-
175-
/// Show only symbol table (instead of query AST)
176-
#[arg(long = "only-symbols")]
177-
pub symbols: bool,
178-
179-
/// Show query CST instead of AST (no effect on source)
180-
#[arg(long)]
181-
pub cst: bool,
182-
183-
/// Include trivia tokens (whitespace, comments)
184-
#[arg(long)]
185-
pub raw: bool,
186-
187-
/// Show source spans
188-
#[arg(long)]
189-
pub spans: bool,
190-
191-
/// Show inferred arities
192-
#[arg(long)]
193-
pub arities: bool,
194-
195-
/// Show compiled graph
206+
pub struct ExecOutputArgs {
207+
/// Pretty-print JSON output
196208
#[arg(long)]
197-
pub graph: bool,
209+
pub pretty: bool,
198210

199-
/// Show unoptimized graph (before epsilon elimination)
211+
/// Include verbose node information (line/column positions)
200212
#[arg(long)]
201-
pub graph_raw: bool,
213+
pub verbose_nodes: bool,
202214

203-
/// Show inferred types
215+
/// Validate output against inferred types
204216
#[arg(long)]
205-
pub types: bool,
217+
pub check: bool,
206218

207-
/// Show bytecode dump
208-
#[arg(long)]
209-
pub bytecode: bool,
219+
/// Entry point name (definition to match from)
220+
#[arg(long, value_name = "NAME")]
221+
pub entry: Option<String>,
210222
}

0 commit comments

Comments
 (0)