feat: 新增 shell 自动补全命令

This commit is contained in:
Mengz 2026-06-07 17:45:10 +08:00
parent 9749a4c832
commit 5c16a4a70e
9 changed files with 189 additions and 2 deletions

View File

@ -172,6 +172,29 @@ export GITLINK_TOKEN="your-token" # Or set env var (for CI/CD, non-interactive e
gitlink-cli repo +list
```
#### Shell Completion
Generate completion scripts for your shell after installation:
```bash
# Bash
mkdir -p ~/.local/share/bash-completion/completions
gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli
# Zsh
gitlink-cli completion zsh > "${fpath[1]}/_gitlink-cli"
# Fish
mkdir -p ~/.config/fish/completions
gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish
# PowerShell
gitlink-cli completion powershell > gitlink-cli.ps1
. ./gitlink-cli.ps1
```
Use `--no-descriptions` if your shell setup prefers compact completion output.
### Quick Start (AI Agent)
> The following steps are for AI Agents. Some steps require the user to complete actions in a browser.

View File

@ -180,6 +180,29 @@ export GITLINK_TOKEN="your-token" # 或设置环境变量(适用于 CI/CD、
gitlink-cli repo +list
```
#### Shell 自动补全
安装后可以为常用 shell 生成自动补全脚本:
```bash
# Bash
mkdir -p ~/.local/share/bash-completion/completions
gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli
# Zsh
gitlink-cli completion zsh > "${fpath[1]}/_gitlink-cli"
# Fish
mkdir -p ~/.config/fish/completions
gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish
# PowerShell
gitlink-cli completion powershell > gitlink-cli.ps1
. ./gitlink-cli.ps1
```
如果当前终端不需要补全说明文本,可以追加 `--no-descriptions` 生成更精简的脚本。
### 快速上手AI Agent
> 以下步骤面向 AI Agent。部分步骤需要用户在浏览器中完成操作。

View File

