placeholder我从 Fzf 切换到 Television:用声明式 Channel 实现跨 Shell 模糊查找

我从 Fzf 切换到 Television:用声明式 Channel 实现跨 Shell 模糊查找

一个跨 Shell 的模糊查找器,用智能快捷触发替代手动路径跳转。本文会解释它的工作原理、配置方法,以及它为什么可能替换你当前的方案。

你可能遇到过这些场景:

  • 路径跳转循环: 反复输入 cd foo/ && ls,结果发现进错目录,再 cd ../.. 重来一遍。
  • 历史命令捞针: 一直按 Up,只为找昨天执行过的一条复杂命令。
  • PID 手动接力:ps aux | grep python 找进程,再复制 PID,最后手动输入 kill

fzf 这样的模糊查找工具可以缓解这些问题,但我后来切到了 Television,因为它在 UI/UX 和跨 Shell 一致性上更合适我的工作流。

这篇文章写给希望更快完成终端导航、但又不想维护一堆 Shell 特定胶水代码的用户。读完你会知道模糊查找器的基本原理、tv 的配置方式,以及它是否比你当前方案更匹配你的习惯。

模糊查找器是什么

假设你要在项目里找某个子目录,可以先用 fd --type directory 列出目录:

$ fd --type directorysrc/...packages/core/utils/src/helperspackages/core/utils/src/parserspackages/ui/components/Button

当列表很长时,人工扫一遍很痛苦。你可以用 fd --type directory | rg <src> 先过滤,但它依然是静态结果。模糊查找器真正有价值的地方在于交互能力:

fd --type directory | fzf --preview 'eza --all --git --long --no-time --color=always --icons {}'

把结果 pipe 给 fzf 后,你会得到一个可交互过滤 + 侧边预览的界面:

television_fzf_example.webp
television_fzf_example.webp

底层发生了什么

执行这条 pipeline 后,fd 会立刻开始扫描。关键点在于:fzf 不会阻塞等待 fd 全部结束。

它使用的是流式架构fd 只要向 stdout 吐出一条路径,fzf 就会从 stdin 立刻读入并更新列表。因此即使后台还在扫几千个文件,你也能几乎瞬间看到可操作的 UI。

--previewfzf 从“文本筛选器”升级为“命令调度器”。

  • 动态替换 {} 是关键占位符。你移动光标时,fzf 会把 {} 动态替换成当前高亮路径(比如 packages/ui)。
  • 子进程执行 每次光标移动,fzf 会启动一个临时 shell 进程执行拼好的命令(如 eza ... packages/ui)。
  • ANSI 透传 因为我们显式设置了 --color=alwayseza 会输出原始 ANSI 转义序列。fzf 在这里相当于一个迷你终端渲染器:捕获这些序列并在侧栏正确还原颜色与图标。

你可能会问:“我快速滚动时,是否会一秒触发 50 次 eza?”

fzf 做了智能 debounce。当你快速移动光标时,它会延迟触发预览,等光标稳定一小段时间再执行;同时会主动杀掉已经过期的 eza 进程,避免 CPU 被无效预览拖垮。

当你选中目标目录并按下 Enterfzf 退出、关闭 eza 预览,并把选中路径输出到标准输出。

这正是 Unix 组合哲学的核心。因为 fzf 输出的是干净文本到 stdout,你可以继续和其他命令拼接,比如直接跳转:

cd $(fd --type directory | fzf ...)

与 Shell 集成

模糊查找器的真正威力在于嵌入 Shell 工作流。你在命令中途按 Ctrl + T,选中文件/目录后结果会直接插入光标位置;不用手打路径,也不用复制粘贴。

如果你不是 bash、zsh、fish(这三者有官方支持),通常需要写 Shell 特定胶水代码。下面是 Nushell 里结合 commandline edit 的配置示例:

{    name: fuzzy_file    modifier: control    keycode: char_t    mode: [emacs, vi_normal, vi_insert]    event: {        send: executehostcommand        cmd: "commandline edit --insert (fd --type file | fzf --preview 'eza --all --git --long --no-time --color=always --icons {}')"    }}

从 fzf 到 Television

到这里你已经看到了 fzf 的机制。它很强,但一旦你跨不同 Shell 使用,就需要维护不同集成脚本。我自己主要在 Windows 与 macOS 上使用 nushell,但偶尔也会用 zsh、bash。继续用 fzf 的话,配置维护成本会持续增长。

