carbon-steel / detour.nvim

Use popup windows to navigate files/buffer and to contain shells/TUIs
MIT License
153 stars 4 forks source link

Auto close Detour on win leave #2

Open JoseConseco opened 11 months ago

JoseConseco commented 11 months ago

I tried to make detour window automatically close when you leave it with:

      vim.keymap.set("n", "<c-w><enter>", function()
        require("detour").Detour() -- Open a detour popup
        local current_bufnr = vim.api.nvim_get_current_buf()
        local current_winid = vim.api.nvim_get_current_win()
        print(current_bufnr, current_winid)
        vim.bo.bufhidden = 'delete' -- close the terminal when window closes
        local test_au = vim.api.nvim_create_augroup("TimedayThemeAu", { clear = true })

        vim.api.nvim_create_autocmd({ "BufEnter" }, {
          -- pattern = "<buffer>",
          buffer = current_bufnr,
          callback = function()
            print "Blff leave"
            vim.api.nvim_win_close(current_winid, true)
          end,
          group = test_au,
          -- nested = true, -- dow notwork in this case
        })
      end)

But it does not seem to work. Maybe this could be added as option into detour itself...

carbon-steel commented 11 months ago

As I understand, you want the popup to close when you switch to another window correct?

In that case, I think you want to use the "WinLeave" event for your autocmd instead of the "BufEnter" event. I changed it (and a couple other things) and it works :)

vim.keymap.set("n", "<c-w><enter>", function()
  require("detour").Detour() -- Open a detour popup
  local current_bufnr = vim.api.nvim_get_current_buf()
  local current_winid = vim.api.nvim_get_current_win()
  vim.bo.bufhidden = 'delete' -- close the terminal when window closes
  -- I am not entirely sure if there is any benefit to having this augroup
  local test_au = vim.api.nvim_create_augroup("TimedayThemeAu", { clear = true })

  vim.api.nvim_create_autocmd({ "WinLeave" }, {
    buffer = current_bufnr,
    callback = function()
      print "Blff leave"
      vim.api.nvim_win_close(current_winid, true)
      -- this autocmd only needs to return once so make sure you return true so it deletes itself after running.
      return true
    end,
    group = test_au,
    -- this nested attribute is actually needed at the moment or breaks the plugin's assumptions.
    -- I need to update the plugin so it doesn't depend on users remembering to setting the nested attribute.
    nested = true,
  })
end)

Edit: Sorry, I got the code wrong the first time.

carbon-steel commented 11 months ago

Leave this open until #3 is resolved

JoseConseco commented 10 months ago

@carbon-steel any ideas why above code stopped working , after latest update?

carbon-steel commented 10 months ago

I'll take a look in a couple hours.

carbon-steel commented 10 months ago

I tried reproducing your error with the following steps:

  1. Open a new neovim instance with no user config/plugins except detour.nvim by running: nvim --clean --cmd "set rtp+=/path/to/your/detour.nvim/"
    • To figure out where your detour.nvim is installed, you have to check where plugin manager keeps installed plugins.
      • As an example, here is where lazy.nvim stores plugins.
    • Alternatively, you could also git clone this repo to a path of your choosing and provide that path to this command. Make sure that you're using the main branch. Either way works.
  2. Save the following code in a new lua file:

    vim.keymap.set("n", "<c-w><enter>", function()
    require("detour").Detour() -- Open a detour popup
    local current_bufnr = vim.api.nvim_get_current_buf()
    local current_winid = vim.api.nvim_get_current_win()
    vim.bo.bufhidden = 'delete' -- close the terminal when window closes
    -- I am not entirely sure if there is any benefit to having this augroup
    local test_au = vim.api.nvim_create_augroup("TimedayThemeAu", { clear = true })
    
    vim.api.nvim_create_autocmd({ "WinLeave" }, {
    buffer = current_bufnr,
    callback = function()
      print "Blff leave"
      vim.api.nvim_win_close(current_winid, true)
      -- this autocmd only needs to return once so make sure you return true so it deletes itself after running.
      return true
    end,
    group = test_au,
    -- this nested attribute is actually needed at the moment or breaks the plugin's assumptions.
    -- I need to update the plugin so it doesn't depend on users remembering to setting the nested attribute.
    nested = true,
    })
    end)
  3. From within the buffer of the new lua file, run :luafile % to execute the code.
  4. Run the :Detour command (a popup should appear)
  5. Switch out of the popup with <C-w>w (the popup should disappear)

