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

Toggle behavior for interactive windows/buffer managed by Fugitive? #2364

Closed
Atan-D-RP4 opened this issue Dec 25, 2024 · 3 comments
Closed

Comments

@Atan-D-RP4
Copy link

I wish the interactive Fugitive Commands like ':Git' had toggling behavior or some way to implement toggling behaviour, specifically for keymaps. I want to be able to use the same command/keymap to close and open the Fugitive windows/buffers.

Right now, any open Fugitive window I close with q or ':bd', which doesn't really feel natural. It feels like hacky workaround.
Maybe option/global variable specific to certain commands for this sort of thing is possible? There is not even any way to properly receive information that the buffer/window the command wants to open is already open or anyway to check something like that to script such functionality personally. Though maybe there is and I haven't found it? I'm coming from Neovim, and Lua is a lot simpler and comprehensible to me for that kind of scripting than Vimscript for me.

@davelens
Copy link

davelens commented Jan 19, 2025

Hi, I'm not Tim.

Firstly I'll throw in my unsolicited €0.02 and say that whenever you run :G it already moves your cursor inside the fugitive buffer because it assumes you want to do something there. Once there you can press gq to close the fugitive buffer and you'll end up wherever your cursor was when you called :G. I know that's not strictly a toggle, but it's the next best thing. I dare say most people have their fugitive mapped to <leader>g, or something related to g, so at least one finger is already in position to get to gq anyway.

Now secondly, if I know Tim (and I don't), the above is very much done on purpose and he won't be looking to build in a toggle. BUT, if one were to build this into their own config anyway, you'd need two things:

1. A way to check for an open fugitive buffer

This would involve looping vim.api.nvim_list_bufs() and match their type with nvim_buf_get_name():match():

-- ./lua/buffers.lua
local buffers = {}

function buffers.is_open(buf_type)
  for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
    if vim.api.nvim_buf_is_loaded(bufnr) then
      local bufname = vim.api.nvim_buf_get_name(bufnr)
      if bufname:match(buf_type) then
        return true
      end
    end
  end
  return false
end

return buffers

2. A keymap to something that uses said function to either open or close fugitive

-- ./lua/maps.lua
map("n", "<leader>g", function()
  if require('buffers').is_open("fugitive://") then
    vim.cmd("bdelete " .. vim.g.current_fugitive_buf)
    vim.g.current_fugitive_buf = nil
  else
    -- Save your cursor position
    local current_win = vim.api.nvim_get_current_win()
    local current_pos = vim.api.nvim_win_get_cursor(current_win)

    -- Call fugitive and save the buffer number
    vim.cmd("G")
    vim.g.current_fugitive_buf = vim.api.nvim_get_current_buf()

    -- Move back to your original cursor position
    vim.api.nvim_set_current_win(current_win)
    vim.api.nvim_win_set_cursor(current_win, current_pos)
  end
end, { desc = "Toggle vim-fugitive" })

Not very robust, since this is banking on you always opening every fugitive window with the same keymap to allow vim.g.current_fugitive_buf to always hold the value of the fugitive buffer (which is necessary to close it). You'll want to check if that value isn't nil at least. But at any rate the happy path seems to Work On My Computer™.

In conclusion, I'd stll recommend for fugitive to do the heavy lifting for you, and stick to the buffer maps whenever you call :G. ✌🏻

@Atan-D-RP4
Copy link
Author

Thanks for the reply.

The solution for this that I used was just an autocmd that I stole off of folke's LazyVim that allows a buffers with certain filetypes to be closed with just keypress of 'q'. Then I just added, fugitive and git filetypes to that list in the autocmds callback.

For reference:

vim.api.nvim_create_autocmd('FileType', {
  group = vim.api.nvim_create_augroup('close-with-q', { clear = true }),
  pattern = {
    'PlenaryTestPopup',
    'checkhealth',
    'dbout',
    'gitsigns-blame',
    'grug-far',
    'help',
    'lspinfo',
    'neotest-output',
    'neotest-output-panel',
    'neotest-summary',
    'notify',
    'git',
    'fugitive',
    'qf',
    'spectre_panel',
    'startuptime',
    'tsplayground',
  },
  callback = function(event)
    vim.bo[event.buf].buflisted = false
    vim.schedule(function()
      vim.keymap.set('n', 'q', function()
        vim.cmd 'close'
        pcall(vim.api.nvim_buf_delete, event.buf, { force = true })
      end, {
        buffer = event.buf,
        silent = true,
        desc = 'Quit buffer',
      })
    end)
  end,
})

@davelens
Copy link

Ha, that man has a generic solution for everything. Thanks for the share! <3

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

2 participants