airblade / vim-gitgutter

A Vim plugin which shows git diff markers in the sign column and stages/previews/undoes hunks and partial hunks.
MIT License
8.34k stars 296 forks source link

Added :GitGutterDiffOrigToggle and made :GitGutterDiffOrig would not … #857

Closed drazil100 closed 1 year ago

drazil100 commented 1 year ago

…open duplicate difforig buffers

One feature I felt was lacking in gitgutter is a way to quickly pull up :GitGutterDIffOrig and then dismiss it just as quickly.

How this works:

There is now a dictionary named s:difforigbuffers keyed to the buffer number of the buffer the diff is for with the value set to the number of the buffer that gets created. Whenever :GitGutterDiffOrigToggle or gitgutter#difforig_toggle() gets called it first loops through the s:difforigbuffersdictionary and checks if the current buffer number already exists as a key or value in the dictionary. If it is a value or it is a key that currently has a value that is a listed buffer then it closes the buffer and returns. If it isn't a key or isn't a value or the difforig buffer isn't listed then it calls gitgutter#difforig()

I also modified gitgutter#difforig() to check the same dictionary to prevent duplicate buffers from being created.

Let me know if there is anything that needs to be changes or if there are any weird edge cases I am not accounting for. Also I didn't know where to put the dictionary so I just put it above gitgutter#difforig()

drazil100 commented 1 year ago

I forgot to mention. The reason I created this is because I wanted to be able to map it to a key for a quick look back at what was changed without having to switch splits to close the difforig buffer. This is also safer as it makes it less likely you will close the actual file and leave only the difforig buffer behind.

airblade commented 1 year ago

Thanks for the suggestion.

This came up about a year ago. Does the solution here work for you?

drazil100 commented 1 year ago

I always forget to check the closed issues xD

Just gave it a try and it isn't quite as clean in functionality. With that solution it throws an error if you are not in a diff split

Error detected while processing function ToggleGitGutterDiffOrig:
line    2:
E16: Invalid range:     +clo

What I did works regardless of if you are in the diff split or the actual file's split as it actually tracks the buffer numbers with no split changing required. My solution does work on it's own without having to be part of the plugin and if you would prefer I keep it to my personal config I completely understand, but I would be happy to make any changes you want to make this work in your plugin if you are interested. I realize now in my excitement that I forgot to edit the documentation (though you may prefer to be the one to do that)

airblade commented 1 year ago

I thought about this some more and remembered that I implemented :GitGutterDiffOrig to match Vim's :DiffOrig. I want to keep it aligned with :DiffOrig so it behaves as people would expect.

Which means that I'll say no, thank you, to your patch.

Thanks very much anyway!

drazil100 commented 1 year ago

In that case I'll just leave this here for anyone reading this later who wishes to replicate my toggle setup in their personal vim / nvim configs. Thanks for taking the time to consider this feature.

lua:

-- Table of difforig buffers and buffers that spawned them
local my_diff_buffers = {}

function ToggleGitGutterDiffOrig()
  for k, v in pairs(my_diff_buffers) do
    if fn.bufnr('%') == k and vim.api.nvim_buf_is_valid(v) or vim.fn.bufnr('%') == v then
      -- The buffer is open, so close the split
      vim.api.nvim_buf_delete(v, { force = true })
      my_diff_buffers[k] = nil
      return
    end
  end
  -- The buffer is closed, so open the split and store the buffer number
  cmd("GitGutterDiffOrig")
  my_diff_buffers[vim.fn.bufnr('%')] = vim.fn.bufnr('$')
end

vim.api.nvim_set_keymap('n', '<F2>', '<cmd>lua ToggleGitGutterDiffOrig()<CR>', {silent=true})

vimscript:

" Table of difforg buffers and the buffers that spawned them
let s:my_diff_buffers = {}

function! ToggleGitGutterDiffOrig()
  for [k, v] in items(s:my_diff_buffers)
    if (bufnr('%') == k && buflisted(v)) || bufnr('%') == v
      " The buffer is open, so close the split
      execute 'bwipeout ' . v
      call remove(s:my_diff_buffers, k)
      return
    endif
  endfor

  " The buffer is closed, so open the split and store the buffer number
  call gitgutter#difforig()
  let s:my_diff_buffers[bufnr('%')] = bufnr('$')
endfunction

nnoremap <silent> <F2> :call ToggleGitGutterDiffOrig()<CR>