Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

virtual text does not hide while run lua require'dap'.stop() #14

Open
y1rn opened this issue Jul 22, 2021 · 27 comments
Open

virtual text does not hide while run lua require'dap'.stop() #14

y1rn opened this issue Jul 22, 2021 · 27 comments

Comments

@y1rn
Copy link

y1rn commented Jul 22, 2021

text does not hide call lua require'dap'.stop() in debugging

@theHamsta
Copy link
Owner

@mfussenegger at the moment virtual text get's hidden on

event_terminated
event_exited
event_continued

exited/terminated don't get triggered with all debug adapters. Any recommendations how I could reliably clear when the debug session stops?

@mfussenegger
Copy link

I think the problem here is that stop() is only closing the session, without telling the debug adapters about it.

Users have to call dap.disconnect(); dap.stop() to properly end the session. I'll try to improve the docs in nvim-dap to clarify the behavior.

@mfussenegger
Copy link

See mfussenegger/nvim-dap#251

@y1rn
Copy link
Author

y1rn commented Jul 27, 2021

dap.disconnect() or dap.close() no trigger event_terminated or event_exited

@mfussenegger
Copy link

That would also mean that the debug adapter and possibly the application you debug keep running. With which debug adapter does that happen, and how does your configuration look like?

It would be possible to generate some kind of client_closed_session event within nvim-dap, but it is possible that this would only hide problems and not fix the root cause.

@y1rn
Copy link
Author

y1rn commented Jul 28, 2021

local dap = require('dap')
dap.adapters.go= function(cb)
  local stdout = vim.loop.new_pipe(false)
  local handle
  local pid_or_err
  local port = 38697
  local root_dir = require 'lspconfig/configs'.gopls.get_root_dir(vim.fn.expand '%:p:h')
  local opts = {
    stdio = {nil, stdout},
    args = {"dap", "-l", "127.0.0.1:" .. port},
    cwd = root_dir,
    detached = true
  }
  handle, pid_or_err = vim.loop.spawn("dlv", opts, function(code)
    stdout:close()
    handle:close()
    if code ~= 0 then
      print('dlv exited with code', code)
    end
  end)
  assert(handle, 'Error running dlv: ' .. tostring(pid_or_err))
  stdout:read_start(function(err, chunk)
    assert(not err, err)
    if chunk then
      vim.schedule(function()
        --- You could adapt this and send `chunk` to somewhere else
        require('dap.repl').append(chunk)
      end)
    end
  end)
  -- Wait for delve to start
  vim.defer_fn(
    function()
      cb({type = "server", host = "127.0.0.1", port = port})
    end,
    100)
end


dap.configurations.go = {
  {
    type = "go",
    name = "Debug",
    request = "launch",
    -- program = "${workspaceFolder}",
    program=function()
      return require 'lspconfig/configs'.gopls.get_root_dir(vim.fn.expand '%:p:h')
    end,
    showLog = "true"
  },
  {
    type = "go",
    name = "Debug file",
    request = "launch",
    -- program = "${file}",
    program = function()
      return vim.fn.fnamemodify(vim.fn.bufname(), ':p')
    end
  },
  {
    type = "go",
    name = "Debug test", -- configuration for debugging test files
    request = "launch",
    mode = "test",
    args = function()
      local lines = vim.fn.readfile(vim.fn.fnamemodify(vim.fn.bufname(), ':p'))
      local fns = {} 
      for _, l in pairs(lines) do
        local name = string.match(l,'^%s*func.*Test(.+)%(')
        if name then 
          table.insert(fns,name)
        end
      end
      if #fns < 1 then
        error("no test case found")
      elseif #fns == 1 then
        return {
          "--test.run",
          "Test"..fns[1]
        }
      else 
        local option_strings =  {"\n\nselect test case: "} 
        for i, case in ipairs(fns) do
          table.insert(option_strings, string.format("%d: %s", i, case))
        end
        local choice = vim.fn.inputlist(option_strings)
        if choice < 1 or choice > #fns then
          error('out of index') 
        end
        return {
          "--test.run",
          "Test"..fns[choice]
        }
      end
    end,
    --program = "${file}"
    program = function()
      return vim.fn.fnamemodify(vim.fn.bufname(), ':p:h')
    end
  },
}


local getExeFile=function()
  local cmd = "cargo metadata --no-deps --format-version 1"
  local cargo_metadata = vim.fn.system(cmd)
  local cargo_workspace_dir = nil
  if vim.v.shell_error == 0 then
    cargo_workspace_dir = vim.fn.json_decode(cargo_metadata)["workspace_root"]
  end
  local fp = cargo_workspace_dir .. '/target/debug/'
  local files = vim.fn.readdir(fp);
  local ss = {}
  for _, v in pairs(files) do
    local p = fp ..v
    if vim.fn.executable(p) == 1 then
      table.insert(ss, v)
    end
  end
  if #ss == 0 then
    return 
  end 
  if #ss == 1 then
    return fp .. ss[1]
  end
 
  local option_strings =  {"select crate: "} 
  for i, runnable in ipairs(ss) do
    table.insert(option_strings, string.format("%d: %s", i, runnable))
  end
  local choice = vim.fn.inputlist(option_strings)
  if choice < 1 or choice > #ss then
     return
  end
  return fp .. ss[choice]
end



dap.adapters.lldb = {
  type = 'executable',
  command = '/usr/bin/lldb-vscode-11', -- adjust as needed
  name = "lldb"
}
dap.configurations.rust = {
  {
    name = "Launch",
    type = "lldb",
    request = "launch",
    program = function()
      vim.fn.system('cargo build')
      -- return getExeFile(vim.fn.getcwd() .. '/target/debug/')
      return getExeFile()
    end,
    cwd = '${workspaceFolder}',
    stopOnEntry = false,
    args = {},
    runInTerminal = false,
  	env = function()
      local variables = {}
      for k, v in pairs(vim.fn.environ()) do
        table.insert(variables, string.format("%s=%s", k, v))
      end
      return variables
    end,
  },
}

