Nino Cangialosi
Nino Cangialosi

Reputation: 65

Defining a shortcut only in vimdiff

I have been using vimdiff in its vimdiff1 layout, where it opens side by side the two buffer of LOCAL and REMOTE. The reason I preferred this layout over the other standard layout is the two shortcuts do and dp for getting and putting diff chuncks respectively.

------------------------------------------
|                   |                    |
|                   |                    |
|                   |                    |
|     LOCAL         |    REMOTE          |
|                   |                    |
|                   |                    |
|                   |                    |
------------------------------------------

Yet, recently I came across the scenario in which I often had do take a mixture of the two chuncks, for which manual editing to the MERGED file has been easier.

Now, I would like to switch to a LOCAL,MERGED,REMOTE layout, and I was wondering if it's possible to define custom keybinding only for vimdiff. Namely, I'd like to define two gl and gr shorcuts for :diffget LOCAL and :diffget REMOTE.

------------------------------------------
|             |           |              |
|             |           |              |
|   LOCAL     |   MERGED  |   REMOTE     |
|             |           |              |
|             |           |              |
------------------------------------------

Is there a way to define a keybinding only for the vimdiff 'mode'? Or alternatively, are there already standands keybindings which I'm not aware of? For reference: https://git-scm.com/docs/vimdiff/en

Of course, I could set these to be global keybindings with:

noremap gl :diffget LOCAL<CR>
noremap gr :diffget REMOTE<CR>

But this would apply them globally to the normal mode.

Upvotes: 3

Views: 325

Answers (2)

romainl
romainl

Reputation: 196926

But this would apply them globally to the normal mode.

  • gl does nothing in normal mode by default and gr is a very niche command that you have probably never used or heard of, so they are quite safe to map globally.
  • Since those mappings are meant for a specific context, you wouldn't accidentally use them outside of that context anyway.

So I think you can safely add them to your vimrc, but with a slight modification:

nnoremap gl :diffget LOCAL<CR>
nnoremap gr :diffget REMOTE<CR>

:noremap creates a non-recursive mapping for normal mode, visual mode, and operator-pending mode, which is not exactly a good idea if that scenario is not handled properly (it's only useful for custom motions). :nnoremap restricts your mappings to normal mode, which is more in line with what you are trying to do.

That said, if you really want to have those mappings only for diffs, it could be done with a :help <expr> mapping, like this:

nnoremap <expr> gl &diff ? ':diffget LOCAL<CR>' : 'gl'
nnoremap <expr> gr &diff ? ':diffget REMOTE<CR>' : 'gr'

where the mapping is kept global but its right-hand side is evaluated at runtime, yielding different macros in different contexts. Here, the check is done on the :help 'diff' option: if it is enabled, then gl does :diffget LOCAL<CR>, if it is not, then gl does gl.

Upvotes: 2

B.G.
B.G.

Reputation: 6036

Well there is no special map mode for the diff window (that would also make no sense). So you usually have to work with map-local to achieve your Goal of mappings for a special buffer:

au BufRead * if &diff | exe 'noremap <buffer> gl :diffget LOCAL<CR>' | exe 'noremap <buffer> gr :diffget REMOTE<CR>' | endif

This however leaves the mapping on your buffer if diff mode is exited. Diff is not a special buffer, but a special mode. For that case it is easier to use the <expr> callback:

nnoremap <expr> gl &diff ? ':diffget LOCAL<CR>' : 'gl'

Which is evaluated every time you press the mapping.

Why do I even talk about the first solution? Well it is the usual way I was heading down, so I guess it isn't bad to state why it isn't the best idea in this case.

Upvotes: 2

Related Questions