diff --git a/.agents/skills/add-command-spec/SKILL.md b/.agents/skills/add-command-spec/SKILL.md new file mode 100644 index 00000000..f0152fb4 --- /dev/null +++ b/.agents/skills/add-command-spec/SKILL.md @@ -0,0 +1,24 @@ +--- +name: add-command-spec +description: Guide for adding new command completion specs to warp-command-signatures. Use when creating a new JSON spec for shell command completions, adding generators for dynamic suggestions, or extending existing command specs. +--- + +# Adding a New Command Spec + +## Steps + +1. **Create JSON spec**: `command-signatures/json/.json` following the [Fig completion spec schema](https://fig.io/docs/reference) +2. **Create generator** (if needed): Add `command-signatures/src/generators/.rs`, define a `generator()` function returning `CommandSignatureGenerators`, and register it in `generators/mod.rs` + +## Style Guideline + +Match the formatting conventions used in the command's `--help` output. For example, if the help text uses `UPPER_CASE` for positional argument names, use the same casing in the spec's argument `name` field. + +## Validation + +Run `cargo test` to verify the spec deserializes correctly and any referenced `generatorName`s exist. + +## Reference Examples + +- **Simple spec with generator**: `json/kill.json` + `src/generators/kill.rs` — minimal example showing `generatorName` usage for process and signal completions +- **Complex spec with multiple generators**: `json/brew.json` + `src/generators/brew.rs` — shows subcommands, options, and multiple generators (`formulae_generator`, `services`, etc.) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b6aa1027..6f1ff504 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -13,21 +13,12 @@ jobs: steps: - uses: actions/checkout@v3 - name: Run cargo fmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: -p warp-command-signatures -p warp-completion-metadata + run: cargo fmt -p warp-command-signatures -p warp-completion-metadata --check - name: Run cargo clippy - uses: actions-rs/cargo@v1 - with: - command: clippy - args: -p warp-command-signatures -p warp-completion-metadata --all-targets --all-features -- -D warnings + run: cargo clippy -p warp-command-signatures -p warp-completion-metadata --all-targets --all-features -- -D warnings test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --verbose + run: cargo test --verbose diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..f973efc0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,70 @@ +# AGENTS.md + +This file provides guidance to agents when working with code in this repository. + +## Overview + +This repository provides command completion signatures ("specs") for Warp terminal. It contains two Rust crates: + +- **`warp-command-signatures`**: The main library that embeds and exposes command specs. Used as a dependency by `warp-internal`. +- **`warp-completion-metadata`**: Core types for signatures, arguments, options, generators, and the Fig-compatible JSON schema. + +## Architecture + +### Command Specs (JSON) + +Specs are JSON files based on the [Fig completion spec schema](https://fig.io/docs/reference), but **Warp does not use Fig's JavaScript generators**. Instead: + +- The `generatorName` field references Rust-based generators (see below) +- Fig's `generateSpec` JavaScript field is present in some imported specs but is **ignored** by Warp +- Static suggestions, templates (`filepaths`, `folders`), and subcommand/option definitions work as documented + +| Location | Description | +|----------|-------------| +| `command-signatures/json/*.json` | Hand-written specs | +| `command-signatures/json/autogenerated/powershell/*.json` | Auto-generated PowerShell cmdlet specs | +| `command-signatures/json/overrides/powershell/*.json` | Hand-written overrides for autogenerated specs | + +The `assets.rs` module uses `rust-embed` to flatten these directories into a single namespace at compile time, so callers just use `signature_by_name("git")`. + +### Generators (Rust) + +Generators produce dynamic completions by running shell commands. They are defined in `command-signatures/src/generators/` (one file per command or command family). + +A generator consists of: +1. A `GeneratorProcess` (either a static `CommandBuilder` or a function that builds a command from tokens) +2. An `on_complete_callback` that parses the command output into `Suggestion`s + +JSON specs reference generators via the `generatorName` field (e.g. `"generatorName": "branches"`). The mapping from name → Rust code is established in `generators/mod.rs` via `dynamic_command_signature_data()`. + +Example from `brew.rs`: +```rust +CommandSignatureGenerators::new("brew") + .add_generator( + "formulae_generator", // Referenced in JSON as "generatorName": "formulae_generator" + Generator::script(CommandBuilder::single_command("brew list -1"), |output| { + output.trim().lines() + .map(|line| Suggestion::with_description(line, "Installed formula")) + .collect_unordered_results() + }), + ) +``` + +### Override System + +For autogenerated specs (currently PowerShell only), hand-written augmentations live in `json/overrides/`. Overrides are matched by option name or argument index and merged at generation time. Only `template` and `generatorName` fields are currently supported for overrides. + +## Key Types + +- `Signature`: Defines a command/subcommand (name, options, arguments, subcommands) +- `Argument`: A positional parameter with types (Template, Generator, or literal Suggestion) +- `Opt`: A flag/option with optional arguments +- `Generator`: Produces dynamic suggestions by running shell commands +- `Template`: Built-in generators for files/folders + +## Testing Invariants + +Tests in `lib.rs` verify: +- All `GeneratorName`s referenced in specs exist in `dynamic_command_signature_data()` +- All JSON specs deserialize without error +- Generator commands contain no unsafe (unquoted) newlines (required for TMUX control mode) diff --git a/completion-metadata/src/lib.rs b/completion-metadata/src/lib.rs index 0b644906..2c3f91af 100644 --- a/completion-metadata/src/lib.rs +++ b/completion-metadata/src/lib.rs @@ -253,7 +253,7 @@ pub enum Shell { /// A shell that can assume POSIX-compliant syntax. Posix, Powershell, - CmdExe + CmdExe, } impl Shell { @@ -262,7 +262,7 @@ impl Shell { match self { Shell::Posix => "2>/dev/null", Shell::Powershell => "2> $null", - Shell::CmdExe => "2> NUL" + Shell::CmdExe => "2> NUL", } } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4c4ea7ca..eaadc1fe 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.82" +channel = "1.85" components = ["rustfmt", "clippy"] targets = ["aarch64-apple-darwin", "x86_64-apple-darwin"] profile = "minimal"