--dap.listeners.after['event_terminated']['my-plugin'] = function(session, body)
dap.listeners.after['event_exited']['my-plugin'] = function(session, body)
  dap.repl.close() 
end
dap.listeners.after['output']['my-plugin'] = function(session, body)
  dap.repl.open() 
end

require('dap.ext.vscode').load_launchjs()

@theHamsta
Copy link
Owner

Maybe I should also react to the disconnect/terminate request to clear the text

@Shatur
Copy link

Shatur commented Sep 9, 2021

Users have to call dap.disconnect(); dap.stop() to properly end the session. I'll try to improve the docs in nvim-dap to clarify the behavior.

@mfussenegger I tried it, but the text still exists.

@JoseConseco
Copy link

@theHamsta any chance that you could expose command virtual_text.toggle or disable ?

@theHamsta
Copy link
Owner

I wanted to refactor the plugin to allow more options and initialization with a proper setup call. When I started the plugin I wanted to have minimal setup and I couldn't think other option than activated and deactivated. I can also add a toggle command

I guess toggling should be something like

vim.g.dap_virtual_text = not vim.g.dap_virtual_text
dap.listeners.after.variables["nvim-dap-virtual-text"](require'dap'.session())

@ranebrown
Copy link

I'm seeing the same issue using cpptools and virtual text remaining after calling disconnect then stop.

@theHamsta
Copy link
Owner

There is now :DapVirualTextForceRefresh as a mitigation, for a proper fix I would need to get notified when one of the termination methods get call in nvim-dap. Right now I'm just reacting to events in the DAP protocol. When a debug adapter fails to terminate properly won't receive a notification that it is not there anymore.

@JoseConseco there are now :DapVirualTextEnable, :DapVirualTextDisable, :DapVirualTextToggle

@mfussenegger
Copy link

There is now also a terminate function in nvim-dap which helps terminate some debug adapters. See mfussenegger/nvim-dap#345

@JoseConseco
Copy link

@theHamsta thanks. It works great now. I can combine now: dap.close()| DapVirtualTextDisable so I no longer have to restart vim to remove the virtual text.

@theHamsta
Copy link
Owner

@JoseConseco you probably want a dap.close() | DapVirtualTextForceRefresh. Or you else you'd need to enable the virtual text again when you start your next debug session DapVirtualTextEnable

@Shatur
Copy link

Shatur commented Nov 1, 2021

DapVirtualTextForceRefresh

I have E5108: Error executing lua [string ":lua"]:1: attempt to call field 'refresh' (a nil value).

@theHamsta
Copy link
Owner

Sorry, I wanted refresh originally to be private. Should be exported now.

@Shatur
Copy link

Shatur commented Nov 1, 2021

Sorry, I wanted refresh originally to be private. Should be exported now.

Now I have another error: E5108: Error executing lua ...tart/nvim-dap-virtual-text/lua/nvim-dap-virtual-text.lua:46: attempt to index local 'session' (a nil value)

@theHamsta
Copy link
Owner

theHamsta commented Nov 1, 2021

I'm really stupid today 😓 Refresh should clear virtual text now only when there's no session (bcea8a4)

@Shatur
Copy link

Shatur commented Nov 1, 2021

Now works, thank you!

@JoseConseco
Copy link

DapVirtualTextForceRefresh works indeed better than DapVirualTextDisable. Btw I think this issue can be closed.

@theHamsta
Copy link
Owner

You're sure? I feel this should happen automatically and without you needing to invoke a command.

@theHamsta
Copy link
Owner

theHamsta commented Mar 28, 2023

I think upstream has done a lot to trigger the event even if the debug adapter hang up .

@crhf
Copy link

crhf commented Jul 7, 2023

Even :DapVirualTextDisable doesn't clear the virt text for me: no new text is produced, but the old text does not hide.

@theHamsta theHamsta reopened this Jul 7, 2023
@crhf
Copy link

crhf commented Jul 7, 2023

I've figured it out. The virt text hides when the debugee executes to the end and exits, and when I call dap.terminate. But if I call dap.close, then the virt text persists, and nothing I do afterwards can ever get them hidden (DapVirtualTextDisable, dap.terminate and DapVirtualTextRefresh, etc.).

So I can just use dap.terminate, though I still wonder why dap.close() | DapVirtualTextForceRefresh doesn't work for me.

@mfussenegger
Copy link

I still wonder why dap.close() | DapVirtualTextForceRefresh doesn't work for me.

dap.close() closes the session object on the client, it doesn't go through the proper termination routine specified by the debug adapter protocol.

See :h dap.close():

Closes the current session.

This does NOT terminate the debug adapter or debugee.
You usually want to use either |dap.terminate()| or |dap.disconnect()|
instead.

@h0m3
Copy link

h0m3 commented Feb 9, 2024

I've figured it out. The virt text hides when the debugee executes to the end and exits, and when I call dap.terminate. But if I call dap.close, then the virt text persists, and nothing I do afterwards can ever get them hidden (DapVirtualTextDisable, dap.terminate and DapVirtualTextRefresh, etc.).

So I can just use dap.terminate, though I still wonder why dap.close() | DapVirtualTextForceRefresh doesn't work for me.

Can confirm. Looks like closing the session is not the correct approach, for me dap.terminate();dap.disconnect() seems to do the trick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants