🐙

Neovim Lua standard library を試せる簡易的な REPL を作ってみた

に公開

はじめに

Neovim プラグインを作成していると Neovim Lua standard library の関数がどのように動作するのか試したくなることがあります。
こういった場面では REPL が便利ですが、Neovim には Lua REPL を呼び出す機能がなさそうだったため、Neovim 上で使える簡易的な REPL を作成しました。

demo

https://github.com/goropikari/lua-repl.nvim

内部

基本的には 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 プログラムを実行できます。

https://www.lua.org/pil/8.html

ただ、これだけだと print の出力を :message で確認しに行かねばならず手間なので loadstring 実行前に print 関数を「引数を保存しておく関数」に置き換えておいて、保存した内容を最終的にプログラムを書いている buffer に出力するようにしました。既存の関数を上書きするのはあまりお行儀の良い方法とは思えませんが他に方法が思いつかなかったためこの方式にしました。

置き換える print の実装
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 をハングさせてしまいそうだったため、こちらも使用を見送りました。

GitHubで編集を提案

Discussion