kitty 是一个 GPU based terminal, 这类terminal 并不少, 比如老灯目前在用的 Alacritty.

kitty 可以说是, 老灯无意中安装上的, 今天本来想卸载它的, 结果把玩了一下, 发现这玩意设计上和性能上都不错.并且 文档齐全, 开发活跃.

Alacritty 出生就自带 Rust 光环, 当前 star 数量约 37.8K. kitty 当前 star 数量才接近 13.9K.

当然, 这个 star 数量并不能说明什么, 因为 Rust 拥有众多的 Rustaceans (老灯也是铁杆 Rustacean) , 以 Rust 光环, 加上 “the fastest terminal emulator” 的营销口号, 获取 star 数量确实不在话下.

当然, kitty 也不是什么 Hello Kitty, 而是实实在在的一个功能完备的终端. Alacritty 在我看来, 只是配合 tmux 使用的一个辅助工具. 离开了 tmux 的 Alacritty 对我来说, 毫无用处, 甚至不如 Gnome Terminal.

我想有必要写文章分享一下 kitty 这么优秀的软件. (鉴于 kitty 的作者是如此低调)

很多时候, 你喜欢一个语言, 自然而然的会希望你手里用的工具都是基于这个语言的. 老灯便是如此. 但是今日试用了 kitty, 老灯觉得, 语言是不是 Rust 已经不重要了. kitty 的魅力足够让我抛弃语言之类的偏见.

kitty 具备完整的功能, 而 Alacritty 别说支持分屏了, 连最基本的多 tab 都不支持. 所以, 应该没有人直接用 Alacritty, 基本上都是搭配 tmux 之类的终端复用器来使用.

关于 terminal multiplexers

terminal multiplexers 的典型代码当然是 tmux 了, 当然, 这里是泛指这一类程序.

作者认为, terminal multiplexers 是一个 bad idea.