@ -55,9 +55,9 @@ func TestRootCmdHasSubcommands(t *testing.T) {
}
names := map[string]bool{}
for _, sub := range root.Commands() {
names[sub.Use] = true
names[sub.Name()] = true
}
for _, want := range []string{"auth", "config", "doctor", "version"} {
for _, want := range []string{"auth", "completion", "config", "doctor", "version"} {
if !names[want] {
t.Fatalf("missing subcommand: %s", want)
}

71
cmd/completion_test.go Normal file
View File

@ -0,0 +1,71 @@
package cmd
import (
"bytes"
"strings"
"testing"
)
func TestCompletionCmdGeneratesSupportedShells(t *testing.T) {
cases := []struct {
shell string
want string
}{
{shell: "bash", want: "__gitlink-cli"},
{shell: "zsh", want: "#compdef gitlink-cli"},
{shell: "fish", want: "complete -c gitlink-cli"},
{shell: "powershell", want: "Register-ArgumentCompleter"},
}
for _, tc := range cases {
root, err := NewRootCmd(RootOptions{Version: "test", Args: []string{"completion", tc.shell}}, nil)
if err != nil {
t.Fatal(err)
}
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
if err := root.Execute(); err != nil {
t.Fatalf("%s completion error: %v", tc.shell, err)
}
if !strings.Contains(out.String(), tc.want) {
t.Fatalf("%s completion missing %q, got:\n%s", tc.shell, tc.want, out.String()[:min(len(out.String()), 400)])
}
}
}
func TestCompletionCmdNoDescriptions(t *testing.T) {
root, err := NewRootCmd(RootOptions{
Version: "test",
Args: []string{"completion", "bash", "--no-descriptions"},
}, nil)
if err != nil {
t.Fatal(err)
}
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
if err := root.Execute(); err != nil {
t.Fatal(err)
}
if strings.Contains(out.String(), "GitLink CLI - command-line tool for GitLink") {
t.Fatalf("expected descriptions to be omitted")
}
}
func TestCompletionCmdRejectsUnsupportedShell(t *testing.T) {
root, err := NewRootCmd(RootOptions{Version: "test", Args: []string{"completion", "xonsh"}}, nil)
if err != nil {
t.Fatal(err)
}
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
err = root.Execute()
if err == nil {
t.Fatal("expected unsupported shell error")
}
if !strings.Contains(err.Error(), "invalid argument") {
t.Fatalf("expected invalid argument error, got %q", err.Error())
}
}

View File

@ -58,6 +58,7 @@ func NewRootCmd(opts RootOptions, tr *i18n.Translator) (*cobra.Command, error) {
rootCmd.AddCommand(apiCmd.NewAPICmd(tr))
rootCmd.AddCommand(configCmd.NewConfigCmd(tr))
rootCmd.AddCommand(doctorCmd.NewDoctorCmd(tr))
rootCmd.AddCommand(newCompletionCmd(tr))
rootCmd.AddCommand(newVersionCmd(version, tr))
shortcuts.RegisterAll(rootCmd, tr)
@ -79,6 +80,43 @@ func newVersionCmd(version string, tr *i18n.Translator) *cobra.Command {
}
}
func newCompletionCmd(tr *i18n.Translator) *cobra.Command {
var noDescriptions bool
cmd := &cobra.Command{
Use: "completion [bash|zsh|fish|powershell]",
Short: tr.T("cmd.completion.short"),
Long: tr.T("cmd.completion.long"),
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
root := cmd.Root()
out := cmd.OutOrStdout()
includeDescriptions := !noDescriptions
switch args[0] {
case "bash":
return root.GenBashCompletionV2(out, includeDescriptions)
case "zsh":
if noDescriptions {
return root.GenZshCompletionNoDesc(out)
}
return root.GenZshCompletion(out)
case "fish":
return root.GenFishCompletion(out, includeDescriptions)
case "powershell":
if noDescriptions {
return root.GenPowerShellCompletion(out)
}
return root.GenPowerShellCompletionWithDesc(out)
default:
return fmt.Errorf("unsupported shell: %s", args[0])
}
},
}
cmd.Flags().BoolVar(&noDescriptions, "no-descriptions", false, tr.T("flag.completion.no_descriptions"))
return cmd
}
func Execute() error {
args := os.Args[1:]
rootCmd, err := NewRootCmd(RootOptions{

View File

@ -0,0 +1,5 @@
# Shell 自动补全命令
新增 `gitlink-cli completion [bash|zsh|fish|powershell]`,用于为 Bash、Zsh、Fish 和 PowerShell 生成原生自动补全脚本。用户安装 CLI 后可以直接把脚本写入对应 shell 的补全目录,减少记忆 Shortcut 命令、全局参数和子命令名称的成本,也让跨平台安装体验更完整。
命令支持 `--no-descriptions`,在不需要补全文案的终端配置中可以输出更精简的脚本。实现复用 Cobra 官方补全生成能力,不引入远端 API 依赖,并通过单元测试覆盖四类 shell 输出、描述开关和非法 shell 参数校验。

View File

@ -16,6 +16,8 @@
"cmd.ci.restart.short": "Restart a build",
"cmd.ci.short": "CI/CD operations",
"cmd.ci.stop.short": "Stop a build",
"cmd.completion.long": "Generate shell completion scripts for gitlink-cli.\n\nLoad the generated script in your shell profile to enable command and flag completion.\n\nExamples:\n gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli\n gitlink-cli completion zsh > \"${fpath[1]}/_gitlink-cli\"\n gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish\n gitlink-cli completion powershell > gitlink-cli.ps1",
"cmd.completion.short": "Generate shell completion scripts",
"cmd.config.get.short": "Get a configuration value",
"cmd.config.init.short": "Initialize configuration file",
"cmd.config.list.short": "List all configuration values",
@ -130,6 +132,7 @@
"flag.ci.stage": "Stage number",
"flag.ci.step": "Step number",
"flag.comment.body": "Comment body",
"flag.completion.no_descriptions": "Disable completion descriptions",
"flag.dataset.description": "Dataset description",
"flag.dataset.dry_run": "Preview the request without writing the dataset",
"flag.dataset.dry_run_delete": "Preview the request without deleting the attachment",

View File

@ -16,6 +16,8 @@
"cmd.ci.restart.short": "重启构建",
"cmd.ci.short": "CI/CD 操作",
"cmd.ci.stop.short": "停止构建",
"cmd.completion.long": "为 gitlink-cli 生成 shell 自动补全脚本。\n\n将生成的脚本加载到 shell 配置中,即可启用命令和参数补全。\n\n示例\n gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli\n gitlink-cli completion zsh > \"${fpath[1]}/_gitlink-cli\"\n gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish\n gitlink-cli completion powershell > gitlink-cli.ps1",
"cmd.completion.short": "生成 shell 自动补全脚本",
"cmd.config.get.short": "获取配置项",
"cmd.config.init.short": "初始化配置文件",
"cmd.config.list.short": "列出所有配置项",
@ -130,6 +132,7 @@
"flag.ci.stage": "阶段编号",
"flag.ci.step": "步骤编号",
"flag.comment.body": "评论内容",
"flag.completion.no_descriptions": "关闭补全描述",
"flag.dataset.description": "数据集描述",
"flag.dataset.dry_run": "预览请求,不写入数据集",
"flag.dataset.dry_run_delete": "预览请求,不删除附件",

View File

@ -63,6 +63,27 @@ gitlink-cli auth login
- HTTPS: `https://www.gitlink.org.cn/owner/repo.git`
- SSH: `git@www.gitlink.org.cn:owner/repo.git`
## Shell 自动补全
安装后可以按用户当前 shell 生成补全脚本,帮助用户发现 Shortcut 子命令和参数:
```bash
# Bash
gitlink-cli completion bash > ~/.local/share/bash-completion/completions/gitlink-cli
# Zsh
gitlink-cli completion zsh > "${fpath[1]}/_gitlink-cli"
# Fish
gitlink-cli completion fish > ~/.config/fish/completions/gitlink-cli.fish
# PowerShell
gitlink-cli completion powershell > gitlink-cli.ps1
. ./gitlink-cli.ps1
```
如果终端补全不需要描述文本,可以追加 `--no-descriptions`
## 输出格式
所有命令输出遵循统一 Envelope 格式: