GithubHelp home page GithubHelp logo

one-small-step-for-vimkind's Introduction

one-small-step-for-vimkind

one-small-step-for-vimkind is an adapter for the Neovim lua language. See the DAP protocol to know more about adapters. It allows you to debug any lua code running in a Neovim instance.

Install

Install using your prefered method for example using vim-plug

Plug 'jbyuki/one-small-step-for-vimkind'

" You will also need a comptabile DAP client

Plug 'mfussenegger/nvim-dap'

After installing one-small-step-for-vimkind, you will also need a DAP plugin which will allow you to interact with the adapter. There are mainly two available:

Configuration

Add these lines to work with nvim-dap.

local dap = require"dap"
dap.configurations.lua = { 
  { 
    type = 'nlua', 
    request = 'attach',
    name = "Attach to running Neovim instance",
  }
}

dap.adapters.nlua = function(callback, config)
  callback({ type = 'server', host = config.host or "127.0.0.1", port = config.port or 8086 })
end

Set keybindings to interact with the nvim-dap client.

vim.api.nvim_set_keymap('n', '<F8>', [[:lua require"dap".toggle_breakpoint()<CR>]], { noremap = true })
vim.api.nvim_set_keymap('n', '<F9>', [[:lua require"dap".continue()<CR>]], { noremap = true })
vim.api.nvim_set_keymap('n', '<F10>', [[:lua require"dap".step_over()<CR>]], { noremap = true })
vim.api.nvim_set_keymap('n', '<S-F10>', [[:lua require"dap".step_into()<CR>]], { noremap = true })
vim.api.nvim_set_keymap('n', '<F12>', [[:lua require"dap.ui.widgets".hover()<CR>]], { noremap = true })
vim.api.nvim_set_keymap('n', '<F5>', [[:lua require"osv".launch({port = 8086})<CR>]], { noremap = true })

Quickstart

  • Launch the server in the debuggee using F5
  • Open another Neovim instance with the source file
  • Place breakpoint with F8
  • Connect using the DAP client with F9
  • Run your script/plugin in the debuggee

Alternaltively you can:

  • Open a lua file
  • Place breakpoint
  • Invoke require"osv".run_this()

See osv.txt for more detailed instructions.

Troubleshoot

flatten.nvim

Set nest_if_no_args to true. See this issue for more informations.

Debugging plugins

Breakpoints are path-sensitive so they should always be set in the executed file even though they might be multiple copies on the system.

This is the case for packer.nvim when developing local plugins. packer.nvim will create a symlink to the plugins files in the nvim-data directory ( it can be located using :echo stdpath('data')). Make sure to set the breakpoints inside the source files in the nvim-data directory and not the local copy. The plugin directory can be found in nvim-data/site/pack/packer/start/YOUR_PLUGIN.

See osv.txt for more detailed instructions.

Dropbox

If you're using a service like Dropbox to share your plugin file, there might be some issue arising with osv. The reason is that the path executed within Neovim and the path opened in dap doesn't match. Consequently, osv has no way to know if the current running script is the same file as the file opened inside the dap client. Try falling back to a local folder to see if this is the cause.

Neovim is waiting for input at startup. Aborting

This appears when the osv's spawned headless neovim instance has an error at startup. Vim will usually wait for an user input but in case of osv, the instance is simply blocked. Resolve any errors that you see at startup. If there are none, the error might be due to the "headlessness". Start using nvim --headless to see if there are any errors.

Breakpoint is not hit

Important : Make sure osv is not running.

  1. Start tracing with :lua require"osv".start_trace()
  2. Perform the action that should be debugged (for ex. calling a function in your plugin)
  3. Stop tracing and display the results with :lua =require"osv".stop_trace() , the = will pretty print the resulting lua table.

Make sure that the path is correct and the breakpoint is set to a line which effectively gets executed.

Status

Handlers:

  • attach
  • scope
  • setBreakpoints
  • stackTrace
  • threads
  • variables
  • stepIn
  • next
  • stepOut
  • continue
  • evaluate
  • pause
  • terminate
  • disconnect
  • setVariable
  • setFunctionBreakpoints
  • setExceptionBreakpoints
  • breakpointLocations

Events:

  • initialized
  • stopped
  • terminated
  • exited
  • output

Capabilities:

  • supportsConditionalBreakpoints
  • supportsHitConditionalBreakpoints
  • supportsSetVariable
  • supportTerminateDebuggee

Name

it's a debugger for the moon language. - @tjdevries

Plugin architecture

Please refer to ARCHITECTURE.md.

Credits

Contribute

See here.

one-small-step-for-vimkind's People

Contributors

jbyuki avatar mfussenegger avatar vatosarmat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

one-small-step-for-vimkind's Issues

Worked first go, now stuck at: Neovim is waiting for input at startup. Aborting.

Hello,

I was able to set it up using the provided default config:

local dap = require"dap"
dap.configurations.lua = { 
  { 
    type = 'nlua', 
    request = 'attach',
    name = "Attach to running Neovim instance",
    host = function()
      local value = vim.fn.input('Host [127.0.0.1]: ')
      if value ~= "" then
        return value
      end
      return '127.0.0.1'
    end,
    port = function()
      local val = tonumber(vim.fn.input('Port: '))
      assert(val, "Please provide a port number")
      return val
    end,
  }
}

dap.adapters.nlua = function(callback, config)
  callback({ type = 'server', host = config.host, port = config.port })
end

I started debugging a lua file (adding breakpoints) and I started the server (with require"osv".launch()) and I was able to go through and debug + get print outputs from the file.

However, I closed neovim and now when I reopen it, I keep getting the complete output of my test file on start-up.

I am not able to relaunch the server (require"osv".launch() or require"osv".run_this()) as each time it reports Neovim is waiting for input at startup. Aborting..

I have tried uninstalling this plugin but this still occurs when opening neovim (I tried running it in headless, and it still prints the file test output on startup without any errors)

How would I be able to "unblock" this situation and get back to using the plugin?

