Neovim Lua standard library を試せる簡易的な REPL を作ってみた
はじめに
Neovim プラグインを作成していると Neovim Lua standard library の関数がどのように動作するのか試したくなることがあります。
こういった場面では REPL が便利ですが、Neovim には Lua REPL を呼び出す機能がなさそうだったため、Neovim 上で使える簡易的な REPL を作成しました。
内部
基本的には buffer に書き込まれた Lua プログラムを Lua の loadstring
関数に渡しているだけです。
loadstring
関数は文字列で書かれた Lua プログラムの内容を wrap した関数を返してくれる関数です。たとえば、loadstring('a = 1')
は function() a = 1 end
と等価です。
複数行に渡るものも評価してくれるため loadstring(vim.fn.join(vim.api.nvim_buf_get_lines(bufnr, start_line, end_line, false), '\n'))()
とするだけで buffer に書いた Lua プログラムを実行できます。
ただ、これだけだと print
の出力を :message
で確認しに行かねばならず手間なので loadstring
実行前に print
関数を「引数を保存しておく関数」に置き換えておいて、保存した内容を最終的にプログラムを書いている buffer に出力するようにしました。既存の関数を上書きするのはあまりお行儀の良い方法とは思えませんが他に方法が思いつかなかったためこの方式にしました。
local output = {}
print = function(...)
local args = { ... }
-- 各引数を文字列化して改行で結合
table.insert(output, table.concat(vim.tbl_map(vim.inspect, args), '\n'))
end
試そうとして諦めたこと
素の Lua REPL を起動して Neovim Lua standard library を読み込むことも考えましたが、どのように読み込むと Neovim で実行するときと同じ参照の仕方にできるのかわからなかったため、loadstring
で評価する方式にしました。
類似のプラグイン
類似のプラグインとして以下の2つを見つけましたが、私の使用方法には合わなかったため今回は使用を見送りました。
ii14/neorepl.nvim
Neovim 上で使える汎用的な REPL プラグインで、Vim script にも対応しています。また、nvim-cmp を利用した補完機能も備えており、とても高機能です。
ただし、ブロックを成していないものは 1 行ずつ評価される仕様のため、複数行にまたがるコードを書く際には不便でした(1行ずつ評価されてしまうので local
で定義した変数が参照できない)。私の用途では、プラグインのコードをコピペしてそのまま動作確認したい場面が多いため、今回は使用を見送りました。
rafcamlet/nvim-luapad
コードがリアルタイムで評価され、結果が virtual text として表示されるプラグインです。プラグインを書きながらリアルタイムで動作確認したい場合に便利そうです。
しかし、私は Lua にあまり慣れておらず、リアルタイムで評価されると誤ったコードを書いた際に Neovim をハングさせてしまいそうだったため、こちらも使用を見送りました。
Discussion