sindrets / diffview.nvim

Single tabpage interface for easily cycling through diffs for all modified files for any git rev.
Other
3.72k stars 105 forks source link

Allow DiffviewOpen to switch to already opened diffview tab #162

Open drybalka opened 2 years ago

drybalka commented 2 years ago

Currently DiffviewOpen simply opens a new tab with a new Diffview instance even if it was already opened. Sometimes that is what user wants, but it would also be convenient to provide an option, such that DiffviewOpen switches to the already opened Diffview tab if it exists.

sindrets commented 2 years ago

Sure, we could add something like a --use-last option.

tuxflo commented 1 year ago

I also think, that this might be a good idea. Especially because in the current version the "open file" (default mapping gf) is somewhat strange.

-> I'd think that I'm back at the "first" Diffview but instead two Diffview tabs are open now.

For me either the mentioned --use-last or --unique or something like that would be great, or a new option in the file panel with does "open selected file and quit diffview".

sindrets commented 1 year ago

@tuxflo I personally think this is an XY problem, that should probably rather be solved by getting more familiar with tab management in vim. :DiffviewOpen was never designed to work as a toggle. It seems that you expect the command to operate under a rather arbitrary set of rules. In actuality it's very simple: the command does exactly what it says on the tin. It always opens a diffview in a new tab page.

-> I'd think that I'm back at the "first" Diffview

Why would you think that? You wouldn't call :tabnew or :tabe and expect that to operate on the tab you were in before, would you?

In the problem you describe you could've just used :h g<Tab> to achieve what you wanted. This default mapping brings you back to your last accessed tab page.

or a new option in the file panel with does "open selected file and quit diffview"

You can add this in your own config. The keymap table accepts both functions and vim commands as the rhs. Just call the goto_file* action first and then use :tabclose # to close the view.

ryuheechul commented 1 year ago

I think what's explained by @sindrets can be expressed as below (which works for me).

local actions = require 'diffview.actions'

require('diffview').setup {
  keymaps = {
    file_panel = {
      ['gf'] = function()
        actions.goto_file()
        vim.cmd 'tabclose #'
      end,
    },
  },
}
ryuheechul commented 1 year ago

I originally wanted a toggling behaviour as well but I found a way that avoid the need all together by editing the buffer right at the Diffview tab with the config below.

local actions = require 'diffview.actions'

require('diffview').setup {
  keymaps = {
    view = {
      -- instead of cycle through another buffer, move around window
      ['<tab>'] = '<Cmd>wincmd w<CR>',
      -- instead of closing one buffer, do `DiffviewClose`
      ['q'] = actions.close,
    },
    file_panel = {
      -- just select them when moving
      ['j'] = actions.select_next_entry,
      ['k'] = actions.select_prev_entry,
      ['<down>'] = actions.select_next_entry,
      ['<up>'] = actions.select_prev_entry,
      -- all of them to just go to the diff2 (right panel) so you can edit right at the Diffview tab
      ['gf'] = actions.focus_entry,
      ['<tab>'] = actions.focus_entry,
      ['<cr>'] = actions.focus_entry,
      -- these are extra that also makes sense to me
      ['h'] = actions.toggle_flatten_dirs,
      ['l'] = actions.focus_entry,
    },
  },
}

This allows me to quickly be able to edit via one of gf, <tab>, <cr>. And q to close Diffview while editing. And <tab> to move around between windows so I can get back to file_panel to choose other files.

_Ideally I would like to close Diffview on file_panel as well but somehow ['q'] = actions.close override works for view but not for file_panel._

sindrets commented 1 year ago

_Ideally I would like to close Diffview on file_panel as well but somehow ['q'] = actions.close override works for view but not for file_panel._

@ryuheechul Many of the actions - including close - are contextual. When invoked from a panel this action will close the panel. When invoked from the diff buffers, it will close the entire view. This is documented under :h diffview-actions.

If you want a mapping to close the view from the file panel, just do this:

require('diffview').setup {
  keymaps = {
    file_panel = {
      ["q"] = "<Cmd>tabc<CR>",
    },
  },
}
ryuheechul commented 1 year ago

@sindrets fantastic and that works like a charm, thanks!

hinell commented 1 year ago

It would be tricky you if you open diffview of different folders in different tabs...

Anyone can point me to a variable that keeps tracks of opened diffview tabs? Thanks!

sindrets commented 1 year ago

It would be tricky you if you open diffview of different folders in different tabs...

@hinell What do you mean? What would be tricky?

Anyone can point me to a variable that keeps tracks of opened diffview tabs? Thanks!

require("diffview.lib").views

Keep in mind that using the internal API is not supported, and these things may change at any point without warning.

hinell commented 1 year ago

@sindrets Would be nice if you expose some of these APIs to the users in a stable fashion. Thank you.

sindrets commented 1 year ago

@hinell I've stated several times that I'm willing to provide a stable API. But before that can happen we need to discuss specifically what the API should provide. And nobody has taken the initiative to start the discussion. Until that happens, offering any form of a stable API is a non-priority.

alex35mil commented 10 months ago

For anyone interested, I have similar toggle function with some bits specific to my configuration.

kevintraver commented 4 months ago

I think what's explained by @sindrets can be expressed as below (which works for me).

local actions = require 'diffview.actions'

require('diffview').setup {
  keymaps = {
    file_panel = {
      ['gf'] = function()
        actions.goto_file()
        vim.cmd 'tabclose #'
      end,
    },
  },
}

Wondering if this is something that can be passed as opts:

require("diffview.actions").goto_file_edit( {close_diffview = true} )

I just think it makes the keymaps read nicer.

hinell commented 4 months ago

@kevintraver I think the point of the OP is to ALWAYS keep a diffview window and focus on it whenever the :DiffviewOpen is run in given CWD. For several different working dirs there might be one diffview stuck.