Skip to main content

xyz_rust/cli/
completion.rs

1// shell 补全脚本生成(bash/zsh/fish)。脚本模板与 Go 版逐字一致;
2// 词表 = 各命令顶层段 + 内建词(completion/help/serve/mcp)与通用 flag。
3
4use std::fmt::Write as _;
5use std::io::Write;
6
7pub fn print_completion(
8    top_words: &[String],
9    out: &mut dyn Write,
10    err_out: &mut dyn Write,
11    bin: &str,
12    shell: &str,
13) -> i32 {
14    let mut names: Vec<&String> = Vec::new();
15    let mut seen: Vec<&str> = Vec::new();
16    for w in top_words {
17        if !seen.contains(&w.as_str()) {
18            seen.push(w.as_str());
19            names.push(w);
20        }
21    }
22    let mut list: Vec<String> = names.iter().map(|s| s.to_string()).collect();
23    list.extend(
24        [
25            "completion",
26            "help",
27            "serve",
28            "mcp",
29            "-h",
30            "--help",
31            "-v",
32            "--version",
33        ]
34        .iter()
35        .map(|s| s.to_string()),
36    );
37    let words = list.join(" ");
38    let mut buf = String::new();
39    match shell {
40        "bash" => {
41            let _ = write!(
42                buf,
43                "# {bin} completion for bash\n_{bin}_completions() {{\n  local cur\n  cur=\"${{COMP_WORDS[COMP_CWORD]}}\"\n  COMPREPLY=( $(compgen -W \"{words}\" -- \"$cur\") )\n}}\ncomplete -F _{bin}_completions {bin}\n"
44            );
45        }
46        "zsh" => {
47            let _ = write!(
48                buf,
49                "#compdef {bin}\n_{bin}_completions() {{\n  local -a cmds\n  cmds=({words})\n  _describe '{bin}' cmds\n}}\ncompdef _{bin}_completions {bin}\n"
50            );
51        }
52        "fish" => {
53            for n in &list[..list.len().saturating_sub(6)] {
54                let _ = writeln!(buf, "complete -c {bin} -f -a {n}");
55            }
56            let _ = writeln!(buf, "complete -c {bin} -f -a completion");
57        }
58        _ => {
59            let _ = writeln!(err_out, "unknown shell {shell:?} (want bash|zsh|fish)");
60            return 2;
61        }
62    }
63    let _ = write!(out, "{buf}");
64    0
65}