diffview.nvim icon indicating copy to clipboard operation
diffview.nvim copied to clipboard

Allow DiffviewOpen to switch to already opened diffview tab

Open drybalka opened this issue 2 years ago • 14 comments

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.

drybalka avatar Jun 21 '22 15:06 drybalka

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

sindrets avatar Jun 24 '22 00:06 sindrets

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 open Diffview, review some changes
  • hit gf to open the file
  • do some other edits, maybe switch to another file
  • open Diffview again

-> 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".

tuxflo avatar Sep 15 '22 15:09 tuxflo

@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.

sindrets avatar Sep 19 '22 13:09 sindrets

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 avatar Nov 18 '22 21:11 ryuheechul

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.

ryuheechul avatar Nov 18 '22 22:11 ryuheechul

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>",
    },
  },
}

sindrets avatar Nov 18 '22 22:11 sindrets

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

ryuheechul avatar Nov 18 '22 22:11 ryuheechul

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!

hinell avatar Jun 30 '23 07:06 hinell

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.

sindrets avatar Jun 30 '23 09:06 sindrets

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

hinell avatar Jun 30 '23 11:06 hinell

@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.

sindrets avatar Jun 30 '23 11:06 sindrets

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

alex35mil avatar Oct 05 '23 14:10 alex35mil

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.

kevintraver avatar Apr 07 '24 16:04 kevintraver

@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.

hinell avatar Apr 10 '24 16:04 hinell