1

I recently wanted to have a mapping that I could trigger from normal mode as well as from insert mode. Writing the same mapping for multiple modes annoyed me as it cluttered my .vimrc and requires me to make the same changes multiple times.


It was pointed out to me, that no such mapping mode exists. See here: https://superuser.com/questions/1236999/vim-multiple-specific-mappings

It was also pointed out, that for very simple mappings I could use a function like this:

function! DoubleMap(x, y)
  exec "nmap ".x." ".y
  exec "imap ".x." ".y
endfunction

I now tried the following:

I created a mapping that takes care of what ever I want to achieve, without using nore:

map <COMPLEX-KEY> <ACTION>

Then I created mappings for the modes I wanted the mapping to work in:

inoremap <KEY> <Esc><COMPLEX-KEY><Esc>i
nnoremap <KEY> <COMPLEX-KEY>

This should allow me to outsource complex mappings to another part of the .vimrc or another file altogether, as well as for easier changes and readability.

But this does not work. Is there a way to trigger a mapping from within a mapping?

3 Answers 3

3

By using the nore forms, you are specifically telling Vim to ignore any existing mappings. (See :help :nore, or, for a bit more explanation, this chapter from Learn Vimscript the Hard Way.)

To use your existing <COMPLEX-KEY> mapping inside another mapping, use imap and nmap for the <KEY> mappings, not the <COMPLEX-KEY> mapping:

noremap <COMPLEX-KEY> <ACTION>

imap <KEY> <Esc><COMPLEX-KEY><Esc>i
nmap <KEY> <COMPLEX-KEY>

Sidenote: You can use <c-o> to run a single normal mode command from insert mode:

imap <KEY> <C-O><COMPLEX-KEY>
1
  • I don't know if I will ever get this in my head. I always confuse nore to mean "don't allow for other mappings to call this" instead of "don't allow this mapping to use other mappings". Thank you very much for the clarification.
    – omnesia
    Commented Aug 7, 2017 at 10:42
1

On a side-note I've implemented a similar feature a long-time ago, now in lh-vim-lib -- it's quite old and convoluted. I've been using it to generate mappings and menus for various modes (insert, normal, visual, command) that trigger the same action from a same keybinding.

For instance,

  • Here in one call, I'm able to define mappings and menus for Insert, Normal and Command modes (nic) that execute :TexMakePDF on <c-l>pdf

    :MenuMake nic 50.330 &LaTeX.Make\ P&DF\ (via\ dvips)    <C-L>pdf
       \ <buffer> :wa<CR>:TeXMakePDF<CR>
    
  • Or here I can insert <em>|</em> in insert mode, or surround the current selection (or word -- normal mode) with the same keybinding (or from the same menu entry)

    :MapMenu 50.370.300 &HTML.&Fonts.&Emphasize <localleader>em em
    

The ideas (implemented in s:Build_CMD) are:

  • to use <c-o> in INSERT mode to revert to normal mode momentarily,
  • to escape command mode (with <c-c>) to return in normal mode
  • from visual mode we need to keep the range
0

To answer the question I first tried to solve with above clarification (and answer to the question that I ended up asking):

I use noremap <complex-key> <action> and

imap <key> <C-O><complex-key>
nmap <key> <complex-key>

to achieve what I was looking for

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.