你都用什麼編輯器呀?蛤?Kakoune?沒聽過耶 ʕ•ᴥ•ʔ - 編輯器的全婆俠之旅 kakoune & helix 篇
我目前用 kakoune 作為主力編輯器。本文會記錄並炫耀目前的設定。
當編輯器開始變慢,就是換換病發作的時候
承認吧,比起找出問題在哪,軟體工程師更善於砍掉重練。
身為使用 NeoVim 的軟體工程師,每天的日常就是:訂閱 Google 快訊 Neovim plugin 關鍵字,每天刷 Reddit NeoVim subreddit,每小時上 dotfyle 看有沒有什麼最新的 plugin、有空就刷 GitHub neovim topic 、隨時關注新專案。一有新的 plugin,當然第一時間直接裝爆。
至此,我的 NeoVim 已經變的比 Emacs 還要像作業系統,開啟速度比裝滿 300 個擴充功能的 VSCode 還要久。你問我有什麼頭緒,我怎麼會知道?
只好不得不說再見了,NeoVim。
(本段僅供參考,敬請謹慎服用)
「快」是入坑起點,但退坑之因也是速度
去年開始我從 VSCode 換到了 NeoVim ,雖然在 Apple Silicon M1 上 VSCode 已經表現不錯了,但有時會出現的卡頓還是讓人不爽,加上 VSCode 時不時因為不明原因爽吃一波 CPU 讓續航直接下降(你就承認 extension 裝太多不就好了)。
換到 Neovim 的 AstroNvim 發行版後,從 Lazygit 開始,我更熟悉了一系列 TUI Apps。
以 Git 操作為例,原本幾乎所有操作都是在 VSCode 裡面完成(沒辦法,GitLens 和 GitGraph 真是好用),現在反倒多樣化碎片化~~了許多。我會用 fzf 搭上 git、用 Lazygit、用 GitHub 網頁介面、用 GitHub 官方的 CLI 再搭上 fzf、用 Fork、請 GPT4 寫一些輔助的 Git Script 等等。雖然碎片化,但我也透過這個過程多了解了一點點 git 的參數,想必一定對開發效率,有著飛越性、質的提升…吧(?)
用了一陣子才發現 Neovim 效能沒想像中好,lsp 與 UI 互動時而卡頓,開啟大檔案有時甚至比 VSCode 還慢,甚至 UI 直接卡死,Telescope 不小心 fuzzy 到大檔也會卡死。上手設定的過程也沒有那麼順利,中途(aka 日常更新外掛的時候)還需要 workaround 一些 lazy.nvim
的問題。
經過這幾個月的密集使用 NeoVim,以及依照慣例的「花式客製」,我對編輯器有了全新的感受。
快速鍵是帶的走的
「快速鍵」是比較具體的例子,以「編輯的心智模型」來描述更為貼切。從最基礎的 editing motion(以 vim motion 為例就 hjkl/d/visual),到打開編輯器相關附加功能,比如檔案樹瀏覽器、內嵌終端機(ㄑㄧㄢ,謝謝)、快速跳轉檔案、LSP 操作(重新命名、重構)、搜尋與取代等等。
在不同的編輯器,預設的快速鍵都不盡相同,大多都可以自訂,方便不同習慣、不同鍵盤的使用者可以最大化自己的生產力。Command Palette 被發揚光大後也變成了成了標配一般的存在,即使不清楚預設的快速鍵,各個編輯器也都能透過它,方便的發現並使用功能。
畢竟一位真正的工程師,是不會去使用滑鼠的(逃
在體驗不同編輯器的過程中,我對於編輯體驗的認知與操作慢慢擴張,最終內化成一套屬於自己的系統。沒辦法,誰叫 AstroNvim 的預設快速鍵那麼合理又好記憶![1]
最終,我會成為編輯器界的全婆俠![2]所有編輯器,都是我的翅膀![3]我要把我的編輯器自訂天賦,帶到所有編輯器![4]
Helix 設定之旅
我先嘗試使用 Helix 作為我的主力編輯器。
Helix 是個內建功能齊全的終端機介面編輯器,內建 tree-sitter、LSP 整合、內建介面類似 Telescope 的 Command Palette,性能絕佳,用起來幾乎不會感受到有什麼卡頓。唯一的敗筆就是擴充性比較低,目前還沒有外掛系統(Plugin System)可用,但你還是可以透過它提供的兩種功能來做到一點點的擴充:
- Shell command
- Shell pipeline
Shell command 簡單來說就是執行外部程式;Pipeline 就和常用的命令列管道一樣,可以把編輯器的內容,變成外部程式的輸入。比如程式碼的格式化(Formatting),就是把編輯的文字內容丟給格式化程式(Formatter)。
Helix 提供的這兩個方法簡單有效率,比如開啟 Lazygit 或其他外部程式,都能用很簡單的方式整合進編輯器了,但 Helix 提供給外部程式的資訊其實相當有限。比如想要知道某一行程式碼的 git blame
,那「檔案路徑」、「行號」等,都是必要資訊,但 Helix 除了內容外就沒有其他資訊了,這就讓某些整合窒礙難行。
不過會看我這樣寫,想必是有什麼解法了吧 XD
運用終端機多工器(Multiplexer)[5] 來獲取編輯器狀態資訊
既然 Helix 不給,那我們就從畫面上,也就是 Helix 的 TUI 產生的文字拿,總可以了吧。
這個解法我是在 Quan Tong 的部落格看到,而他是在 helix 的 subreddit 看到。解法如下:
- Helix 的狀態列會顯示目前開啟檔案的路徑,與游標資訊
- 用 Tmux/Kitty/Wezterm/zellij 的 API 拿到畫面上的所有文字 (
get-text
) - 用 Regex 把檔名和游標資訊擷取出來
- Works like a charm! 🎉
雖然很神奇,但我腦袋告訴我這鐵定不穩定。比如想要狀態列樣式時,或是視窗寬度不足,而導致狀態列的文字被刪減縮短。各種狀況都會讓這條 Happy path 直接失敗。
與 Helix 配合使用檔案樹
去年看到 Helix File Tree 的 PR 想說快要合併了,可以期待一下。結果結論是超出 Helix 想實作的範圍,直接不合併。好吧,那我只好找個 TUI 的檔案樹湊合湊合了。我先是嘗試了 nnn 和 vifm [6],最後在 broot 定了下來。
那外部的檔案樹就要怎麼配合 Helix 使用?
一樣有點腦漿炸裂[7]的解法。因為 Helix 的架構設計,你無法在其他 process 去操控編輯器的行為,比如告訴哪個編輯器實體去開啟某個檔案。但你一樣可以透過終端機多工器的 API!
- 利用 tmux/wezterm/kitty/zellij 的 API 檢查檔案樹右側面板 (panel)是否有 Helix 開啟
- 若沒有:用
hx $filepath
指令開啟一個新面板 - 若有:用
send-keys
傳送按鍵模擬:e $filepath
到該面板
聰明的你也想的到了,這種方式同樣沒有那麼穩固。只要右側面板的 Helix 不在一般模式(Normal mode),比如在輸入模式,那這套方法一樣不管用。
身為編輯器真理的探求者,看到有這麼多問題的整合方式,自然不會滿足於此。於是,我向啟發 Helix 設計的 OG 編輯器:Kakoune — 發起了挑戰![8]
有如瘋狂科學家[9]的執念之作:Kakoune
Kakoune 和 Vim 系編輯器最大的差異就是快速鍵,需要將原本的肌肉記憶「擴充」一下。注意我這邊用的詞是擴充,因為既有的 vim 還是會在各種地方用到,所以我還是會根據環境切換。
在拜讀了 hadronized 的 Even more hindsight on Vim, Helix and Kakoune 一文後,我下定決心給 Kakoune 一個嘗試。
hadronized 是 This week in Neovim (TWiN) 的前維護者。去年我回鍋 Neovim 後有好一陣子,TWiN 都在我的每週追番清單裡面。也是他把 Tree Sitter 帶到 Kakoune 的,實在是一位有夠強的開發者。
Kakoune 有自己一套完整的設計理念,把自己精確的定義在「程式碼編輯器」這個範疇。IDE 各式工具內建整合?不做的。檔案瀏覽器?不做的。視窗分割管理?不做的。
那這些不做的功能怎麼辦?Kakoune 從一開始就最大化了「可組合性」(Composibility)。Helix 上述的兩種外部溝通方式可以說是從 Kakoune 來的,而 Kakoune 也把這套組合性最強化。
Kakoune 實作了 Client/Server 的架構,你可從不同 process 連到同一個編輯器 Session,同時編輯同一個 buffer。多視窗支援?只要在不同視窗開啟 Kakoune 連線到同一個編輯 Session 即可。跨程式的互動?直接向 Session 送指令。
Kakoune 穩定又小,保持良好的效能,API 也算是穩定,比較不會有那種一週修一次設定檔的情況(對,我就是在說 NeoVim)。編輯器目前約半年一更版,外掛程式雖然生態系小,但是因為 Kakoune 的設計理念,所以外掛的實作也趨向 shell script 為主,比較複雜的外掛,比如 lsp、tree-sitter 等,社群偏向利用 rust/go/crystal 這種可以編譯成二進位執行檔的語言來實作。
下面就來展示目前我在 Kakoune 中設定折騰出來的的各種「現代編輯器」的體驗。
在 Kakoune 中體驗現代編輯器的功能
Floating window with tmux-popup
請參考我的前一篇文章 - 不會關掉的 tmux popup。完全取代了 ToggleTerm 功能,還能在編輯器以外的地方使用,更加通用。
Git 操作
Kakoune 內建了一系列 git 操作整合,但我其實更常用 Lazygit。Lazygit 可以經過擴充設定,來支援 Conventional commit、GitHub pull request 整合、AI commit message 等功能,更加與編輯器解耦。
對於快速複製程式碼的 GitHub Permalink,我甚至實作了用 Crystal 語言寫的 gitlinker.cr。
更多 fzf 相關功能
多虧了 kakoune 社群大大實作的 kks,外部腳本可以方便的與 kakoune 互動,拿取資料、傳送指令。下面就是一些透過 fzf 實作出類似 Command Palette 的介面。
使用 broot 作為檔案瀏覽器
Language server support via kak-lsp
在去年十一月之後,kak-lsp 支援了同時跑多個 lsp server 的功能。以 JavaScript/TypeScript 開發來說,我可以同時跑 tsserver、css/scss、tailwind、eslint、emmet 等等,應用變的實際許多。最近也有相關的 AI lsp 相關開發,比如 helix-gpt、lsp-ai 等等,也讓 kakoune 有某種程度上的 copilot 替代(阿當然還是比不上 VSCode/Zed/NeoVim 這種原廠級支援度的)。
當然 kak-lsp 因為編輯器本身的限制,還是缺少一些支援,比如 ghost text (inline type annotation),floating hover card 等。一切體驗感覺都會更原始一點。
A more composable editor, a more complete life
所謂編輯器的獨特性也只是軟體工程師彰顯身價的炫耀財,平平都是打工人,也只能在那微小有限之處彰顯自己的不平凡(暴論)
Kakoune 精簡快速核心的哲學打動了我。除了編輯以外的功能通通委外的哲學,對於我這種 TUI 工具控,也提供了很好的擴充和掌握性,想要什麼、不想要什麼,自己換掉就好,有時遇到 bug,開 PR 貢獻 lsp 或是編輯器,自然也是不在話下…QQ(阿怎麼哭了)
Kakoune 的使用者就是沒那麼多,自然生態系也小了許多。目前比較熱鬧的地方在 Discord 伺服器,問問題都會很快的得到回應。
I use Kakoune btw
希望這句話成為繼「I use Arch btw」之後,最 Geek 的一句自我介紹,共勉之 XD
lazyvim 也不錯啦 ↩︎
THE 迪西遜,雖然還是會一直拿來當梗,但老漢的強大家都懂 https://www.wikiwand.com/en/The_Decision_(TV_program) ↩︎
vifm 也有官方的 helix 整合方式,不過要使用 tmux https://github.com/vifm/vifm/tree/master/data/plugins/editor ↩︎
此處意指 Mind-blowing,附上脳漿炸裂ガール,給有時還會聽聽 V 家的各位 https://www.youtube.com/watch?v=Ey_NHZNYTeE ↩︎
瘋狂科學家的比喻是來自於 By Default 這個 YouTube 頻道。雖然頻道只有寥寥數片,但第一部片就因為演算法之力突破 50 萬觀看。順暢的口白,幽默的音調,還有各種哏的參照,哼,有趣的男人,你引起我的注意了!他也有評價 Kakoune 編輯器的影片,也是蠻值得一看的。 ↩︎