6

Sometimes in a diff I want to obtain just the single line that I'm on. So I made the following mappings:

nnoremap dO :.diffget<CR>
nnoremap dP :.diffput<CR>

This worked well, except now whenever I do dd it sits and waits for more input since the last d could be the start of one of my new mappings. Now, of course I could just change my mappings to something different to solve this problem, but this means that I can't use any of the d namespace that isn't currently being used which is quite unfortunate. I want vim to understand that I'm simply trying to extend the d namespace. dd is a finished command and ddO is invalid, therefore there is no need to wait after dd has been entered. Is there a way to accomplish this?

  • 4
    I do not see why your mappings would cause a delay after dd. I have tested your mappings and I see no delay with dd. Are you sure you do not have another set of conflicting mappings? Use :verbose nmap dd to see all dd related mappings. – Peter Rincker Jul 8 '16 at 22:23
  • @PeterRincker Before I put the mapping, dd works as expected. After the mapping dd pauses for a few seconds before acting. :verbose nmap dd reports "No mapping found." I have noticed after some experimentation that when set from my .vimrc I experience this problem, but when I set it straight from an ex command it works as you've described. Not sure why there would be a disconnect there, but honestly the wait seems like expected behavior to me. – Tumbler41 Jul 11 '16 at 13:25
  • 1
    There should be no difference between defining the commands in your vimrc or via an ex command. I was able to successfully test your mappings in my vimrc without a delay. If you are still experiencing a delay then I must assume there is something in your vimrc that is causing the issue. I would suggest you start with a bare vimrc or at the very least comment out portions of your vimrc until you find the culprit. – Peter Rincker Jul 11 '16 at 16:54
9

What you're referring to as a "namespace" is an operator. When you press d, you are put in Operator-pending mode. That is, the operator is waiting for a key (typically a motion to define a range) before executing their respective commands, such as :delete.

You can change your maps to operator maps:

onoremap <expr> O v:operator == 'd' ? ':.diffget<cr>' : '<esc>'
onoremap <expr> P v:operator == 'd' ? ':.diffput<cr>' : '<esc>'

Operator maps aren't usable until you're in Operator-pending mode. That means that the maps above could be used with all operators. But you only want it to work with d, so check to see if the pending operator is d before allowing O and P to be used for the diff commands. Using another operator such as cO would return <esc> cancelling the operator.

Operator maps can be more complicated than this. Read :h omap-info, :h 'operatorfunc', :h v:operator and :h g@ to learn more about them.

  • Oh, clever! I thought of answering and suggesting onoremap, but I didn't know how to make it only apply to d, and not all the other operators. Thanks, I learned something very useful today! – DJMcMayhem Jul 8 '16 at 20:39
  • @DJMcMayhem If you want to see elaborate operator maps, check out fakeclip.vim and vim-surround. Search for g@ in the source. – Tommy A Jul 8 '16 at 20:52
  • Sweet! Yes, I was tentatively looking at onoremap as well, but have never used it before and wasn't sure how to go about it. Thanks! – Tumbler41 Jul 8 '16 at 21:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.