I'm trying to toggle some ctrl maps in command directly, it didn't work as expected:

com Test0 nnoremap <c-j> :echo "c-j"<cr>
com Test1 nnoremap <c-h> :echo "c-h"<cr>
com Test2 exe 'nnoremap <c-l> :echo "c-l"<cr>'
com Test3 exe 'nnoremap <c-right> :echo "c-right"<cr>'

" uncomment this, I see results of :map and "E15: invalid expression: ^M"
" Test0

Only Test1 and Test2 works. Test0 works like :map, have no idea why that happens. If I execute the exe ... or nnoremap ... sub command in command line, everything works. what am I missing?

  • My general advice (also in 'autocmd's) is to avoid all substitution and quoting pitfalls by having your command just call a function and have the function execute all the commands, which means the commands will all run in a sane context where you know what to expect. Also, bonus: you get to add more commands to the function easily rather than having to deal with | and <bar> etc. (essentially one more variation of the same problem.) – filbranden Mar 25 at 14:26
  • @filbranden One size does not fit all. There are times the sub command took only one or two statements. I believe one should not write function in that case, especially when that function is only called by this command alone. – dedowsdi Mar 25 at 23:16

Hmm. This is interesting. Here's what get saved as the command (:com Test0):

nnoremap <NL> :echom "c-j"<CR>

(<C-J> is equivalent to <NL> in Vim)

So what do we know about the <> format? That it can be used in mappings and abbreviations as a substitute for the represented keys/chars. That it can be used in exe command arguments the same way but only if escaped (e.g. \<Tab>).

If that command is entered directly it works. It would make sense that it should do the same when run by the operation generated by com. But it doesn't. Instead the <NL> is acting like Enter key and when Test0 is run it submits the nnoremap alone, immediately. And, actually, we can't assume that something executed indirectly follows the exact same documented behavior as for the directly entered equivalent and obviously it's not here.

Without diving into the code (which I might just do) I can only surmise. There is something that makes <NL> different from other key(codes). Along with <CR> it is the only thing that can submit commands for execution (:h c_<NL>: "start entered command"). I'd assume that's a crucial detail here with respect to why other special keycodes (e.g. <c-h>) don't behave differently than expected. Note that if you skim through the results of, for example, :helpgrep <NL> you'll see there are various places where <CR> and <NL> have exceptional behavior and/or are treated differently than most other special characters. So I don't think what we're seeing here, while a head-scratcher, is totally unexpected or unprecedented.

Anyways, for now I at least can offer a working version. This successfully escapes the mapped key...

com! Test0 exe 'nnoremap \<c-j> :echom "c-j"<cr>'

Funny things is, this just adds to the mystery, really. Now we're sort of doing double indirection/interpretation and it works the way we'd expect! Interesting.

| improve this answer | |
  • Thanks. I thought keycodes only have special meaning in map family commands, I must be wrong. Could you point me where can I find keycode have special meaning in command in help? – dedowsdi Mar 25 at 3:32
  • There is also :h c_CTRL-H and :h c_CTRL-L, why would Test1 and Test2 work? <c-right> also have special meaning in command line mode. – dedowsdi Mar 25 at 3:39
  • Yeah...the order things are happening is a little different than what I said I believe...updating my answer – B Layer Mar 25 at 4:25
  • Alas, I retracted my definitive analysis for something less satisfying. :) – B Layer Mar 25 at 4:52
  • 1
    Thanks for the digging. It's the first time I see the valid use of \<c-..> in single qutoe, it's so hard to swallow. Another work around is com! Test0 nnoremap <lt>c-j> :echom "c-j"<cr>. – dedowsdi Mar 25 at 5:42

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.