3

How to map d to call a function without getting into waiting mode? If I just do

nnoremap <buffer> d :call Function()<CR>

After I press d, it will wait for a while before it execute the function.

1
  • 5
    You can control the timeout with the timeout and timeoutlen settings, but it's impossible to not have Vim wait since Vim won't know if you intend to use a motion after d; the only way to know is to wait for a while (or telepathy, but I don't think that's implemented yet). My recommendation would be to not map d but to use a different key instead, or map it to something like dq or <Leader>d. It might help if you could describe what Function() does; if it's delete-related there might be a better way to solve your problem. Apr 11, 2020 at 12:40

1 Answer 1

9

Vim will wait for more keystrokes when there is a longer mapping that starts with the same prefix. Vim is trying to resolve which of the mappings to trigger, so it will take enough characters to decide whether the user was typing the sequence for the longer one.

In my particular case, when I tried to reproduce your issue, I had a mapping for ds from the vim-surround plug-in.

You can list all the normal mode mappings with d as a prefix with the :map d command:

:map d
n  d           *@:call Function()<CR>
n  ds            <Plug>Dsurround

So when you type only d, Vim will wait for the next character to figure out if it's an s (for ds), or if it's a different character, in which case it will execute the d mapping and then execute the extra character as a separate normal mode command, once the d mapping has finished.

One way to trigger the shorter mapping is to wait for a timeout (assuming 'timeout' is enabled and 'timeoutlen' configured, the default is enabled at 1s.) But this is of course not ideal, since you still need to wait for the timeout for the mapping to trigger...

Another solution worth mentioning, since you asked about a local mapping on a buffer, is to use the <nowait> modifier. The way <nowait> works is when you have a <buffer> mapping (such as your d) for which global mappings exist which start with the same prefix (such as ds from vim-surround.) In that case, using <nowait> will make the local mapping trigger right away, without waiting for more keystrokes to potentially match the longer mapping. This, in effect, disables global longer mappings if any existed. If that's the problem you're also having, this is a potential solution:

nnoremap <buffer> <nowait> d :call Function()<CR>

Mapping a command such as d is an odd choice... You're clobbering the "delete" command, which is pretty central to Vim and text editing. Picking an alternative mapping (such as <Leader>d) might be advisable.

Unless you're working on using Vim to drive a completely separate user interface (for example, netrw which implements a file browser) and you're planning to reimplement most or all commands. In that case, using <nowait> to essentially disable longer global mappings is probably a good idea.

1
  • 1
    Yes it's a complete new window. Nowait works!
    – Rui Liu
    Apr 13, 2020 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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