WezTermに移行してみている
iTerm2がもっさりしているのと、macOSでしか使えないので、マルチプラットフォーム対応の高速なターミナルエミュレータをいくつか検討している。候補としてはAlacritty、WezTerm、Kittyの3つ
KittyはPythonで設定ファイルを書けるということで以前試してみたんだけれども、日本語の表示周りが壊滅的だったのですぐに捨てた記憶がある。
今日試しに入れてみたらちゃんと表示されていた。
しかしフォントを変更したらなぜか勝手に斜体になり(当然Regularも同梱されているフォント)、意味不明なのでやはり使わないことに。
Alacrittyは設定ファイル等のドキュメントは無い。公式ドキュメントにもあるように、デフォルトで用意されている alacritty.yml
に設定可能な項目と、コメントの形で各フィールドの内容が記載されている。
とりあえずそんなに設定する項目もないので適当に設定を完了。カラースキームはNordが好きなので、Alacritty用にportしているものを見つけてきてコピペ。
プロンプトに関してはstarshipにまかせているので一切設定していない。
Alacrittyでキーバインドを設定しようと思ったけれど
- キーバインドは複数修飾キーを押さないとOSやtmuxやVimのキーバインドを潰しそう
- 出来るアクションが限られている
ということもあって設定をするのを一旦やめた。
Alacrittyの設定を一旦終えたので、次はWezTermの設定をしてみる。Alacrittyとは対象的にWezTermは圧倒的な量のドキュメントがあり、これを個人開発でサポートしているかと思うと頭が下がる。
設定ファイルはLuaで記述する形式で、Luaは書いたことがないけれどなんとなく雰囲気で書けそうなので、とりあえず見てみる。
WezTermのドキュメントは非常に丁寧で、「Luaで記述する」という特殊性でネガティブに判断されたり、心理的障壁を高く感じられないように、行えばいいことを1から記述している。自分もこれでだいぶ安心した。Luaで記述すると言っても、単純にTableをreturnすればそれで良いらしい。
local wezterm = require 'wezterm'
return {
font = wezterm.font 'JetBrains Mono',
color_scheme = 'Batman',
}
公式ドキュメントが非常に丁寧なので、4. Configurationsの項目を上から順番に読みながら少しずつ設定していく。
フォントはKittyやAlacrittyよりも柔軟にフォントのフォールバックの設定が出来るのが良い。フォント周りは各OSでデフォルト環境でも最低これは入っているというフォントファミリーは確実に使ってもらいたいし、自分が追加でインストールするであろうフォントがあればそちらを優先してもらいたい。そのあたりを設定できるのは非常に高評価。
local wezterm = require 'wezterm'
return {
font = wezterm.font_with_fallback {
'Fira Code',
'DengXian',
},
}
特に驚いたのはカラースキームの設定の項目で、デフォルトで700種類以上のカラースキームが設定可能になっている。(実際は700+種類設定可能なのはnightly buildだけで、安定版リリースはできないものもあるが、それでも十分すぎるほど用意されている。)
自分がお気に入りで使っているNordカラースキームもデフォルトで用意されているので、それだけで設定の手間が省けた。
color_scheme = 'nord'
またキーバインドに関してもかなり柔軟に対応出来ることに驚くとともに、沼だなと感じた。
キーバインドがかぶらないようにリーダーキーという概念があるのもだいぶ気に入っている。
local wezterm = require 'wezterm'
return {
-- timeout_milliseconds defaults to 1000 and can be omitted
leader = { key = 'a', mods = 'CTRL', timeout_milliseconds = 1000 },
keys = {
{
key = '|',
mods = 'LEADER|SHIFT',
action = wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' },
},
-- Send "CTRL-A" to the terminal when pressing CTRL-A, CTRL-A
{
key = 'a',
mods = 'LEADER|CTRL',
action = wezterm.action.SendString '\x01',
},
},
}
またキーバインドに関しては既存のアクションだけではなく、自分で自由にLuaでアクションを記述して、それを呼び出せる自由度が気に入った。たとえば、自分がテストで設定してみた、ランダムにカラースキームを変更するキーバインドはこれ。
local wezterm = require 'wezterm'
function random_color_scheme()
math.randomseed(os.time())
local schemes = {
"Atom",
"Builtin Pastel Dark",
"Chalkboard",
"Dracula+",
"Japanesque",
"nord",
"rebecca",
"Wombat",
}
local i = math.random(#schemes)
return schemes[i]
end
wezterm.on('random-color-scheme', function(window, pane)
local overrides = window:get_config_overrides() or {}
scheme = random_color_scheme()
overrides.color_scheme = scheme
window:set_config_overrides(overrides)
end)
keys = {
{ key = 'A', mods = 'CTRL', action = wezterm.action.EmitEvent 'random-color-scheme' },
},
}
これで Ctrl+Shift+a
を押すと、wezterm.action.EmitEvent
が呼び出され、'random-color-scheme'
というイベントが発火される。すると wezterm.on
でそのイベントハンドラーが定義されていて、そこで独自定義の関数 random_color_scheme
が呼び出されたあとに、カラースキームがランダムで入れ替わる。
公式レポジトリに wezterm.lua
自慢スレがあったのでメモ。
wezterm.action.ScrollToPrompt
を使いたくて OSC 133 について調べてるんだけどもいまいちよくわからない。
ここで OSC 133 という仕様に従って実装しているらしいんだけど、ドキュメントにリンクしてある gitlab.freedesktop.org
が落ちていてリンク先のドキュメントが見れない。どうもこのドキュメントによるとシェルが何かしらのエスケープシーケンスを送信することによって、ターミナルエミュレーターがそれを元にプロンプトの区切りを理解する、ということみたいなんだけれども、シェルが差し込まなければいけないのか、適当にプロンプト文字列の中に入れておけば実現できるのかがよくわかっていない。
Starshipを使ってOSC 133を混ぜる方法がわからなかったので質問した。
Starship側で制御するのは一旦諦めてzshで設定することにした。これで ScrollToPrompt
が使える。
実現したいことがどうもうまくできなそうなので(力技でやれば出来るにはできそうだけど)、質問をしてみた。
OSC 133でマークされたときの出力単位(SemanticZone
)ごとにコピーを行うのをキーバインドのみで実現したいとissueを出したらWezが速攻で機能を追加してくれて本当に感謝。
WezTermのnightlyをmacOSでインストールする場合は、homebrewのCaskがレポジトリに設定されているので、それを利用する。
brew tap wez/wezterm
brew install --cask wez/wezterm/wezterm-nightly
キーバインドで、キーテーブルをごそっと変えられるのがなにげに便利だと気づいて使い始めた。Vimでいうところのモードみたいな感じ。たとえば Ctrl+Shift+p
に resize_pane
というキーテーブルを one_shot=false
で割り当てるとあたかもモードに入ったような感じになって、その後 ESC
が押されるまでキーバインドが固定される。
keys = {
{ key = 'p', mods = 'SHIFT|CTRL', action = wezterm.action.ActivateKeyTable { name = 'resize_pane', one_shot = false } },
},
key_tables = {
resize_pane = {
{ key = 'h', action = wezterm.action.AdjustPaneSize {"Left", 1} },
{ key = 'j', action = wezterm.action.AdjustPaneSize {"Down", 1} },
{ key = 'k', action = wezterm.action.AdjustPaneSize {"Up", 1} },
{ key = 'l', action = wezterm.action.AdjustPaneSize {"Right", 1} },
{ key = 'Escape', action = 'PopKeyTable' },
},
},
複雑なことをしようとしたときにキーバインドをシンプルに保てる機能。