First, terminal multiplexers are  a bad idea, do not use them, if at all possible. kitty contains features that do all of what tmux does, but better, with the exception of remote persistence ( #391). 

In summary: multiplexers add unnecessary overhead, suffer from a complexity cascade, because they actually have to translate escape codes, modifying them in hackish ways to get them to work with their concepts of windows/sessions.

Energy/performance wise they are poison, every byte has to be parsed twice, once by the middleman and once by the terminal. And they act as a drag on the ecosystem as a whole, making it very hard to get any new features. Designing features becomes harder because you have to design for compatibility with a horrible hack and the diffusion into the ecosystem tends to get gated by basically a handful of individuals with, let’s say, very limited vision.

机器翻译下吧:

首先,终端多路复用器是一个坏主意,如果可能的话,不要使用它们。kitty 包含的功能做了Tmux 所做的一切,但更好,除了远程持久化(#391)。

总结:多路复用器增加了不必要的开销,遭受了复杂的级联,因为它们实际上必须翻译转义代码,以黑客的方式修改它们,以使它们与它们的窗口/会话概念一起工作。

能源/性能方面,它们是毒药,每一个字节都要被解析两次,一次由中间人解析,一次由终端解析。而且它们是整个生态系统的拖累,使其很难获得任何新功能。设计功能变得更加困难,因为你必须为兼容一个可怕的黑客而设计,而且扩散到生态系统中往往会被一小撮具有非常有限的视野的人所阻止。

所以, 当你用着 tmux 还觉得它很高级的时候, 事实上它是一种很古老的东西, 从设计上来说, 它并不优雅, 只是解决了需求问题. 作为 tmux + Alacritty 用户, 其实一直也没深入了解 tmux 的实现, 今天读到 kitty 作者的这段话, 奇怪的知识又增加了.

性能

kitty 的核心部分采用 C 编写, UI 界面采用 python 以方便扩展.

这里老灯采用这个脚本进行一个简单的测试(from https://github.com/alacritty/alacritty/issues/289#issuecomment-340283908):

for i in {1..400000}; do
  echo -e '\r'
  echo -e '\033[0K\033[1mBold\033[0m \033[7mInvert\033[0m \033[4mUnderline\033[0m'
  echo -e '\033[0K\033[1m\033[7m\033[4mBold & Invert & Underline\033[0m'
  echo
  echo -e '\033[0K\033[31m Red \033[32m Green \033[33m Yellow \033[34m Blue \033[35m Magenta \033[36m Cyan \033[0m'
  echo -e '\033[0K\033[1m\033[4m\033[31m Red \033[32m Green \033[33m Yellow \033[34m Blue \033[35m Magenta \033[36m Cyan \033[0m'
  echo
  echo -e '\033[0K\033[41m Red \033[42m Green \033[43m Yellow \033[44m Blue \033[45m Magenta \033[46m Cyan \033[0m'
  echo -e '\033[0K\033[1m\033[4m\033[41m Red \033[42m Green \033[43m Yellow \033[44m Blue \033[45m Magenta \033[46m Cyan \033[0m'
  echo
  echo -e '\033[0K\033[30m\033[41m Red \033[42m Green \033[43m Yellow \033[44m Blue \033[45m Magenta \033[46m Cyan \033[0m'
  echo -e '\033[0K\033[30m\033[1m\033[4m\033[41m Red \033[42m Green \033[43m Yellow \033[44m Blue \033[45m Magenta \033[46m Cyan \033[0m'
done

机器环境为 X11 + Nvidia + ArchLinux

Intel i9-9900 (16) @ 4.000GHz

Resolution: 3840x2160

  • Alacritty 0.10.1 (2844606d) + tmux 3.2a 17s
  • kitty 0.24.324s
  • GNOME Terminal 3.42.2 using VTE 0.66.2 24s
  • Wez Terminal 20220101-133340-7edc5b5a 44s

Wez Terminal 是真的卡. 跟 Alacritty 一样同样是 Rust 写的东西, 怎么速度上差这么多呢? 所以, 语言并不能决定性能. 还得看你怎么写的.

关于 WezTerminal 的性能差的问题, reddit 上 两年前就有人提了, 没想到两年后还是这样.

配置

kitty 基本上是开箱即用的.

但是由于我是一个 Alacritty + tmux 用户, 因此自然希望, 习惯上的很多快捷键能得以保留.

折腾好的配置在这: https://github.com/ttys3/my-kitty-config

默认的kitty_mod ctrl+shift 保留下来了.

注意不要试图将 kitty_mod 设置成 ctrl+a , 这是不会工作的. 因为 kitty_mod has to be modifiers not keys. see https://github.com/kovidgoyal/kitty/discussions/3457#discussioncomment-587511

You can download a sample kitty.conf file with all default settings and comments describing each setting by clicking:  sample kitty.conf.

Kittens

kitten意为"幼猫", 而 kitty 是"猫咪" 的意思. 这个取名也相当有意思.

kittens 相当于 kitty 的插件. 内置的所有 kittens 可以在这里找到: https://sw.kovidgoyal.net/kitty/kittens_intro/

diff

老灯觉得这个 kitty-diff 显示的色彩效果是真的好, 咋一看以为打开了 gui 的 meld.

使用方法:

kitty +kitten diff file1 file2

甚至还可以集成到 git, 将以下配置添加到 ~/.gitconfig 中:

[diff]
    tool = kitty
    guitool = kitty.gui
[difftool]
    prompt = false
    trustExitCode = true
[difftool "kitty"]
    cmd = kitty +kitten diff $LOCAL $REMOTE
[difftool "kitty.gui"]
    cmd = kitty kitty +kitten diff $LOCAL $REMOTE

diff 功能老灯对比了一下同是 python 实现的 meld, 发现 meld 的 diff 能够区分同一行的不同字符的变动, 而 kitty 的并不能, 以下是对比图:

另一个问题是, 在 dark terminal colorscheme 下面, kitty 默认的白色背景的 diff 结果显得怪怪的, 这里有一个黑色版的, 不过老灯看着也不是很满意, 还不如直接用白色背景版的.

目前来说, delta 的 diff 效果和配色默认用着也挺舒服的. 所以在kitty diff 功能改进之前, 老灯还是继续用 delta.

icat

icat 可以直接在 kitty 里面显示图片, 老灯直接用 4k 图片测试过了, 显示效果相当好.

ImageMagick must be installed for icat to work.

alias icat="kitty +kitten icat"

themes

themes 可以让你即时预览主题效果, 并支持一键切换.

kitty +kitten themes

https://github.com/trygveaa/kitty-kitten-search

这是一个第三方的 kitten

Troubleshooting

1. zoom panel 功能

kitty 并没有像 tmux 一样自带这个功能, 但是其扩展能力极强, 实现这个非常轻松.

参考 https://sw.kovidgoyal.net/kitty/kittens/custom/#using-kittens-to-script-kitty-without-any-terminal-ui

在 kitty 配置目录下创建文件 ~/.config/kitty/zoom_toggle.py, 内容如下:

def main(args):
    pass

from kittens.tui.handler import result_handler
@result_handler(no_ui=True)
def handle_result(args, answer, target_window_id, boss):
    tab = boss.active_tab
    if tab is not None:
        if tab.current_layout.name == 'stack':
            tab.last_used_layout()
        else:
            tab.goto_layout('stack')

注意, stack layout 必须要 被允许.

The first layout listed in enabled_layouts in kitty.conf will be the default

ref https://github.com/kovidgoyal/kitty/issues/2258#issuecomment-571201141

老灯现在的配置是 enabled_layouts splits,stack

实现这一功能的 issue 在这 https://github.com/kovidgoyal/kitty/issues/870#issuecomment-429313856

通过 提交记录发现, 作者实现这一功能的支持, 只改动了几行代码. 不得不佩服.

2. session 保存和加载

已经有讨论, 但是并无进展:

https://github.com/kovidgoyal/kitty/issues/1197#issuecomment-785435558

在 tmux 里面, 我们可以使用 tmux-plugins/tmux-resurrecttmux-plugins/tmux-continuum 两个插件实现自动 dump 和 加载 session

kitty 这边目前好像还没有这样直接就拿来能用的插件方案.

kitty 内置了 session 支持, 也就是说它支持 session restore, 但是 dump 这一方便好像没有比较官方的支持.

如果能在退出时自动 dump 出可以直接用于 restore 的 session 配置, 那么其实这个功能就会比较好实现了.

静态 session 配置比较简单: https://github.com/ttys3/my-kitty-config#session-restore

dump 功能目前有 第三方实现可用: https://github.com/kovidgoyal/kitty/issues/1197#issuecomment-785435558

注意 kitty @ ls 需要开启 allow_remote_control yes (改这个需要重启kitty, reload 配置不会生效)

3. status line

老灯 tmux 下的 status line 大概长这样:

这个不是刚需, 而且, 可以采用 DE 顶部的 status line 解决

kitty 有 panel 貌似可以实现类似的功能: https://sw.kovidgoyal.net/kitty/kittens/panel/

不过我一直没能让它显示出来…

搞笑的是, 有人问这个作者, 文档里面的 demo 脚本, 作者回答这个涉及隐私信息不能给你 Orz

https://github.com/kovidgoyal/kitty/issues/2523

lol. wtf? A sensitive status command? this is a first.

4. terminfo 问题

如果你尝试ssh到远程机器, 可能会发现你本机的zsh报错:

/home/user007/.zsh_compatible:bindkey:2: cannot bind to an empty key sequence

这个问题其实不只存在于 kitty, 任何有自己独立的 terminfo 的 terminal (且其信息没有在ncurses中内置), 基本上都会有这个问题. 比如 Alacritty 也有这个问题.

这个问题官方faq文档里面也有说明: I get errors about the terminal being unknown or opening the terminal failing when SSHing into a different computer?

This happens because the kitty terminfo files are not available on the server. You can ssh in using the following command which will automatically copy the terminfo files to the server:

kitty +kitten ssh myserver

This ssh kitten takes all the same command line arguments as ssh, you can alias it to ssh in your shell’s rc files to avoid having to type it each time:

alias ssh="kitty +kitten ssh"

https://github.com/kovidgoyal/kitty/issues/879

有人建议提交 xterm-kitty terminfo 到 ncurses 数据库, 这样ssh到安装了较新的 ncurses 的系统上便不会有识别不了xterm-kitty 的问题.

不过这个作者说, ncurses 那边的人不喜欢他, 不给它集成进去. 2018年的issue, 现在2022年了, 确实是件难事哈.

https://github.com/kovidgoyal/kitty/issues/879#issuecomment-419686348

So to summarize the ncurses maintainer’s response:

  1. He does not like kitty’s license (I’m happy to change the license of just the terminfo file to CC license, if needed)
  2. He does not like kitty TERM variable. This is not going to change as it would break lots of programs that turn on various features when they see a TERM variable of the type xterm-whatever. A situation that was created by the ncurses maintainer refusing to add new capabilities for various things.
  3. He does not like the fact that kitty has introduced new capabilities into the terminal ecosystem

About what I expected from my previous interactions with him. He excels at presenting excuses to maintain the status quo. I’m afraid I am not interested in tying kitty to this particular boat anchor. There’s a reason the terminal ecosystem has stagnated for so long, and ncurses is a big part of that stagnation.

使用 kitty +kitten ssh 之类的方式连接也是挺蛋疼的. 老灯干脆让它标榜自己为 xterm-256color 算了, 就像我给 Alacritty 设置的一样. 另外, Gnome Terminal 也是用的 xterm-256color , 所以, 这个应该问题不大.

编辑 kitty.conf设置 term xterm-256color 即可.

ref: https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.term

5. kitty 误变成 inode/directory 的默认打开程序

不知是我手抖误设置了还是 kitty 安装的时候设置的.

经过检查, 发现 /usr/share/applications/mimeinfo.cache 文件中 inode/directory 的值变成了 kitty-open.desktop 跑在了 org.gnome.Nautilus.desktop 的前面.

inode/directory=kitty-open.desktop;org.gnome.Nautilus.desktop;vifm.desktop;visual-studio-code.desktop;

当然, 我们不用动/usr/share/applications/mimeinfo.cache这个文件, 编辑 ~/.config/mimeapps.list 加上下面这一行即可修正:

inode/directory=org.gnome.Nautilus.desktop

目前缺少的功能

  1. copy mode / vim mode

see https://github.com/kovidgoyal/kitty/issues/1698

Refs

kitty icon 来自 https://github.com/DinkDonk/kitty-icon

Unicode 7.0 text characters aren’t displayed / too wide #3312

https://sw.kovidgoyal.net/kitty/overview/#design-philosophy

https://sw.kovidgoyal.net/kitty/kittens_intro/#kittens

https://sw.kovidgoyal.net/kitty/kittens/themes/#how-it-works

https://sw.kovidgoyal.net/kitty/overview/#other-keyboard-shortcuts

https://sw.kovidgoyal.net/kitty/conf.html#opt-kitty.enabled_layouts

https://github.com/dflock/kitty-save-session

https://github.com/trygveaa/kitty-kitten-search