mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
Add fabro completion subcommand for shell completions
Uses clap_complete to generate tab-completion scripts for zsh, fish, elvish, and PowerShell. Bash generation is caught gracefully since clap_complete panics with #[command(flatten)] subcommands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
41f7b0cda6
commit
93aa239056
10 changed files with 177 additions and 1 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -628,6 +628,15 @@ dependencies = [
|
|||
"strsim 0.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.55"
|
||||
|
|
@ -1448,6 +1457,7 @@ dependencies = [
|
|||
"base64",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"cli-table",
|
||||
"console 0.15.11",
|
||||
"core-foundation 0.9.4",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ base64 = "0.22"
|
|||
bytes = "1"
|
||||
tokio-util = "0.7"
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
clap_complete = "4"
|
||||
jsonschema = { version = "0.42", default-features = false }
|
||||
chrono = { version = "0.4", features = ["clock"] }
|
||||
bollard = "0.18"
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
"pages": [
|
||||
"reference/dot-language",
|
||||
"reference/cli",
|
||||
"reference/shell-completions",
|
||||
"reference/user-configuration",
|
||||
"reference/run-directory",
|
||||
"reference/sdk",
|
||||
|
|
|
|||
|
|
@ -888,6 +888,24 @@ fabro store dump abc123 -o ./debug-output
|
|||
|
||||
---
|
||||
|
||||
## `fabro completion`
|
||||
|
||||
Generate shell completion scripts for bash, zsh, fish, elvish, and PowerShell.
|
||||
|
||||
```bash
|
||||
fabro completion bash
|
||||
fabro completion zsh
|
||||
fabro completion fish
|
||||
```
|
||||
|
||||
| Argument | Description |
|
||||
|---|---|
|
||||
| `<SHELL>` | Shell to generate completions for: `bash`, `zsh`, `fish`, `elvish`, `powershell` (required) |
|
||||
|
||||
See [Shell Completions](/reference/shell-completions) for installation instructions for each shell.
|
||||
|
||||
---
|
||||
|
||||
## `fabro docs`
|
||||
|
||||
Open the Fabro documentation website in your default browser.
|
||||
|
|
|
|||
70
docs/reference/shell-completions.mdx
Normal file
70
docs/reference/shell-completions.mdx
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: "Shell Completions"
|
||||
description: "Set up tab completion for the fabro CLI in your shell"
|
||||
---
|
||||
|
||||
The `fabro completion` command generates shell completion scripts for tab-completing commands, flags, and arguments.
|
||||
|
||||
## Bash
|
||||
|
||||
Add to your `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
eval "$(fabro completion bash)"
|
||||
```
|
||||
|
||||
Or generate a file and source it:
|
||||
|
||||
```bash
|
||||
fabro completion bash > ~/.local/share/bash-completion/completions/fabro
|
||||
```
|
||||
|
||||
## Zsh
|
||||
|
||||
Add to your `~/.zshrc` (before `compinit`):
|
||||
|
||||
```bash
|
||||
eval "$(fabro completion zsh)"
|
||||
```
|
||||
|
||||
Or generate a file:
|
||||
|
||||
```bash
|
||||
fabro completion zsh > "${fpath[1]}/_fabro"
|
||||
```
|
||||
|
||||
You may need to run `compinit` or start a new shell session for changes to take effect.
|
||||
|
||||
## Fish
|
||||
|
||||
```bash
|
||||
fabro completion fish | source
|
||||
```
|
||||
|
||||
Or persist to the completions directory:
|
||||
|
||||
```bash
|
||||
fabro completion fish > ~/.config/fish/completions/fabro.fish
|
||||
```
|
||||
|
||||
## PowerShell
|
||||
|
||||
Add to your PowerShell profile:
|
||||
|
||||
```powershell
|
||||
fabro completion powershell | Out-String | Invoke-Expression
|
||||
```
|
||||
|
||||
## Elvish
|
||||
|
||||
```bash
|
||||
eval (fabro completion elvish | slurp)
|
||||
```
|
||||
|
||||
## Supported shells
|
||||
|
||||
Run `fabro completion --help` to see all supported shells:
|
||||
|
||||
```bash
|
||||
fabro completion --help
|
||||
```
|
||||
|
|
@ -42,6 +42,7 @@ fabro-store = { path = "../fabro-store" }
|
|||
fabro-types = { path = "../fabro-types" }
|
||||
fabro-util = { path = "../fabro-util" }
|
||||
clap.workspace = true
|
||||
clap_complete.workspace = true
|
||||
cli-table.workspace = true
|
||||
console.workspace = true
|
||||
indicatif.workspace = true
|
||||
|
|
|
|||
|
|
@ -812,6 +812,8 @@ pub(crate) enum Commands {
|
|||
#[command(subcommand)]
|
||||
command: SandboxCommand,
|
||||
},
|
||||
/// Generate shell completions
|
||||
Completion(CompletionArgs),
|
||||
/// System maintenance commands
|
||||
System(SystemNamespace),
|
||||
/// Send a queued analytics event (internal)
|
||||
|
|
@ -893,6 +895,7 @@ impl Commands {
|
|||
ProviderCommand::Login(_) => "provider login",
|
||||
},
|
||||
Self::Sandbox { command } => command.name(),
|
||||
Self::Completion(_) => "completion",
|
||||
Self::System(ns) => match &ns.command {
|
||||
SystemCommand::Prune(_) => "system prune",
|
||||
SystemCommand::Df(_) => "system df",
|
||||
|
|
@ -1040,6 +1043,12 @@ pub(crate) enum ProviderCommand {
|
|||
Login(ProviderLoginArgs),
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct CompletionArgs {
|
||||
/// Shell to generate completions for
|
||||
pub shell: clap_complete::Shell,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct LlmNamespace {
|
||||
#[command(subcommand)]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use anyhow::Result;
|
|||
use args::{Commands, GlobalArgs, LONG_VERSION, RunCommands};
|
||||
#[cfg(feature = "server")]
|
||||
use args::{ServerCommand, ServerNamespace};
|
||||
use clap::Parser;
|
||||
use clap::{CommandFactory, Parser};
|
||||
use fabro_telemetry::{git, panic as tel_panic, sanitize, sender};
|
||||
use fabro_util::printer::Printer;
|
||||
use fabro_util::terminal::Styles;
|
||||
|
|
@ -225,6 +225,27 @@ async fn main_inner() -> (String, Result<()>) {
|
|||
Commands::Provider(ns) => commands::provider::dispatch(ns).await?,
|
||||
Commands::Sandbox { command } => commands::sandbox::dispatch(command, &globals).await?,
|
||||
Commands::System(ns) => commands::system::dispatch(ns, &globals).await?,
|
||||
Commands::Completion(args) => {
|
||||
let mut cmd = Cli::command();
|
||||
let shell = args.shell;
|
||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
let mut buf = Vec::new();
|
||||
clap_complete::generate(shell, &mut cmd, "fabro", &mut buf);
|
||||
buf
|
||||
}));
|
||||
match result {
|
||||
Ok(buf) => {
|
||||
use std::io::Write;
|
||||
std::io::stdout().write_all(&buf)?;
|
||||
}
|
||||
Err(_) => {
|
||||
anyhow::bail!(
|
||||
"Failed to generate completions for {shell}. \
|
||||
Try zsh, fish, elvish, or powershell instead."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Commands::SendAnalytics { path } => {
|
||||
let result = sender::upload(&path).await;
|
||||
let _ = std::fs::remove_file(&path);
|
||||
|
|
|
|||
44
lib/crates/fabro-cli/tests/it/cmd/completion.rs
Normal file
44
lib/crates/fabro-cli/tests/it/cmd/completion.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use fabro_test::{fabro_snapshot, test_context};
|
||||
|
||||
#[test]
|
||||
fn help() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.command();
|
||||
cmd.args(["completion", "--help"]);
|
||||
fabro_snapshot!(context.filters(), cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Generate shell completions
|
||||
|
||||
Usage: fabro completion [OPTIONS] <SHELL>
|
||||
|
||||
Arguments:
|
||||
<SHELL> Shell to generate completions for [possible values: bash, elvish, fish, powershell, zsh]
|
||||
|
||||
Options:
|
||||
--debug Enable DEBUG-level logging (default is INFO) [env: FABRO_DEBUG=]
|
||||
--no-upgrade-check Disable automatic upgrade check [env: FABRO_NO_UPGRADE_CHECK=true]
|
||||
--quiet Suppress non-essential output [env: FABRO_QUIET=]
|
||||
--verbose Enable verbose output [env: FABRO_VERBOSE=]
|
||||
--storage-dir <STORAGE_DIR> Storage directory (default: ~/.fabro) [env: FABRO_STORAGE_DIR=[STORAGE_DIR]]
|
||||
-h, --help Print help
|
||||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generates_zsh_completions() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.command();
|
||||
cmd.args(["completion", "zsh"]);
|
||||
cmd.assert().success();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generates_fish_completions() {
|
||||
let context = test_context!();
|
||||
let mut cmd = context.command();
|
||||
cmd.args(["completion", "fish"]);
|
||||
cmd.assert().success();
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ mod asset;
|
|||
mod asset_cp;
|
||||
mod asset_list;
|
||||
mod attach;
|
||||
mod completion;
|
||||
mod config;
|
||||
mod config_show;
|
||||
mod cp;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue