nvim の nvim-dap で lua をデバッグするべく自分で書いてみた。 手頃なのが見つからなかったので。

github.com
github.com favicon https://github.com/ousttrue/my_nvim/blob/master/luada.lua

https://microsoft.github.io/debug-adapter-protocol/ の自前実装。

request のうち initialize, launch, setBreakpoints, configurationDone, threads, stackTrace, scopes, variables, continue, next を実装した。 event のうち initialized, exited, stopped(breakpoint, step) を実装した。

これで最低限の breakpoint を設定して止める、ステップ実行、変数表示までできた。

ログレベルを設定して

require('dap').set_log_level('trace')

nvim の :lua print(vim.fn.stdpath "cache") に配置される dap.log を観察したらだいたいできた。

nvim-dap の設定は以下。

local dap = require("dap")
local luada = vim.api.nvim_get_var("my_nvim_root") .. "/luada.lua"
-- luada adapter を登録
dap.adapters.luada = {
-- debug用のスクリプトを lua で実行し、標準入出力で DAP 通信(JSON-RPC)を開始する
type = "executable",
command = vim.api.nvim_get_var("my_nvim_root") .. "/neovim/.deps/usr/bin/luajit.exe",
args = { luada },
}
-- filetype lua のときに luada を使用する。launch の引数
dap.configurations.lua = {
{
name = "lua debug adapter",
type = "luada",
request = "launch",
program = "${fileDirname}\\${file}",
args = { "a", "b", "c" },
},
}
+---------+ DAP +--------------------+
| nvim dap|------->stdin |luajit.exe luada.lua|
| |<-------stdout| |
+---------+ +--------------------+
+==> loadscript(target_lua_script)

入出力を DAP で占有してしまうので、それでも大丈夫なスクリプトしかデバッグできない。 (print 関数は、stderr に出力するように退避したので、dap.log には出る)

素の standalone の lua interpreter で簡単にできる範囲で実装する方針。

はまりポイント

Windows 版 は、io.stdoutCRCRLF に変換されるのを回避できない。

setmode(_fileno(stdout),_O_BINARY);

を lua で呼び出す手段が無い。

Content-Leght: 123\n\n

と出力して変換されるのに任せることにした。

debug.sethook 内で coroutine.yield できない

Lua debug hooks seems to prevent the coroutine from working
So, I'm trying to build a multitasking system in lua that hands control back to the main thread at regular intervals. The issue is that debug.sethook seems to cause the coroutines to die immediatel...
Lua debug hooks seems to prevent the coroutine from working favicon https://stackoverflow.com/questions/54858455/lua-debug-hooks-seems-to-prevent-the-coroutine-from-working
Lua debug hooks seems to prevent the coroutine from working

breakpoint 等によるスクリプト中断を coroutine.yield で実装しようとしたのだけど断念した。 (yield すると suspend にならずに dead になる)

https://github.com/tomblind/local-lua-debugger-vscode は、coroutine で実装しているような気がするのだが・・・。

yield する代わりに main.loop をネストさせてそこで通信待機させることにした、

launch で開始すると早すぎる

これは、 nvim-dap の実装の問題のような気がするが、 capabilities に以下を設定して、 configurationDone リクエストで自開始する。

supportsConfigurationDoneRequest = true,

ToDo

luada リポジトリを作って vscode 拡張としてリリースする。