feat(cli): cph completions <shell> 子命令(clap_complete)

用 clap_complete 4 给 cph 生成 shell 补全脚本(bash/zsh/fish/powershell/elvish)。
clap ValueEnum 枚举 Shell;run_completions 从 Cli::command() 派生,自动跟随
子命令/flag 演进。用法:`cph completions zsh > ~/.zfunc/_cph`。

- 依赖经 `cargo add clap_complete@4 -p cph-cli` 添加(4.6.5,默认 features 无额外依赖)
- README 补补全安装一节

测试:全 workspace 49 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-23 15:21:46 +08:00
parent e3370cad15
commit 4a9eb59aa9
4 changed files with 53 additions and 0 deletions
Generated
+10
View File
@@ -294,6 +294,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"
@@ -399,6 +408,7 @@ name = "cph-cli"
version = "0.0.1"
dependencies = [
"clap",
"clap_complete",
"cph-check",
"cph-diag",
"cph-typst",
+6
View File
@@ -20,6 +20,12 @@ cph check <工程目录> # 校验合法性(6 类诊断)
cph build <工程目录> --target student -o build/student.pdf # 渲讲义 PDF
```
Shell 补全(可选):
```sh
cph completions zsh > ~/.zfunc/_cph # 或 bash/fish/powershell/elvish
```
## 仓库布局
```
+1
View File
@@ -13,3 +13,4 @@ cph-check = { path = "../cph-check" }
cph-diag = { workspace = true }
cph-typst = { path = "../cph-typst" }
clap = { version = "4", features = ["derive"] }
clap_complete = "4"
+36
View File
@@ -46,6 +46,22 @@ enum Command {
#[arg(short = 'o', long, value_name = "OUT")]
out: Option<PathBuf>,
},
/// Print a shell-completion script to stdout (clap_complete; ADR-0013 opt-in
/// sibling: a local convenience, no lesson involved). Pipe to your shell's
/// completion file, e.g. `cph completions zsh > ~/.zfunc/_cph`.
Completions {
/// Which shell to generate completions for.
shell: Shell,
},
}
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
enum Shell {
Bash,
Zsh,
Fish,
PowerShell,
Elvish,
}
fn main() -> ExitCode {
@@ -59,9 +75,29 @@ fn main() -> ExitCode {
match cli.command {
Command::Check { path } => run_check(&path, &engine),
Command::Build { path, target, out } => run_build(&path, &engine, &target, out),
Command::Completions { shell } => run_completions(shell),
}
}
/// Emit a shell-completion script for `shell` to stdout. The script is built
/// from the same `Cli` clap definition above, so it tracks subcommands/flags as
/// they evolve.
fn run_completions(shell: Shell) -> ExitCode {
use clap::CommandFactory;
use clap_complete::Shell as CompShell;
let sh = match shell {
Shell::Bash => CompShell::Bash,
Shell::Zsh => CompShell::Zsh,
Shell::Fish => CompShell::Fish,
Shell::PowerShell => CompShell::PowerShell,
Shell::Elvish => CompShell::Elvish,
};
let mut cmd = Cli::command();
clap_complete::generate(sh, &mut cmd, "cph", &mut std::io::stdout());
ExitCode::SUCCESS
}
/// Print every diagnostic in `report` to stderr, followed by a summary line.
fn print_diagnostics(report: &CheckReport) {
for d in &report.diagnostics {