persistent-breakpoints.nvim icon indicating copy to clipboard operation
persistent-breakpoints.nvim copied to clipboard

Doesn't work well with sessions

Open foxt451 opened this issue 1 year ago • 1 comments

The problem I have is when I have buffers in sessionoptions and save/restore a session with some buffers having breakpoints. Apparently, upon restoring session neovim adds buffers to your buffer list, but doesn't load their contents. And so when breakpoints.set is called with a line number, the breakpoint ends up at the beginning of the file. I've tried various Buf* events in the config.

Could we somehow add code that loads the related buffers before setting the breakpoints in them?

I replicated this by adding a breakpoint to a file, navigating to another file, then :mksession!, close neovim, open neovim, :source Session.vim and navigating back to the file with a breakpoint

foxt451 avatar Sep 12 '24 23:09 foxt451

I am using "rmagatti/auto-session" and having the same issue.

TendonT52 avatar Oct 14 '24 18:10 TendonT52

please provide a minimal config to re-produce the bug.

Weissle avatar Oct 26 '24 17:10 Weissle

Here is the config to reproduce

{
    "Weissle/persistent-breakpoints.nvim",
    config = function()
        require("persistent-breakpoints").setup({ load_breakpoints_event = { "BufReadPost" } })
    end,
    keys = {
        {
            "<leader>db",
            function()
                require("persistent-breakpoints.api").toggle_breakpoint()
            end,
            desc = "Set breakpoint",
        },
        {
            "<leader>dB",
            function()
                require("persistent-breakpoints.api").toggle_breakpoint()
            end,
            desc = "Clear breakpoints",
        },
        {
            "<leader>dp",
            function()
                require("persistent-breakpoints.api").set_log_point()
            end,
            desc = "Print point",
        },
        {
            "<leader>dC",
            function()
                require("persistent-breakpoints.api").set_conditional_breakpoint()
            end,
            desc = "Breakpoint Condition",
        },
    },
},
{
    "rmagatti/auto-session",
    lazy = false,
    config = function()
        require("auto-session").setup({
            auto_session_suppress_dirs = { "~/config", "~/repos" },
        })
    end,
}

But I already solved it by using daic0r/dap-helper.nvim instead

{
    "daic0r/dap-helper.nvim",
    dependencies = { "rcarriga/nvim-dap-ui", "mfussenegger/nvim-dap" },
    config = function()
        require("dap-helper").setup()
    end,
}

You can see the full change here https://github.com/TendonT52/.config/commit/567a48dc941208bd487106596380d833423e728b

TendonT52 avatar Oct 27 '24 08:10 TendonT52

Here is the config to reproduce

{
    "Weissle/persistent-breakpoints.nvim",
    config = function()
        require("persistent-breakpoints").setup({ load_breakpoints_event = { "BufReadPost" } })
    end,
    keys = {
        {
            "<leader>db",
            function()
                require("persistent-breakpoints.api").toggle_breakpoint()
            end,
            desc = "Set breakpoint",
        },
        {
            "<leader>dB",
            function()
                require("persistent-breakpoints.api").toggle_breakpoint()
            end,
            desc = "Clear breakpoints",
        },
        {
            "<leader>dp",
            function()
                require("persistent-breakpoints.api").set_log_point()
            end,
            desc = "Print point",
        },
        {
            "<leader>dC",
            function()
                require("persistent-breakpoints.api").set_conditional_breakpoint()
            end,
            desc = "Breakpoint Condition",
        },
    },
},
{
    "rmagatti/auto-session",
    lazy = false,
    config = function()
        require("auto-session").setup({
            auto_session_suppress_dirs = { "~/config", "~/repos" },
        })
    end,
}

But I already solved it by using daic0r/dap-helper.nvim instead

{
    "daic0r/dap-helper.nvim",
    dependencies = { "rcarriga/nvim-dap-ui", "mfussenegger/nvim-dap" },
    config = function()
        require("dap-helper").setup()
    end,
}

You can see the full change here TendonT52/.config@567a48d

Thanks this worked for me

Ajaymamtora avatar Oct 27 '24 17:10 Ajaymamtora

I also encountered this, just by opening multiple files at a time (either as tab pages or windows). So this bug affects more than just sessions.

In minimal.lua:

local vim = vim

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
    spec = {
        {
            'mfussenegger/nvim-dap', -- Debug Adapter Protocol (DAP) client.
            dependencies = { 'Joakker/lua-json5', },
            config = function()
                -- Read DAP configuration from ".vscode/launch.json", if it exists. Provided by nvim-dap.
                require('dap.ext.vscode').load_launchjs(nil, {})
            end,
        },
        {
            'Weissle/persistent-breakpoints.nvim', -- save breakpoints between sessions.
            opts = {
                load_breakpoints_event = { "BufReadPost" },
                -- Breakpoints are saved in the following directory.
                save_dir = vim.fn.stdpath("data") .. "/persistent_breakpoints",
            }
        },
    },
})

Then start neovim with either nvim -u minimal.lua -O file1.ext file2.ext or nvim -u minimal.lua -p file1.ext file2.ext, and set breakpoints in both files using lua require('persistent-breakpoints.api').toggle_breakpoint(). The next time you run the command, the breakpoint in file2.ext is in line 1. However, if you swap the order of file1.ext and file2.ext on the command line, the breakpoint in file2.ext is in the right place, while the one for file1.ext shows in line 1. If you open more than 2 files, only the first file has the right breakpoint, while the rest all show on line 1.

dlyongemallo avatar Jan 10 '25 12:01 dlyongemallo

I'm pretty happy with the following workaround:

return {
    'Weissle/persistent-breakpoints.nvim',
    -- ...
    keys = {
        {
            '<leader>d,',
            function()
                require('persistent-breakpoints.api').reload_breakpoints()
                -- Reopen DAP UI to update breakpoint list (it won't happen automatically) 
                require('dapui').toggle()
                require('dapui').toggle()
            end,
            desc = 'Reload breakpoints',
        },
    },
}

If I open DAP UI and see that the breakpoint I'm interested in doesn't doesn't have a line number, I open that file and use the specified binding to reload the breakpoints. It's a bit of extra work, but not much. I understand though if it's not a sufficient solution for everyone, especially if you have multiple breakpoints and you'd like all of them to work after closing and reopening the editor.

rafalglowacz avatar Jan 11 '25 22:01 rafalglowacz

@Weissle Is there any reason not to always call reload_breakpoints instead of load_breakpoints on the load_breakpoints_event? I found that if I changed this line to use reload instead of load, the bug goes away.

dlyongemallo avatar Jan 12 '25 16:01 dlyongemallo

Maybe there is a ordering problem between session loading and breakpoint loading. Always use reload has impact on the performance, but I think usually we will not feel the difference. Will fix it sooner.

Weissle avatar Mar 02 '25 17:03 Weissle

@rafalglowacz Why not have it automatically reload based on some event, rather than a keybind? e.g., when the DAP UI is launched:

local dap, dapui = require("dap"), require("dapui")
dap.listeners.before.launch.dapui_config = function()
    require('persistent-breakpoints.api').reload_breakpoints()
    dapui.open()
end

dlyongemallo avatar Mar 20 '25 11:03 dlyongemallo