Here is what happens on my system when I do this (ignore the pink color of the popup. That's just the default colorscheme.):

autocmd2.webm

Could you try this a let me know if it works for you?

If it doesn't, could you provide the first three lines from: nvim --version?

carbon-steel commented 9 months ago

Hey @JoseConseco, I've just introduced some changes to the plugin to add better autocmd support. Could you try running the plugin on the autocmds branch and see how it works for you? I'd like to get some feedback before merging it into main.

JoseConseco commented 9 months ago

I just tried, and sometimes closing detour window automatically, works - for example when using using ctrl+w + [jklw] (to switch to different window). But then if I try to open detour in new split - eg. using ctrl+v - then split will be done, but 'old' detour window will remain open.

local function close_on_leave()
  local attached_bufnr = vim.api.nvim_get_current_buf()
  local attached_winid = vim.api.nvim_get_current_win()
  -- vim.bo.bufhidden = 'delete' -- close the terminal when window closes
  -- I am not entirely sure if there is any benefit to having this augroup
  local test_au = vim.api.nvim_create_augroup("DetourClose", { clear = true })

  vim.api.nvim_create_autocmd({ "WinEnter"}, {
    buffer = attached_bufnr,
    callback = function()
      print "Detour leave"
      -- check if current window is floating. If it is, skip closing detur window
      local winid = vim.api.nvim_get_current_win()
      if vim.api.nvim_win_get_config(winid).relative ~= "" or winid == attached_winid then
        return
      end
      vim.api.nvim_win_close(attached_winid, true)
      -- this autocmd only needs to return once so make sure you return true so it deletes itself after running.
      return true
    end,
    group = test_au,
    -- this nested attribute is actually needed at the moment or breaks the plugin's assumptions.
    -- I need to update the plugin so it doesn't depend on users remembering to setting the nested attribute.
    nested = true,
  })
end

vim.keymap.set("n", "<c-w><enter>", function()
  require("detour").Detour() -- Open a detour popup
  close_on_leave()
end)
vim.keymap.set("n", "gD", function()
  require("detour").DetourCurrentWindow() -- Open a detour popup
  close_on_leave()
  -- vim.bo.bufhidden = 'delete' -- delete this scratch buffer when we move out of it
  require('telescope.builtin').lsp_definitions({initial_mode = 'normal'})

end)
JoseConseco commented 9 months ago

In the end, it would be cool if detour had build in option, where its floating window is closed automatically, when it is left.

carbon-steel commented 9 months ago

I think this code should work. Could you give it a try?

local function close_on_leave(popup_id)
    -- This autocmd will close the created detour popup when you focus on a different window.
    vim.api.nvim_create_autocmd({ "WinEnter" }, {
        callback = function()
            local window_id = vim.api.nvim_get_current_win()
            -- Skip cases where we are entering popup menus or the detour popup itself.
            if vim.api.nvim_win_get_config(window_id).relative ~= "" or window_id == popup_id then
                return
            end

            -- Check to make sure the popup has not already been closed
            if vim.tbl_contains(vim.api.nvim_list_wins(), popup_id) then
                vim.api.nvim_win_close(popup_id, false)
            end

            -- delete this autocmd if the popup was closed
            return not vim.tbl_contains(vim.api.nvim_list_wins(), popup_id)
        end,
    })
end

vim.keymap.set("n", "<c-w><enter>", function()
    local ok = require("detour").Detour() -- Open a detour popup

    if ok then
        close_on_leave(vim.api.nvim_get_current_win())
    end
end)

vim.keymap.set("n", "gD", function ()
    local ok = require("detour").Detour() -- Open a detour popup
    -- Call this function whether or not a detour popup was successfully created. This means we fallback to using the current window if the popup failed.
    require('telescope.builtin').lsp_definitions({initial_mode = 'normal'})

    if ok then
        close_on_leave(vim.api.nvim_get_current_win())
    end
end)

If this code works for you, I'd like to incorporate this close_on_leave function to the plugin as an additional feature as you suggested :)

JoseConseco commented 9 months ago

It works now. I must be bad at lua :/ . Thanks, all is great now. I can create split from detour, and it will close popup ok now.

carbon-steel commented 9 months ago

I've merged the changes in the autocmds branch in to the dev branch. Could you switch to the dev branch and let me know when you've done so? I'll delete the autocmds branch afterwards.

JoseConseco commented 9 months ago

Done. All seems work ok, on dev too.

carbon-steel commented 9 months ago

Great! thanks :)

I must be bad at lua :/.

No, autocmd's are genuinely tricky. I've been wrestling with them the whole time I've been working on this plugin.