📢 Update
Nushell 0.116 版本重构了 Completion API。在最新版本中,外部 Completer 已原生支持别名(Alias)解析,不再需要手动编写逻辑来展开或补全 Alias
本文已同步更新:
- 更新了 Completion API 的配置写法;
- 删除了原文章中针对 Alias 逻辑的冗余处理章节。
Nushell 是一款基于 Rust 构建的现代 Shell。相比仅支持 UNIX 平台的 Fish,它天然跨平台,在不同系统间工作时无需来回切换Shell,且 Nushell 有着活跃的社区。
但 Fish 有着更成熟的补全生态,例如它原生支持对 Claude Code 进行补全,Nushell 社区对其的支持则稍晚一些。
好消息是,在 Nushell 中我们可以通过两种方案实现补全,且二者完美共存:
- Custom Completions:手写补全脚本,可参考 Nushell 社区脚本库
- External Completers:桥接外部补全工具(如 Fish、Carapace、Zoxide)
本文主要介绍第二种方式——让你在 Nushell 里也能复用 Fish 的补全能力。
整体架构
在 completions.nu 中,我们将补全系统拆分为两个核心模块:
- 桥接(bridge):连接外部补全系统(fish / carapace)
- 分发调度(dispatcher):根据命令类型选择最合适的补全器
Step 1. 桥接 Fish 与 Carapace
Fish 作为一款成熟的 Shell,在拥有丰富补全生态的同时,也提供了一个 complete --do-complete 接口,允许我们通过命令行直接调用其内部的补全逻辑:# 调用 Fish 的补全逻辑,获取 `git switch or` 的候选补全项$ fish --command "complete --do-complete 'git switch or'"origin/HEAD Remote Branchorigin/dev Remote Branchorigin/main Remote Branch
Carapace 则是另一个通用的跨平台补全引擎,能够为多种 Shell 统一提供补全能力。它的接口调用方式为 carapace <command> <shell> <args...>,并且能够直接输出 JSON 格式的补全数据:# 调用 Carapace 获取 `git switch or` 在 Nushell 下的 JSON 结构化补全输出# Carapace 输出的 JSON 默认是 one-line 的,为了美观,此处使用 jq 进行格式化$ carapace git nushell git switch or | jq[ { "value": "origin/head ", "display": "origin/head", "description": "remote branch" }, { "value": "origin/dev ", "display": "origin/dev", "description": "remote branch" }, { "value": "origin/main ", "display": "origin/main", "description": "remote branch" }]
借助 Nushell 提供的 External Completer API,我们可以将这些能力整合进 Nushell:let fish_completer = {|place| fish --command $"complete '--do-complete=($place.command | str replace --all "'" "\\'" | str join ' ')'" | from tsv --flexible --noheaders --no-infer | rename value description | update value {|row| let value = $row.value let need_quote = ['\' ',' '[' ']' '(' ')' ' ' '\t' "'" '"' "`"] | any {$in in $value} if ($need_quote and ($value | path exists)) { let expanded_path = if ($value starts-with '~') {$value | path expand --no-symlink} else {$value} $'"($expanded_path | str replace --all "\"" "\\\"")"' } else {$value} }}let carapace_completer = {|place| CARAPACE_LENIENT=1 carapace $place.command.0 nushell ...$place.command | from json}
Step 2. 分发调度
不同补全器的质量因工具而异:
- 某些工具在 Fish 中补全最完整(如
git、bun) - 其他工具则更适合 Carapace
因此采用 分发策略:指定命令走 Fish,其余走 Carapace。
得益于 Nushell 0.116 的升级,我们在分发逻辑中可以直接接受原始 spans,无需再手动编写别名查找和展开的代码:let external_completer = {|place| match $place.command.0 { nu | tv | bun | git | rclone => $fish_completer _ => $carapace_completer } | do $in $place}
Step 3. 启用 External Completer
最后在 Nushell 配置中启用外部补全即可:$env.config.completions = { case_sensitive: false quick: true partial: true algorithm: "prefix" external: { enable: true completer: $external_completer } use_ls_colors: true}
还可以进一步配置 menu 和 keybindings 以获得更丝滑的体验,参考我的配置仓库 Efterklang/dotfiles。
效果演示
配置完成后,输入 ssh 按 Tab 即可自动列出 ~/.ssh/config 中的远程主机,git 补全也一应俱全:
