Neovimにecho APIを追加した

1 min read読了の目安(約1600字

Neovimにメッセージを表示するだけのAPIを追加した。

https://github.com/neovim/neovim/pull/13673

地味だがAPIの追加自体が新鮮な体験だったので簡単に紹介する。

使い方

以下のようなAPIになっている。

nvim_echo({chunks}, {history}, {opts})

chunksには[text, hl_group]の配列(virtual_textと同様)、
historyにはmessage-historyに残すかどうかのブール値を与える。
(optsは将来の拡張のために空けてあるだけ)

つまりecho系のコマンドをまとめて扱える。(echoerr以外)

vim.api.nvim_echo({
  {"This is a "},{"warning", "WarningMsg"},{" message.\n"},
  {"NOTE: This is a comment.", "Comment"},
}, true, {})

同じメッセージをコマンドで出すのは結構大変。
(echonはmessage-historyに残らないのでAPIと同じ挙動にはならない)

vim.cmd("echon 'This is a '")
vim.cmd("echohl WarningMsg")
vim.cmd("echon 'warning'")
vim.cmd("echohl None")
vim.cmd("echon ' message.\n'")
vim.cmd("echohl Comment")
vim.cmd("echon 'NOTE: This is a comment.'")
vim.cmd("echohl None")

⚠ このAPIで出力されたメッセージは:messagesでのhighlightにまだ対応していない。
修正するissueは作ったのでゆるりとやる予定。

実装した感想

C言語慣れしてなくてもツールの力でハードルが下がってなんとかなった。

CONTRIBUTING.mdにあるがCC=clang make CMAKE_FLAGS="-DCLANG_ASAN_UBSAN=ON"でビルドしたものを使うと、
メモリリークしてる箇所を教えてくれる。

早めにテストを書き、test/README.mdにある方法で関係するテストだけを実行して、
ASanとテストに怒られながら実装するのが効率いいんじゃないかと思った。
以下のように環境変数で実行するテストを絞れる。
TEST_FILE=test/functional/api/vim_spec.lua TEST_FILTER=.*nvim_echo.* make functionaltest

また、ビルドするとbuild/compile_commands.jsonが生成されるのでclangdが使える。
プロジェクトルートにcompile_commands.jsonへのシンボリックリンクを作成するとnvim-lspで問題なく動く。

結局大変だったのは、C言語うんぬんよりグローバル変数の意味を読み解くことだった。
これは気合で読むか知ってる人に聞くしかない気がしている。

何にせよC実装部分をいじっての機能追加が無理でないとわかって嬉しい。
DraftでPR作った段階でbfredl氏がインターフェースを決めるためのコメントをくれてやりやすかった。
とても感謝。