Add shell completion generation
This commit is contained in:
parent
d9728a326d
commit
5b2c30f817
7 changed files with 98 additions and 3 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -591,6 +591,15 @@ dependencies = [
|
|||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.1"
|
||||
|
|
@ -1512,6 +1521,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"base64",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"geth-cas",
|
||||
"geth-config",
|
||||
"geth-control",
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ base64 = "0.22"
|
|||
blake3 = "1"
|
||||
bytes = "1"
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
clap_complete = "4"
|
||||
directories = "5"
|
||||
# Compatibility pins for iroh 0.95's ed25519-dalek prerelease dependency.
|
||||
ed25519 = "=3.0.0-rc.1"
|
||||
|
|
|
|||
|
|
@ -86,9 +86,11 @@ metadata from an authorized peer over Iroh.
|
|||
|
||||
The bootstrap implementation provides:
|
||||
|
||||
- `geth guide [init|owner-setup|enrollment|keys|overlay|service|smoke-test]` for
|
||||
- `geth guide [init|owner-setup|enrollment|keys|overlay|service|completions|smoke-test]` for
|
||||
embedded workflow help, including `--admin-key` / `--signing-key` setup
|
||||
examples
|
||||
- `geth completions <bash|zsh|fish|powershell|elvish>` for shell completion
|
||||
scripts generated from the live CLI command tree
|
||||
- `geth init`
|
||||
- `geth init --admin-key <public-key> --signing-key <private-key> --node-name <name>`
|
||||
- `geth daemon run`
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ license.workspace = true
|
|||
anyhow.workspace = true
|
||||
base64.workspace = true
|
||||
clap.workspace = true
|
||||
clap_complete.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
geth-config = { path = "../geth-config" }
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
use anyhow::{Context, Result, bail};
|
||||
use base64::Engine;
|
||||
use clap::{Args, Parser, Subcommand, ValueEnum};
|
||||
use clap::{Args, CommandFactory, Parser, Subcommand, ValueEnum};
|
||||
use clap_complete::{Shell, generate};
|
||||
use geth_config::GethPaths;
|
||||
use geth_control::{ControlRequest, ControlResponse};
|
||||
use geth_node::service::{ServiceInstallOptions, ServiceManager, ServiceReport};
|
||||
use std::io::Read;
|
||||
use std::io::{Read, stdout};
|
||||
use std::path::PathBuf;
|
||||
|
||||
const TOP_LEVEL_AFTER_HELP: &str = r#"Common starts:
|
||||
geth guide init
|
||||
geth guide owner-setup
|
||||
geth guide overlay
|
||||
geth guide completions
|
||||
geth init
|
||||
geth init --admin-key ~/.ssh/id_ed25519_sk.pub --signing-key ~/.ssh/id_ed25519_sk --node-name laptop
|
||||
geth daemon run
|
||||
|
|
@ -73,6 +75,7 @@ Topics:
|
|||
keys Meaning of --admin-key and --signing-key.
|
||||
overlay Optional Iroh overlay network planning.
|
||||
service Install and manage geth as a user service.
|
||||
completions Shell completion installation examples.
|
||||
smoke-test Minimal commands to verify a node and daemon."#;
|
||||
|
||||
const GUIDE_INIT: &str = r#"geth init has two modes.
|
||||
|
|
@ -178,6 +181,34 @@ Preview definitions without installing:
|
|||
geth daemon service print
|
||||
"#;
|
||||
|
||||
const GUIDE_COMPLETIONS: &str = r#"Shell completions:
|
||||
|
||||
geth can print completions for bash, zsh, fish, PowerShell, and elvish. The
|
||||
generated scripts are produced from the same Clap command tree as `geth --help`,
|
||||
so subcommands and flags stay in sync with the executable.
|
||||
|
||||
Bash:
|
||||
mkdir -p ~/.local/share/bash-completion/completions
|
||||
geth completions bash > ~/.local/share/bash-completion/completions/geth
|
||||
|
||||
Zsh:
|
||||
mkdir -p ~/.zfunc
|
||||
geth completions zsh > ~/.zfunc/_geth
|
||||
# Ensure ~/.zfunc is in fpath, then run: compinit
|
||||
|
||||
Fish:
|
||||
mkdir -p ~/.config/fish/completions
|
||||
geth completions fish > ~/.config/fish/completions/geth.fish
|
||||
|
||||
PowerShell:
|
||||
geth completions powershell > geth.ps1
|
||||
# Source geth.ps1 from your PowerShell profile.
|
||||
|
||||
Elvish:
|
||||
mkdir -p ~/.elvish/lib
|
||||
geth completions elvish > ~/.elvish/lib/geth.elv
|
||||
"#;
|
||||
|
||||
const GUIDE_OVERLAY: &str = r#"Optional overlay network:
|
||||
|
||||
geth has an experimental overlay-network design inspired by iroh-lan. The
|
||||
|
|
@ -256,6 +287,10 @@ pub enum Command {
|
|||
#[arg(value_enum)]
|
||||
topic: Option<GuideTopic>,
|
||||
},
|
||||
Completions {
|
||||
#[arg(value_enum)]
|
||||
shell: Shell,
|
||||
},
|
||||
#[command(long_about = INIT_LONG_ABOUT, after_long_help = INIT_AFTER_HELP)]
|
||||
Init {
|
||||
#[arg(
|
||||
|
|
@ -366,6 +401,7 @@ pub enum GuideTopic {
|
|||
Keys,
|
||||
Overlay,
|
||||
Service,
|
||||
Completions,
|
||||
SmokeTest,
|
||||
}
|
||||
|
||||
|
|
@ -1063,6 +1099,10 @@ pub struct EmptyArgs {}
|
|||
|
||||
pub async fn run() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
if let Command::Completions { shell } = &cli.command {
|
||||
print_completions(*shell);
|
||||
return Ok(());
|
||||
}
|
||||
let paths = GethPaths::resolve().context("resolve geth paths")?;
|
||||
match cli.command {
|
||||
Command::Guide { topic } => {
|
||||
|
|
@ -1169,6 +1209,7 @@ fn print_guide(topic: Option<GuideTopic>, json: bool) -> Result<()> {
|
|||
Some(GuideTopic::Keys) => ("keys", GUIDE_KEYS),
|
||||
Some(GuideTopic::Overlay) => ("overlay", GUIDE_OVERLAY),
|
||||
Some(GuideTopic::Service) => ("service", GUIDE_SERVICE),
|
||||
Some(GuideTopic::Completions) => ("completions", GUIDE_COMPLETIONS),
|
||||
Some(GuideTopic::SmokeTest) => ("smoke-test", GUIDE_SMOKE_TEST),
|
||||
};
|
||||
if json {
|
||||
|
|
@ -1185,8 +1226,14 @@ fn print_guide(topic: Option<GuideTopic>, json: bool) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn print_completions(shell: Shell) {
|
||||
let mut command = Cli::command();
|
||||
generate(shell, &mut command, "geth", &mut stdout());
|
||||
}
|
||||
|
||||
fn request_for_command(command: Command) -> Result<ControlRequest> {
|
||||
Ok(match command {
|
||||
Command::Completions { .. } => bail!("completion generation does not use the daemon"),
|
||||
Command::Status => ControlRequest::Status,
|
||||
Command::Sync {
|
||||
command: SyncCommand::Status,
|
||||
|
|
|
|||
|
|
@ -160,6 +160,36 @@ fn guide_command_explains_overlay_boundaries() {
|
|||
assert!(stdout.contains("all overlay packets must be carried over Iroh"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn completions_are_generated_without_daemon() {
|
||||
let home = tempfile::tempdir().expect("tempdir");
|
||||
let output = run_geth(home.path(), &["completions", "bash"]);
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"stderr: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(stdout.contains("_geth"));
|
||||
assert!(stdout.contains("overlay"));
|
||||
assert!(stdout.contains("completions"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn guide_command_explains_completion_installation() {
|
||||
let home = tempfile::tempdir().expect("tempdir");
|
||||
let output = run_geth(home.path(), &["guide", "completions"]);
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"stderr: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(stdout.contains("geth completions bash"));
|
||||
assert!(stdout.contains("PowerShell"));
|
||||
assert!(stdout.contains("fish"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn owner_init_requires_admin_key_and_signing_key() {
|
||||
let home = tempfile::tempdir().expect("tempdir");
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ Implementation order:
|
|||
- `[x]` README has a two-machine walkthrough for the main smoke tests.
|
||||
- `[x]` CLI recovery errors tell operators the next command to run.
|
||||
- `[x]` JSON sync status is script-friendly for stale/failed peer detection.
|
||||
- `[x]` Shell completions are generated from the Clap command tree for
|
||||
bash, zsh, fish, PowerShell, and elvish.
|
||||
- `[x]` Completion installation examples are available through
|
||||
`geth guide completions`.
|
||||
|
||||
- `[x]` Two-node operator-flow test coverage.
|
||||
Acceptance criteria:
|
||||
|
|
|
|||
Loading…
Reference in a new issue