Fish,全称 "the friendly interactive shell", 是一款用户友好、功能强大的 shell,以其开箱即用的特性和美观的界面而闻名。2月27日,Fish 迎来了 4.0 版本的重大更新,官宣地址
https://fishshell.com/blog/new-in-40
。本次更新不仅带来了诸多新特性和改进,更是在底层架构上完成了从 C++ 到 Rust 的彻底重写。
Fish 最初是用 C 编写的,后来移植到 C++,而这次是从 C++ 到 Rust 的重大转变。这次重构的意义在于:
-
增强安全性:Rust 语言以其内存安全特性而著称,可以有效避免 C++ 中常见的内存泄漏、空指针等问题。
-
提升开发效率:Rust 拥有现代化的工具链和友好的错误提示,能够显著提高开发效率。
-
改善并发性:Rust 在并发编程方面具有优势,为 Fish 未来实现真正的多线程执行奠定了基础。
Fish 4.0 中移除了大约 57,000 行 C++ 代码,并新增了大约 75,000 行 Rust 代码。这次重写工作历时近两年,涉及 1155 个文件,超过 20 万行的增删代码。尽管工作量巨大,但 Fish 4.0 在功能和使用体验上依然保持了稳定。为什么 Fish 团队要这样大刀阔斧地重写?
变化的原因
Fish 4.0 的变化并非凭空而来,据 Fish 团队的介绍,是出于下面的原因:
-
C++ 的局限性
:C++ 在工具链、开发体验和安全性方面存在一些问题,例如 C++ 编译器的升级困难、头文件管理繁琐、容易出现内存错误等。C++ 的工具生态不够完善,升级编译器比较麻烦,而且 C++ 本身在开发体验设计上存在不足,字符串处理繁琐且容易出错。
-
Rust 的优势
:Rust 在工具链、
开发体验
和安全性方面具有优势,例如 Rust 拥有强大的包管理器
cargo
、友好的错误提示、内存安全保证等。Rust 拥有出色的工具链,
rustup
可以轻松安装和管理 Rust 环境。Rust 在开发体验方面也表现出色,例如 Rust 的
Option
类型可以显式地处理空指针情况。
-
并发的需求
:Fish 希望在内部命令的执行中实现真正的多线程并发,而 C++ 在这方面存在一些难以解决的问题。Rust 的
Send
和
Sync
特性可以静态地强制执行线程安全规则,从而更容易实现并发。
-
吸引更多贡献者
:Fish 团队希望通过使用 Rust 这种更现代、更流行的语言来吸引更多的贡献者。
-
终端集成的需求
:为了更好地与各种终端集成,Fish 需要更灵活地处理键盘输入和输出。
-
用户反馈
:Fish 4.0 的许多新特性和改进都来自于用户的反馈和建议。
4.0 版本的功能变化
除了底层代码的重构,Fish 4.0 还带来了许多值得关注的新特性和改进:
改进的键盘绑定
-
引入了一种全新的键盘绑定语法。用户可以使用
bind ctrl-right
或
bind alt-backspace
这样更直观的方式来绑定按键,而无需使用
bind \e\[1\;5C
这种难以理解的转义序列。
-
增强了对组合键的支持。通过启用
xterm
的 "modifyOtherKey" 和
kitty
键盘协议等终端特性,Fish 可以区分
ctrl+i
、
ctrl+shift+i
和
Tab
键。
改进的命令行体验
-
现在可以更好地与终端集成。Fish 使用 OSC 133 序列来标记提示符和命令输出,从而与终端的 shell 集成脚本更好地协同工作。
-
修复了长命令行的显示问题。现在,即使命令行长度超过屏幕宽度,Fish 也能正确滚动显示。
-
commandline
命令的更改会立即生效。例如,
commandline -i foo
会立即将 "foo" 插入到命令行中。
-
ctrl-r
历史记录搜索现在支持 glob 语法。例如,
git*HEAD
将搜索包含 "git" 和 "HEAD" 的历史记录条目。
支持自定义命令历史记录
允许用户通过定义
fish_should_add_to_history