(Just to add, it is possible that I ran require"osv".launch() from the same nvim instance that I had the debugged file open in - if that is possible? At this stage I don't remember the initial launch run)

Thanks

Vim:Error invoking 'nvim_exec_lua' on channel 7

if i using this to auto enable the osv

vim.api.nvim_create_autocmd({ "FileType" }, {
    pattern = "lua",
    callback = function ()
        require "osv".launch({
            host = '127.0.0.1',
            port = 8088,
            log = false
        })
    end
})

then i will get this error messages

Error detected while processing CursorMoved Autocommands for "*":
E5108: Error executing lua ...vim/site/pack/packer/opt/packer.nvim/lua/packer/load.lua:165: Vim(echomsg):E114: Missing quote: "Error in packer_compiled: ...vim/site/pack/packer/opt/packer.nvim/lu
a/packer/load.lua:155: Vim(append):Error executing lua callback: /usr/share/nvim/runtime/filetype.lua:20: Vim(append):Error executing lua callback: Vim:Error invoking 'nvim_exec_lua' on channel 7
:
stack traceback:
        [C]: in function 'cmd'
        ...vim/site/pack/packer/opt/packer.nvim/lua/packer/load.lua:165: in function <...vim/site/pack/packer/opt/packer.nvim/lua/packer/load.lua:161>
        [string ":lua"]:1: in main chunk

Does this plugin work with vimspector?

The readme mentions that one of vimspector or nvim-dap can be used. There's no information how to configure this plugin to work with vimspector. Can you please provide one?

How to debug non-neovim lua code?

Suppose I have a standalone main.lua with #!/usr/bin/lua which does some smart and tricky suftt and therefore it is complicated and therefore I need a debugger with breakpoints to debug it. How to run main.lua under OSV? Maybe there should be an instruction for that

How to debug key mapping or auto commands

Hi, I'm trying to debug some plugins I've written, which inevitably use some key mapping and automatic commands, but I can't debug it.For example, here is the file I want to debug, I hit the breakpoint to the third line, when I run lua require'dap'.continue() and then run lua require'dap'.step_into(), I get the message: No stopped threads. Cannot move

vim.keymap.set('n', '<BS>',
    function()
        print("start")
        for i=1,10 do
            print(i)
        end
        print("end")
    end 
)

This is my dap config

local ok, dap = pcall(require, 'dap')
if not ok then
    vim.notify('load module dap faild')
    return
end

local nvim_server
local nvim_chanID

local function dap_server(opts)

    assert(dap.adapters.nlua,
        "nvim-dap adapter configuration for nlua not found. "..
        "Please refer to the README.md or :help osv.txt")

    if nvim_chanID then
        local pid = vim.fn.jobpid(nvim_chanID)
        vim.fn.rpcnotify(nvim_chanID, "nvim_exec_lua", [[return require"osv".stop()]])
        vim.fn.jobstop(nvim_chanID)
        if type(vim.loop.os_getpriority(pid)) == 'number' then
            vim.loop.kill(pid, 9)
        end
        nvim_chanID = nil
    end

    nvim_chanID = vim.fn.jobstart({vim.v.progpath, '--embed', '--headless'}, {rpc = true})
    assert(nvim_chanID, "Could not create neovim instance with jobstart!")

    local mode = vim.fn.rpcrequest(nvim_chanID, "nvim_get_mode")
    assert(not mode.blocking, "Neovim is waiting for input at startup. Aborting.")

    vim.fn.rpcrequest(nvim_chanID, "nvim_command", "packadd one-small-step-for-vimkind")

    nvim_server = vim.fn.rpcrequest(nvim_chanID,
        "nvim_exec_lua",
        [[return require"osv".launch(...)]],
        { opts })

    vim.wait(100)

    return nvim_server
end


dap.adapters.nlua = function(callback, config)
    if not config.port then
        local server = dap_server()
        config.host = server.host
        config.port = server.port
    end
    callback({ type = 'server', host = config.host, port = config.port })
    if type(config.post) == 'function' then
        config.post()
    end
end

dap.configurations.lua = {
    {
        type = "nlua",
        request = "attach",
        name = "debug current file",
        post = function()
            dap.listeners.after['setBreakpoints']['osv'] = function(session, body)
                assert(nvim_chanID, "Fatal: neovim RPC channel is nil!")
                vim.fn.rpcnotify(nvim_chanID, "nvim_command", "luafile " .. vim.fn.expand("%:p"))
                dap.listeners.after['setBreakpoints']['osv'] = nil
            end
        end
    },
    {
        type = 'nlua',
        request = 'attach',
        name = "attach to nvim",
        host = function()
            local value = vim.fn.input('Host [127.0.0.1]: ')
            if value ~= "" then
                return value
            end
            return '127.0.0.1'
        end,
        port = function()
            local val = tonumber(vim.fn.input('Port: '))
            assert(val, "Please provide a port number")
            return val
        end,
    }
}

Frames for pre-compiled sources report wrong path/line/column

Neovim pre-compiles a couple of it's modules.
See https://github.com/neovim/neovim/blob/0fe0cf5adaab06b92250eb350306de63c4d4f36f/CONTRIBUTING.md?plain=1#L259-L268

If you try to step into a function that's defined in such a pre-compiled module like vim.validate (https://github.com/neovim/neovim/blob/0fe0cf5adaab06b92250eb350306de63c4d4f36f/runtime/lua/vim/shared.lua#L849-L854), the debug adapter reports frames like:

stackFrames = { {
    column = 0,
    id = 31,
    line = 0,
    name = "validate",
    source = {
      name = "@vim/shared.lua",
      path = "/path/to/dev/project/a/vim/shared.lua"
    }
  }, {

/project/a is not the folder containing neovim, but a different project I was debugging. It looks like it resolves this as relative path against the working directory?

These frames currently lead to two errors with nvim-dap:

  • Vim:E474: Invalid argument
  • Debug adapter reported a frame at line 0 column 1, but: Cursor position outside buffer. Ensure executable is up2date
    and if using a source mapping ensure it is correct

The first is because it tries to place a sign at line 0. The second because it tries to jump to its position. Neither works in an empty document. (Signs are 1 based, and nvim-dap sets linesStartAt1 = true, so 0 is invalid anyways)

The specification says 0 line should be ignored, but under the condition that the source attribute is missing:

https://microsoft.github.io/debug-adapter-protocol/specification#Types_StackFrame

  /**
   * The line within the source of the frame. If the source attribute is missing
   * or doesn't exist, `line` is 0 and should be ignored by the client.
   */
  line: number;

So I'm a bit reluctant to simply ignore line=0 frames.

Is there a way osv could resolve the proper source, or maybe skip them?

Print value of global variable?

Hi,
sorry this is (probably) more of a usage question than a bug report, but I didn't know where to ask questions.
I'm using this plugin with some success, but I noticed that in the REPL, I can only print the value of function-local variables (variables of the function where the debugger is currently stopped). When I try to print a variable of the enclosing scope (the module), I get "nil". Is there a way around that?

How to install?

Hi!
In README.md reads

Install
After installing one-small-step-for-vimkind, you will also need a DAP plugin which will allow you to interact with the adapter.

Please update Install instruction!

Cannot launch with another rpc client

Hi, I'm having trouble launching the server when I have another plugin flatten.nvim which connects to the nvim rpc server. Is there a solution to ensure both plugins work at the same time?

E5108: Error executing lua Vim:Error invoking 'nvim_exec_lua' on channel 3:
ch 3 was closed by the client
stack traceback:
        [C]: in function 'rpcrequest'
        ...re/nvim/lazy/one-small-step-for-vimkind/lua/osv/init.lua:134: in function 'launch'
        [string ":lua"]:1: in main chunk

Evaluation only displays an empty rectangle

I am trying to setup one-small-step-for-vimkind and make it work with nvim-dap, and it seems like everything is working, but I do not manage to make the plugin add a watch or evaluate a value on the fly :
evaluation

Since I manage to do it with a Python debugger and the same nvim-dap, I guess the issue comes from either one-small-step-for-vimkind or (probably) my configuration.

Versions/Commits hashes :
one-small-step-for-vimkind : 27e5f59
nvim-dap : 6cedcb5

My config for the DAP is the following :

local dap = require('dap')

dap.configurations.lua = {
	{
		type = "nlua",
		request = "attach",
		name = "Attach to running Neovim instance",
		host = function()
			local value = vim.fn.input "Host [127.0.0.1]: "
			if value ~= "" then
				return value
			end
			return "127.0.0.1"
		end,
		port = function()
			local val = tonumber(vim.fn.input("Port: ", "54321"))
			assert(val, "Please provide a port number")
			return val
		end,
	},
}

dap.adapters.nlua = function(callback, config)
	callback { type = "server", host = config.host, port = config.port, log = true }
end

Obviously, I don't exclude having made a stupid mistake somewhere due to my lack of experience with configuring vim and LUA 😬

Any instruction on how to get the debugger going using LunarVim?

I am using LunarVim and would love to try the debugger but as mentioned something needs to be done with a config file. I am not sure what to do!!!

I have installed the debugger and when i try to launch the debugger i get the following error message:

E5108: Error executing lua Vim:Error invoking 'nvim_exec_lua' on channel 517:
Error executing lua: [string "<nvim>"]:1: module 'osv' not found:

Can't toggle breakpoints after attached

If I do the following:

  1. Start nvim my_file.lua
  2. :lua require 'osv'.launch()
  3. Launch another nvim my_file.lua
  4. Set a breakpoint in the second client
  5. :lua require 'dap'.continue() → enter the host/port
  6. :luafile % in the first client

...then execution stops at the breakpoint that I set, as it should. However, if I add or remove breakpoints in the second nvim client, it seems to have no effect. If I change the breakpoints and :luafile % in the first client, then execution stops at exactly the same set of breakpoints that were on when require'dap'.continue was called.

Is this expected?

Missing line field in StackFrame, causes errors in Vimspector

Using osv with vimspector, adapter configuration:

{
    "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#",
    "adapters": {
        "nlua": {
            "host": "127.0.0.1",
            "port": "8086"
        }
    },

    "configurations": {
        "osv": {
            "adapter": "nlua",
            "configuration": {
                "request": "attach"
            }
        }
    }
}

Vimspector errors, and gives the logs

2023-01-29 14:06:00,878 - INFO - **** INITIALISING NEW VIMSPECTOR SESSION ****
2023-01-29 14:06:00,878 - INFO - API is: neo
2023-01-29 14:06:00,878 - INFO - VIMSPECTOR_HOME = /home/ppeb/.local/share/nvim/site/pack/packer/start/vimspector
2023-01-29 14:06:00,878 - INFO - gadgetDir = /home/ppeb/.local/share/nvim/site/pack/packer/start/vimspector/gadgets/linux
2023-01-29 14:06:00,880 - INFO - User Msg: Loaded /home/ppeb/.cache/vimspector
2023-01-29 14:06:02,840 - INFO - User requested start debug session with {}
2023-01-29 14:06:02,842 - DEBUG - Reading configurations from: None
2023-01-29 14:06:02,842 - DEBUG - Reading configurations from: /home/ppeb/gitclone/ppebboard/.vimspector.json
2023-01-29 14:06:02,843 - DEBUG - Reading gadget config: /home/ppeb/.local/share/nvim/site/pack/packer/start/vimspector/gadgets/linux/.gadgets.json
2023-01-29 14:06:02,850 - DEBUG - Reading gadget config: None
2023-01-29 14:06:02,851 - INFO - Configuration: {"adapter": "nlua", "configuration": {"request": "attach"}}
2023-01-29 14:06:02,851 - INFO - Adapter: {"host": "127.0.0.1", "port": "8086"}
2023-01-29 14:06:02,854 - DEBUG - min_width/height: 149/50, actual: 283/70 - result: horizontal
2023-01-29 14:06:02,968 - DEBUG - LAUNCH!
2023-01-29 14:06:02,974 - INFO - Starting debug adapter with: {"host": "127.0.0.1", "port": "8086"}
2023-01-29 14:06:02,974 - DEBUG - Connection Type: neochannel
2023-01-29 14:06:02,989 - INFO - Debug Adapter Started
2023-01-29 14:06:02,990 - DEBUG - Sending Message: {"command": "initialize", "arguments": {"adapterID": "adapter", "clientID": "vimspector", "clientName": "vimspector", "linesStartAt1": true, "columnsStartAt1": true, "locale": "en_GB", "pathFormat": "path", "supportsVariableType": true, "supportsVariablePaging": false, "supportsRunInTerminalRequest": true, "supportsMemoryReferences": true}, "seq": 0, "type": "request"}
2023-01-29 14:06:03,024 - DEBUG - Message received: {'seq': 1, 'request_seq': 0, 'type': 'response', 'success': True, 'body': [], 'command': 'initialize'}
2023-01-29 14:06:03,025 - DEBUG - Sending Message: {"command": "attach", "arguments": {"request": "attach", "name": "test"}, "seq": 1, "type": "request"}
2023-01-29 14:06:03,025 - DEBUG - Message received: {'seq': 2, 'type': 'event', 'event': 'initialized'}
2023-01-29 14:06:03,025 - DEBUG - Sending Message: {"command": "setBreakpoints", "arguments": {"source": {"name": "gen.lua", "path": "/home/ppeb/gitclone/ppebboard/lua/ppebboard/gen.lua"}, "breakpoints": [{"line": 37}], "sourceModified": false}, "seq": 2, "type": "request"}
2023-01-29 14:06:03,026 - DEBUG - Sending Message: {"command": "setExceptionBreakpoints", "arguments": {"filters": []}, "seq": 3, "type": "request"}
2023-01-29 14:06:03,091 - DEBUG - Message received: {'seq': 1, 'request_seq': 1, 'type': 'response', 'success': True, 'command': 'attach'}
2023-01-29 14:06:03,135 - DEBUG - Message received: {'seq': 2, 'request_seq': 2, 'type': 'response', 'success': True, 'body': {'breakpoints': [{'verified': True}]}, 'command': 'setBreakpoints'}
2023-01-29 14:06:03,135 - DEBUG - Message received: {'seq': 3, 'request_seq': 3, 'type': 'response', 'success': True, 'body': {'breakpoints': []}, 'command': 'setExceptionBreakpoints'}
2023-01-29 14:06:03,139 - DEBUG - Sending Message: {"command": "threads", "seq": 4, "type": "request"}
2023-01-29 14:06:03,141 - DEBUG - Message received: {'seq': 4, 'request_seq': 4, 'type': 'response', 'success': True, 'body': {'threads': [{'id': 1, 'name': 'main'}]}, 'command': 'threads'}
2023-01-29 14:06:06,493 - DEBUG - Message received: {'seq': 5, 'type': 'event', 'event': 'stopped', 'body': {'reason': 'breakpoint', 'threadId': 1}}
2023-01-29 14:06:06,494 - WARNING - User Msg: Paused in thread 1 due to breakpoint
2023-01-29 14:06:06,504 - DEBUG - Sending Message: {"command": "threads", "seq": 5, "type": "request"}
2023-01-29 14:06:06,544 - DEBUG - Message received: {'seq': 6, 'request_seq': 5, 'type': 'response', 'success': True, 'body': {'threads': [{'id': 1, 'name': 'main'}]}, 'command': 'threads'}
2023-01-29 14:06:06,545 - DEBUG - Sending Message: {"command": "stackTrace", "arguments": {"threadId": 1}, "seq": 6, "type": "request"}
2023-01-29 14:06:06,595 - DEBUG - Message received: {'seq': 7, 'request_seq': 6, 'type': 'response', 'success': True, 'body': {'stackFrames': [{'id': 1, 'name': 'create_board', 'column': 0, 'line': 37, 'source': {'path': '/home/ppeb/gitclone/ppebboard/lua/ppebboard/gen.lua', 'name': '@/home/ppeb/.local/share/nvim/site/pack/packer/start/ppebboard/lua/ppebboard/gen.lua'}}, {'id': 2, 'name': 'main'}], 'totalFrames': 2}, 'command': 'stackTrace'}

In the last line, 'stackFrames': [], the second one, {'id': 2, 'name': 'main'} is missing the line field, which is required in a StackFrame

nvim gets spawned recursively?

Sorry I haven't pinpointed the cause of this yet, but I believe it's either this plugin or nvim-dap causing it because I've only noticed this recently and only as I've been doing debug sessions over the past few days.

This just happened to me for the 2nd or 3rd time in the last 2 days, and both times I had left a debug session stay open and stopped on a breakpoint for several hours on-end (e.g. 12 hours) (including letting my computer go to sleep and waking it back up with the session still running). Anyway, I'll go to invoke a shell command and get an EAGAIN error, and when I check my processes, there will be a very large number of nvim instances eating up all 64gb of my ram (even though I'm only running 2 or 3 myself). I am not running anything that spawns nvim processes automatically afaik (unless barebones neovim is doing that itself for some reason, which I doubt). So it is therefore likely that the cause is this plugin or nvim-dap I believe. I haven't had much chance to investigate the issue because every time it happens, by the time I realize it, my terminal freezes due to being out of ram/resources/process slots etc. Maybe it has something to do with leaving a debug session open while my computer goes to sleep? Not sure.

Note

Both times I had also toggled the dap repl, used it, and left it open as well.

I am using macOS Ventura 13.5 and neovim 0.9.1. Recently I've updated my OS and installed the dap-virtual-text plugin.

I'll try to reproduce this or investigate it further when I get the chance.


The last time it happened to me, I had launched the debuggee using this sh script:

# I use `defer_fn()` because otherwise nvim freezes if `osv.launch()`
# is called without it, `osv.launch()` also freezes nvim if called anytime
# before `VimEnter` fires. Replacing the `defer_fn()` below with `schedule()`
# likewise freezes nvim it seems, but this behavior is another issue not related
# to this topic afaik.

nvim \
  -n \
  -i NONE \
  -u NONE \
  '+set rtp^=.' \
  "+autocmd VimEnter * ++once ++nested lua vim.defer_fn(function() require'osv'.launch{ port = 8086 } end, 1e3)" \
  "$@"

nvim-dap config

local api = vim.api
local dap = require 'dap'
local wk = require 'which-key'

-- DEBUGGEE CONFIGURATION
-- key:  filetype of current buf
-- type: key of dap.adapters
dap.configurations.lua = {
    {
        type = 'nlua',
        request = 'attach',
        name = 'Attach to running Neovim instance',
    },
}

-- ADAPTER CONFIGURATION
-- Configure nvim-dap to connect to or launch a debug adapter
dap.adapters.nlua = function(callback, config)
    callback {
        type = 'server',
        host = config.host or '127.0.0.1',
        port = config.port or 8086,
    }
end

-- {{{ Mappings
local last_action

local function expand_aliases(t)
    local ret = {}
    for keys, def in pairs(t) do
        for _, key in ipairs(type(keys) == 'table' and keys or { keys }) do
            assert(ret[key] == nil, 'duplicate key/mapping: ' .. key)
            ret[key] = def
        end
    end
    return ret
end

local function step_over()
    last_action = 'n'
    require('dap').step_over()
end

wk.register(
    expand_aliases {
        name = 'DAP/Debugger',

        ['\\'] = {
            function()
                return last_action and '\\' .. last_action
                    or [[<Cmd>lua api.nvim_err_writeln "no previous command to reference"<CR>]]
            end,
            'Repeat last action',
            expr = true,
            noremap = false,
        },

        [{ 'si', 'i' }] = {
            function()
                last_action = 'i'
                require('dap').step_into {
                    -- steppingGranularity = nil,
                    askForTargets = true,
                }
            end,
            'Step (i)nto',
        },

        [{ 'so', 'o' }] = {
            function()
                last_action = 'o'
                require('dap').step_out {
                    -- steppingGranularity = nil,
                    askForTargets = true,
                }
            end,
            'Step (o)ut',
        },

        n = {
            step_over,
            'Step over/(n)ext',
        },

        c = {
            function()
                last_action = 'c'
                require('dap').continue()
            end,
            '(C)ontinue',
        },

        ['<CR>'] = {
            function()
                last_action = '<CR>'
                require('dap').run_to_cursor()
            end,
            'Run to cursor',
        },

        p = {
            function() require('dap').pause() end,
            '(P)ause thread',
        },

        -- Breakpoints

        [{ 'bt', 'bb' }] = {
            function() require('dap').toggle_breakpoint() end,
            '(T)oggle (b)reakpoint',
        },

        bl = {
            function() require('dap').list_breakpoints(true) end,
            '(L)ist (b)reakpoints',
        },

        bc = {
            function() require('dap').clear_breakpoints() end,
            '(C)lear (b)reakpoints',
        },

        [{ 'be', 'eb' }] = {
            function() require('dap').set_exception_breakpoints() end,
            'Set (e)xception (b)reakpoint',
        },

        -- gt = {
        --     function()
        --         require("dap").goto_(vim.v.count ~= 0 and vim.v.count or nil)
        --     end,
        --     "Go to cursor line",
        -- },

        h = {
            function() require('dap.ui.widgets').hover() end,
            '(H)over',
        },

        l = {
            function()
                require('osv').launch {
                    -- args = vim.tbl_filter(
                    --     (function(i)
                    --         return function(v)
                    --             i = i + 1
                    --             return i ~= 1
                    --                 and v ~= "--embed"
                    --                 and v ~= "--headless"
                    --         end
                    --     end)(0),
                    --     vim.v.argv
                    -- ),
                    port = 8086,
                }
            end,
            '(L)aunch DAP Server',
        },

        f = {
            function()
                require('dap').focus_frame()
                vim.cmd 'normal! zz'
            end,
            '(F)ocus/jump to curr frame',
        },

        q = {
            function() require('dap').terminate() end,
            'Quit/Terminate',
        },
        -- },
    },
    {
        -- buffer = nil,
        expr = false,
        mode = 'n',
        noremap = true,
        nowait = false,
        prefix = '\\',
        silent = false,
    }
)

wk.register({
    ['<M-Up>'] = {
        function() require('dap').up() end,
        'Go up in stacktrace',
    },

    ['<M-Down>'] = {
        function() require('dap').down() end,
        'Go down in stacktrace',
    },

    ['<M-Right>'] = { step_over, 'Step over' },
}, {
    -- buffer = nil,
    expr = false,
    mode = 'n',
    noremap = true,
    nowait = false,
    -- prefix = "\\",
    silent = false,
})
-- }}}

-- {{{ Signs
for _, val in
    ipairs(vim.fn.sign_define(vim.tbl_map(function(signdef)
        signdef.linehl = signdef.name .. 'SignLine'
        signdef.numhl = signdef.name .. 'SignNr'
        signdef.texthl = signdef.name .. 'Sign'
        signdef.culhl = signdef.name .. 'SignCul'
        return signdef
    end, {
        -- For breakpoints (default: `B`)
        { name = 'DapBreakpoint' },

        -- For conditional breakpoints (default: `C`)
        { name = 'DapBreakpointCondition' },

        -- For log points (default: `L`)
        { name = 'DapLogPoint' },

        -- To indicate where the debugee is stopped (default: `→`)
        {
            name = 'DapStopped',
            -- icon = "",
            text = '',
        },

        -- To indicate breakpoints rejected by the debug adapter (default: R`)
        { name = 'DapBreakpointRejected' },
    })))
do
    assert(val == 0, 'failed to define sign')
end
-- }}}

local liskey = 'tmillr'
dap.listeners.after.event_stopped[liskey] = function(session, ev_payload)
    vim.cmd 'normal! zz'
end

nvim-dap-virtual-text config

require("nvim-dap-virtual-text").setup {
    enabled = true,                        -- enable this plugin (the default)
    enabled_commands = true,               -- create commands DapVirtualTextEnable, DapVirtualTextDisable, DapVirtualTextToggle, (DapVirtualTextForceRefresh for refreshing when debug adapter did not notify its termination)
    highlight_changed_variables = true,    -- highlight changed values with NvimDapVirtualTextChanged, else always NvimDapVirtualText
    highlight_new_as_changed = false,      -- highlight new variables in the same way as changed variables (if highlight_changed_variables)
    show_stop_reason = true,               -- show stop reason when stopped for exceptions
    commented = false,                     -- prefix virtual text with comment string
    only_first_definition = false,         -- only show virtual text at first definition (if there are multiple)
    all_references = true,                 -- show virtual text on all all references of the variable (not only definitions)
    clear_on_continue = true,              -- clear virtual text on "continue" (might cause flickering when stepping)

    --- A callback that determines how a variable is displayed or whether it should be omitted
    --- @param variable Variable https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable
    --- @param buf number
    --- @param stackframe dap.StackFrame https://microsoft.github.io/debug-adapter-protocol/specification#Types_StackFrame
    --- @param node userdata tree-sitter node identified as variable definition of reference (see `:h tsnode`)
    --- @param options nvim_dap_virtual_text_options Current options for nvim-dap-virtual-text
    --- @return string|nil A text how the virtual text should be displayed or nil, if this variable shouldn't be displayed
    -- display_callback = function(variable, buf, stackframe, node, options)
    --   if options.virt_text_pos == 'inline' then
    --     return ' = ' .. variable.value
    --   else
    --     return variable.name .. ' = ' .. variable.value
    --   end
    -- end,

    -- position of virtual text, see `:h nvim_buf_set_extmark()`, default tries to inline the virtual text. Use 'eol' to set to end of line
    -- virt_text_pos = vim.fn.has 'nvim-0.10' == 1 and 'inline' or 'eol',
    virt_text_pos = 'eol',

    -- Experimental Features
    all_frames = false,                    -- show virtual text for all stack frames not only current. Only works for debugpy on my machine.
    virt_lines = false,                    -- show virtual lines instead of virtual text (will flicker!)
    -- virt_text_win_col = nil             -- position the virtual text at a fixed window column (starting from the first text column) ,
                                           -- e.g. 80 to position at column 80, see `:h nvim_buf_set_extmark()`
}

Questions on execution termination and printing to the dap-repl

First, ty for this really wonderful plugin, I was able to set it up nicely to work when running lua require'dap'.continue() so I can avoid calling run_this() or the triple instance logistics (A+B+launch() instaces) and it works fairly well.

In case you're interested, my one-small-step-for-vimkind configuration can be found in my config's lua/plugins/dap/lua.lua.

Admittedly I haven't gotten deep into the code of this plugin yet but perhaps there are simple answers for my questions:

  • Is there an easy way to know when the luafile <file> is done so I can shut down the server? I tried all nvim-dap events and none of them seem to fire when execution is done (e.g. event_terminated, event_stopped, etc), which brings me to the 2nd question/issue:

  • Running continue when execution is done brings up the Session active, but not stopped at breakpoint prompt which requires to terminate before being able to run the debug configuration again, however sending terminate fails with E5560: vimL function must not be called in a lua loop callback at the call to vim.fn.sign_unplace.

I believe it is an issue with nvim-dap and opened the below PR which solves the issue:
mfussenegger/nvim-dap#486

  • Is there a way to view lua print statements in the [dap-repl] buffer? when using a double instance setup (A being the DAP server) and running :luafile myscript.lua on A I am able to see the print statements output on the :messages of A but not in the [dap-repl] on B - is that a bug/setup issue or even possible?

Launching osv via cli args

Screenshot 2024-02-03 at 11 21 35 AM

idk if this is possible or easy to fix but I thought I'd go ahead and create this issue anyway for reference/help/feedback. It's not a huge deal, but it does keep me from (or makes it harder at least) debugging tests (which are typically run in headless mode).

I haven't investigated this a ton yet; any ideas? Perhaps it has something to do with how nvim operates internally while in headless mode (e.g. not allowed to start a job or rpc client/server until after the ui channel/client/server/job has started)? Maybe it would require changing the rpc/server/client functions that are used for communication (e.g. to use libuv instead) in order to fix this? Or is this something that is supposed to work and is an issue on my end? Thanks

Stdout (print, io.write) doesn't seem to work

I am using one-small-step-for-vimkind in a LazyVim setup, altogether with nvim-dap and nvim-dap-ui.

Almost everything works fine (breakpoints, step-into, widgets, ...). However, the output to stdout (either via print or io.write) doesn't apper in the dap-repl or DAP Console.

Any ideas? Or this is the expected behavior?

Can't `require'osv'.launch()`

Hi, I'm trying to use OSV for the first time. I'm following the setup / quick-start instructions verbatim and getting an error:

E5108: Error executing lua Vim:Error invoking 'nvim_get_mode' on channel 3:
ch 3 sent an invalid message, closed.
stack traceback:
        [C]: in function 'rpcrequest'
        ...nvim/plugged/one-small-step-for-vimkind/lua/osv/init.lua:95: in function 'launch'
        [string ":lua"]:1: in main chunk

I'm using Neovim 0.7 from Homebrew and the latest versions of OSV and nvim-dap as of today. My nvim-dap is confirmed working (I can successfully use nvim-dap-python, for example).

Can dap continue launch the lua file?

With Python and Rust, when doing dap continue it is able to launch the debugger.

With osv I could only achieve debugging using require'osv'.run_this() to achieve the same.
This means that key maps need to be different between lua and other languages.

Is there a way to configure osv or dap so the same technique of dap continue will work also for lua debugging?

Customizable command to launch nvim

In the latest nightly build NVIM v0.7.0-dev+667-g419e0d117d

:lua require"osv".run_this() or :lua require"osv".launch() results in the following error

E5108: Error executing lua Vim:Error invoking 'nvim_exec_lua' on channel 10:
Error executing lua: [string "<nvim>"]:1: module 'osv' not found:        no field package.preload['osv']        no file './osv.lua'        no file '/usr/share/luajit-2.0.5/osv.lua'        no file '/usr/local/share/lua/5.1/osv.lua'        no file '/usr/local/share/lua/5.1/osv/init.lua'        no file '/usr/share/lua/5.1/osv.lua'        no file '/usr/share/lua/5.1/osv/init.lua'        no file './osv.so'        no file '/usr/local/lib/lua/5.1/osv.so'        no file '/usr/lib/lua/5.1/osv.so'        no file '/usr/local/lib/lua/5.1/loadall.so'stack traceback:        [C]: in function 'require'        [string "<nvim>"]:1: in main chunkstack traceback:        [C]: in function 'rpcrequest'        ...packer/start/one-small-step-for-vimkind/lua/osv/init.lua:706: in function 'run_this'        [string ":lua"]:1: in main chunk

Repl evaluate doesn't have access to function upvalues

I haven't checked, but this may only be specific to callbacks (e.g. autocmd callback, timer callback). It looks like the current impl only uses debug.getlocal() while traversing the current call stack (which may not necessarily contain all of the values the current frame/fn has access to, e.g. its upvalues from its defining context).

Also, I'm not sure if this is 100% correct regardless, as the outer frame often contains locals which shouldn't technically/normally be accessible from the current frame (although I view this issue as somewhat secondary to the issue concerning a lack of access to upvalues).

Idea for fix

When evaluating (at least for the repl context, maybe for hover context too?), only collect the locals of the current frame/fn. Then, use debug.getupvalue() in a loop to get/collect all of the upvalues of the current frame/fn.

Precedence/fallback order should be:

Matching Local w/ Highest Index || Matching Upvalue || Matching fenv value || nil

using the first non-nil value found.

Note

There can be multiple locals with the same name in a given frame/fn, which is why the one with the highest index wins. Simply using a foreword/increasing loop and collecting the values into a table map should be sufficient, as locals at later/higher indices will naturally overwrite earlier ones.

Note

Also note how it ends by trying to resolve against the function's env, not _G itself. The env is usually _G, but not always.

There's also a webpage on lua.org describing how to accomplish just this and precisely mimic Lua's usual value retrieval algorithm (i.e. when evaluating/executing some chunk/fn) here.

require"osv".launch() locks up neovim

NVIM v0.5.0-dev+1300-g7fcc59655

Hi, I'm having some trouble trying to get the plugin working and I'm not sure if it's the plugin, nvim or something else with my set up. When I try to launch(), nvim is locking up - I can see the new spawned instance of embedded/headless vim in the process table, but it goes no further. A bit of debugging shows the problem lies with the rpcrequest blocking and never returning:

https://github.com/jbyuki/one-small-step-for-vimkind/blob/main/lua/osv/init.lua#L86
if I comment that line out, the same problem occurs at:
https://github.com/jbyuki/one-small-step-for-vimkind/blob/main/lua/osv/init.lua#L90

I'm using nvim nightly. Not sure if it's broken or maybe it has changed the way rpcrequests are handled, so the problem may be with nvim rather than the plugin.

Debug adapter disconnected

I have two files

  1. test file that write with busted - test.lua
  2. my code - mycode.lua

I run server than set breakpoint inside mycode.lua. But when I run lua require"dap".continue() it gets me this massage 'session active but not stopped at breakpoint'
I run lua require"osv".run_this() sometime it work and stop in breakpoint but get this massage Debug adapter diconnected
do i something wrong?
Can you add more example to documentation?

Possible way to resolve symlink issue

I see that document has suggested opening file in symlinked position to solve the problem:

When your plugin is executed from within nvim, it won't call the files
located inside your local directory but go through the symlink.
This means that breakpoints should also be set in the files which are
located inside the symlink so that executed files and the files which
contain breakpoints match and stop on trigger.
In consequence, reopen the files through the symlink and place the breakpoints
there to properly trigger them.

But actually it should not work since (neo)vim will auto resolve the symlink when opening the file: vim/vim#4942

And i've tried the following patch to always resolve link, which works for me:

diff --git a/lua/osv/init.lua b/lua/osv/init.lua
index 7fd405f..a6c5cc8 100644
--- a/lua/osv/init.lua
+++ b/lua/osv/init.lua
@@ -332,7 +332,7 @@ function M.wait_attach()
         if info.source:sub(1, 1) == '@' then
           stack_frame.source = {
             name = info.source,
-            path = vim.fn.fnamemodify(info.source:sub(2), ":p"),
+            path = vim.fn.resolve(vim.fn.fnamemodify(info.source:sub(2), ":p")),
           }
           stack_frame.line = info.currentline 
           stack_frame.column = 0
@@ -517,6 +517,7 @@ function M.wait_attach()
           local path = source_path:sub(2)
           local succ, path = pcall(vim.fn.fnamemodify, path, ":p")
           if succ then
+            path = vim.fn.resolve(path)
             path = vim.uri_from_fname(path:lower())
             if bps[path] then
               log("breakpoint hit")

Hope this will give help for a better solution.

Debugger couldn't connect to 127.0.0.1:8086: ECONNREFUSED while debugging lazy plugins

Description

I recently started to use lazyvim and quickly became interested in debugging plugins. I tried lazyvim default nvim lua debug setup. But every time I was trying to attach a debugger to nvim instance I get: Couldn't connect to 127.0.0.1:8086: ECONNREFUSED.

Expected behavior

Debugger will work

Neovim version

v0.9.4

Operating system/version

MacOS 14.1.2 (23B92)

Repro

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
	vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
	vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
end
vim.opt.runtimepath:prepend(lazypath)

vim.g.mapleader = " "

-- install plugins
local plugins = {
	"folke/tokyonight.nvim",
	{
		"mfussenegger/nvim-dap",
		dependencies = {
			{
				"jbyuki/one-small-step-for-vimkind",
				config = function()
					local dap = require("dap")
					dap.configurations.lua = {
						{
							type = "nlua",
							request = "attach",
							name = "Attach to running Neovim instance",
						},
					}
					dap.adapters.nlua = function(callback, config)
						callback({ type = "server", host = config.host or "127.0.0.1", port = config.port or 8086 })
					end
				end,
			},
		},
		keys = {
			{
				"<leader>db",
				function()
					require("dap").toggle_breakpoint()
				end,
				desc = "Toggle Breakpoint",
			},
			{
				"<leader>dc",
				function()
					require("dap").continue()
				end,
				desc = "Continue",
			},
		},
	},
}
require("lazy").setup(plugins, {
	root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")

How to use?

Hi, I am trying to set it up to debug my nvim lua plugins.
suppose I am trying to debug lua_test.lua. Flowed the instruction in README.md
I will open lua_test.lua in nvim instance 1 and run launch. it will echo a port (e.g. 64929) debug server is on.
In another nvim open lua_test.lua. and run lua require'dap'.countine. I will be ask to input the debug server port.
But after I input the port. There is no message to indicate I connected to the server or not. If I run require'dap'.continue, I saw no stopped thread, Can not move`

Is anything missed in my steps?

Plugin does not support wrapped `nvim` executable?

I just installed this plugin and followed all the instructions precisely to get it set up and start debugging. As soon as I ran launch() however, I received an error:

E5108: Error executing lua: Vim:Error invoking 'nvim_exec_lua' on channel 4:                                                                                           
Error executing lua: [string "<nvim>"]:1: module 'osv' not found:                                                                                                      
        no field package.preload['osv']                                                                                                                                
        no file '/nix/store/rnjjjd25ms18dmyb47mpnfw17jn5lzss-luajit-2.1.0-2022-10-04-env/share/lua/5.1/osv.lua'                                                        
        no file '/nix/store/rnjjjd25ms18dmyb47mpnfw17jn5lzss-luajit-2.1.0-2022-10-04-env/share/lua/5.1/osv/init.lua'                                                   
        no file '/nix/store/rnjjjd25ms18dmyb47mpnfw17jn5lzss-luajit-2.1.0-2022-10-04-env/lib/lua/5.1/osv.so'                                                           
stack traceback:                                                                                                                                                       
        [C]: in function 'require'                                                                                                                                     
        [string "<nvim>"]:1: in main chunk                                                                                                                             
stack traceback:                                                                                                                                                       
        [C]: in function 'rpcrequest'                                                                                                                                  
        ...rt/vimplugin-one-small-step-for-vimkind/lua/osv/init.lua:143: in function 'launch'

I think I know what the issue is, because this is something that I've run into recently with plenary. My nvim and plugins are all managed and installed by the nix pkg manager. To install Neovim, Nix builds a static/readonly wrapper shell script that wraps and exec's the actual nvim binary, and then links this script into PATH as nvim. The reason for the wrapper is to pass several environment vars and cli args automatically directly to nvim, for example to set 'packpath' to the appropriate value to bootstrap plugin loading. Anyway, the crux of the issue comes down to the use of v:progpath which is a readonly variable that is resolved and set internally by nvim. Even when nvim is/points to a wrapper executable/bash script around the actual binary and exec -a "$0" ... is used within the wrapper to invoke it, vim/neovim still sets v:progpath to the actual underlying binary instead of the wrapper script, meaning that none of my plugins get loaded automatically (leading to the error above).

Perhaps it would be possible to allow for the nvim binary spawned by this plugin to be specified/configured (whether via a function arg, or env var, etc.)? This would help out anyone who's using nix or a wrapped nvim binary.


On an unrelated note, I was also curious if this plugin allows configuring the communication with the server in order to have it go over a unix domain socket/pipe instead of tcp? The former should be more secure and performant and is also recommended over tcp in the neovim docs. I think nvim actually defaults to using a pipe as well (see :h rpc-connecting).

Thanks

How to use with larger projects

I followed your example and I can get dap to stop at breakpoints. (not always, sometimes it doesn't work with the simple example.)

I wanted to ask how I can use dam with larger projects? I'd like to debug Telescope to help me writing an extension.
I've added a breakpoint which should stop when I open my Telescope picker but it never stops.
In this case I don't use `luafile myscript.lua' as that's not how the function would be called.

Is there anyway to prevent the debugger from entering outside projects?

To start, this is an amazing plugin :)

However I am noticing quite often that my breakpoints are treated more as suggestions as opposed to hard breakpoints. They aren't ignored, but the debugger likes to first stop inside the osv project before it stops in whatever code I have added a breakpoint to. Additionally, often the debugger will use the step over command to jump into some other running code before coming back to the section I care about (the next line in my project).

Its really cool to see all the different plugins that are running and such, but not really useful when I am trying to hunt down a bug in my own code. The Visual Studio debugger has an option for "justMyCode" where it doesn't traverse into "outside project" code, I was wondering if this is a thing I can enable for osv?

No response or event received

Hi, When executing Disconnect Request or Terminate Request in dap-client, the response or event cannot be received.
I execute the dap.terminate() method after successfully connecting to the debug adapter, but none of the listeners I set up are running properly.

This is my config, Modified form @ibhagwan

local ok, dap = pcall(require, 'dap')
local ok, util = pcall(require, 'util')

local function dap_server_lua(opts)
    local terminal = vim.fn.split(os.getenv("TERM"), '-', 1)[1]
    local pipe = vim.fn.tempname()
    local cmd = string.format('%s -e nvim --listen %s', terminal, pipe)
    local debugee_id = vim.fn.jobstart(cmd)
    assert(debugee_id ~= 0 or debugee_id ~= -1, 'fail')

    local ok, adapter_id
    ok = vim.wait(5000, function ()
        ok, adapter_id = pcall(vim.fn.sockconnect,'pipe', pipe, {rpc = true})
        return ok and adapter_id > 0
    end)
    assert(ok, 'timeout')

    vim.fn.rpcrequest(
        adapter_id,
        'nvim_create_autocmd',
        'vimleavepre',
        { command = [[lua require('osv').stop()]] }
    )

    local server = vim.fn.rpcrequest(
        adapter_id,
        "nvim_exec_lua",
        [[return require"osv".launch(...)]],
        { opts }
    ) or {}
    server.adapter_id = adapter_id
    server.debugee_id = debugee_id
    return server
end

dap.configurations.lua = {
    {
        type = "nlua",
        request = "attach",
        name = "current file",
        server = function() return dap_server_lua(nil) end,
    },
}

local nlua_server_by_session_id = {}
dap.adapters.nlua = function(callback, config)
    assert(config.server.host and config.server.port,  'fail')
    callback({ type = 'server', host = config.server.host, port = config.server.port })
    local session = dap.session() or {}
    assert(session.id and session.filetype == 'lua', 'fail')
    nlua_server_by_session_id[session.id] = config.server

    if not dap.listeners.after['Terminate']['osv'] then
        print('00')
        dap.listeners.after['Terminate']['osv'] = function(session, err, respond, request_payload, mes_id)
            if session.filetype ~= 'lua' then
                print('11')
               return
            end
            local server = nlua_server_by_session_id[session.id]
            if not server then
                print('22')
               return 
            end

            vim.fn.rpcrequest(
                server.adapter_id,
                "nvim_exec_lua",
                [[require"osv".stop()]]
            )
            vim.fn.jobstop(server.debugee_id)
        end
    end
    if not dap.listeners.after['Disconnect']['osv'] then
        print('00')
        dap.listeners.after['Disconnect']['osv'] = function(session, err, respond, request_payload, mes_id)
            if session.filetype ~= 'lua' then
                print('11')
               return
            end
            local server = nlua_server_by_session_id[session.id]
            if not server then
                print('22')
               return 
            end

            vim.fn.rpcrequest(
                server.adapter_id,
                "nvim_exec_lua",
                [[require"osv".stop()]]
            )
            vim.fn.jobstop(server.debugee_id)
        end
    end
end


local map_bak_list = {}
vim.keymap.set('n', 'dp', function() dap.toggle_breakpoint() end)
vim.keymap.set('n', 'd<cr>', function()
    dap.continue({ new = true })
    if #dap.sessions() > 1 then
        return
    end

    map_bak_list = {}
    for _, map in ipairs({
        { 'n', '<a-p>', function() dap.toggle_breakpoint() end },
        { 'n', '<a-c>', function() dap.toggle_breakpoint(vim.fn.input('c :')) end },
        { 'n', '<a-e>', function() dap.set_exception_breakpoints() end },
        { 'n', 'qp', function() dap.list_breakpoints() end },
        { 'n', 'cp', function() dap.clear_breakpoints() end },
        { 'n', '<a-j>', function() dap.step_into({ askForTargets = true }) end },
        { 'n', '<a-k>', function() dap.step_back({ askForTargets = true }) end },
        { 'n', '<a-l>', function() dap.step_over({ askForTargets = true }) end },
        { 'n', '<a-o>', function() dap.step_out({ askForTargets = true }) end },
        { 'n', '<a-g>', function() dap.run_to_cursor() end },
        { 'n', '<a-G>', function() dap.goto_() end },
        { 'n', '<cr>', function() dap.continue() end },
        { 'n', '<bs>', function() dap.reverse_continue() end },
        { 'n', '<a-r>', function() dap.restart() end },
        { 'n', '<space>', function() dap.pause() end },
        { 'n', '<c-n>', function() dap.down() end },
        { 'n', '<c-p>', function() dap.up() end },
        { 'n', '<c-m>', function() dap.focus_frame() end },
        { 'n', '<c-r>', function() dap.restart_frame() end },
        { 'n', 'rp', function() dap.repl.toggle() end },
        { 'n', '@>m-.<@', function()
            dap.terminate()
            if #dap.sessions() > 0 then
               return
            end

            for _, map in ipairs(map_bak_list) do
                util.restore_map(map)
            end
        end },
    }) do
        table.insert(map_bak_list, util.save_map(map[1], map[2]))
        vim.keymap.set(map[1], map[2], map[3])
    end
end)

Get error when restart session

Hi, i get error message when i execute dap.restart(), this is my config #31 (comment)

E5113: Error while calling lua chunk: Vim:E475: Invalid argument: Channel id must be a positive integer

stack traceback:
        [C]: in function 'rpcnotify'
        ...packer/start/one-small-step-for-vimkind/lua/osv/init.lua:55: in function 'sendProxyDAP
'
        ...packer/start/one-small-step-for-vimkind/lua/osv/init.lua:166: in function 'f'
        ...packer/start/one-small-step-for-vimkind/lua/osv/init.lua:631: in function '__index'
        t.lua:13: in main chunk

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.