Television(tv)的思路是:把复杂性从脚本层搬到配置层。它是一个快速、可移植的模糊查找器,尽可能保证多 Shell 下一致体验:

  • 声明式 Channel: 不再依赖复杂 pipe,把逻辑写进 TOML Channel,更易读、易分享、易版本化。
  • Shell Integration:config.toml 配一次,即可在 bash、zsh、fish、nushell 中获得一致行为(例如 Ctrl + T 智能补全、Ctrl + R 历史搜索),无需手工逐个绑定。
  • 现代化 UX 与可发现性: 它有比较精致的 UI,以及动态快捷键提示栏。这对上手非常友好,你可以边用边学,不需要先死记命令。

快速开始

第一步:安装 Television

为你的系统安装 tv 二进制:

# Windows (Scoop)scoop install television# macOS (Homebrew)brew install television# Linux / Othercargo install television

第二步:下载 Channel

运行 tv update-channels 下载社区维护的 channel。它们是预定义搜索源,告诉 tv“搜什么、怎么展示”。

第三步:Shell 集成

tv 初始化脚本注入你的 Shell 配置。它会注册两个全局快捷键,把 tv 直接接入日常命令流:

# Zshecho 'eval "$(tv init zsh)"' >>~/.zshrc# Bashecho 'eval "$(tv init bash)"' >>~/.bashrc# Fishtv init fish | source # Add to config.fish

Channel

Channels are short configuration recipes that typically dictate what tv should search through and what’s displayed on the screen along with various other options.

Channels | Television

Channel 决定了 tv 搜索范围和结果展示方式,文件位置在 ~/.config/television/cable/

你之前执行的 tv update-channels 会把常用 channel 从社区拉取到本地。

$ tree ~/.config/television~/.config/television├── config.toml├── cable│   ├── alias.toml│   ├── aws-buckets.toml│   ├── aws-instances.toml│   ├── git-repos.toml│   ├── nu-history.toml│   ├── text.toml│   └── zsh-history.toml
依赖要求

  • 某些 channel 依赖额外 CLI 工具,例如 batfd
  • 如果你使用 nushell,建议在 config.toml 里设定 shell = bash/zsh[1],因为很多社区 channel 使用的是 POSIX 兼容 shell 语法。
config.toml
shell = "bash" # 也可以用 zsh

用 Channel 增强工作流

这项能力,也就是智能 Shell 集成,是我从 fzf 切到 television 的主要原因。

不同于静态文件搜索,按下 Ctrl + T 时,tv 会根据你当前命令缓冲区内容自动触发对应 channel,实现上下文感知:

  • 编辑场景: 输入 vimcat 时触发 files channel。
  • 导航场景: 输入 cd 时触发 dirs channel。
  • 进程管理: 输入 killps 时触发 procs channel。
config.toml
[shell_integration.channel_triggers]"dirs" = ["cd"]"files" = ["cat", "vim"]

这种行为由 config.toml 中的 [shell_integration.channel_triggers] 声明。你可以按自己的工作流自定义映射(完整示例可参考我 GitHub 上的 config.toml)。

需要权衡的点

Television 不是所有模糊查找场景下的完美替代。

适合选 tv 的情况:

  • 你经常切换 Shell,想要一致行为
  • 你偏好配置文件而不是脚本
  • 你看重内置 channel 系统对常见搜索任务的覆盖

继续用 fzf 更合理的情况:

  • 你已经有大量高度定制的 fzf 集成,迁移成本过高
  • 你对当前方案很满意,也不需要跨 Shell 可移植性

真正值得注意的是:Shell 工具碎片化会产生隐性维护成本。你今天为 bash 定制的一段 fzf 配置,未来切到别的 Shell 时很可能变成迁移负担。tv 试图在配置层解决这个问题,而不是在脚本层反复补丁。

延伸阅读

如果想深入了解完整能力,建议直接阅读 Television 文档。另外也推荐看 Unix Community Channels,可以快速浏览社区最新集成玩法。

顺带一提,这套文档光从视觉上也值得一看:界面干净,配合像素风 Doto 字体,风格非常鲜明。


  1. Many channel don’t work in nushell · Issue #884 · alexpasmantier/television ↩︎

CompactRelaxed
Normal1.70