I am making some remaps for inserting/removing comments and "dividers" for different languages. In my ftplugins files the variable g:CommentChar is defined. For some reason I am getting the following error:

E114: Missing quote: "\ E15: Invalid expression: ":normal! mA^i".g:CommentChar."\

when trying to use the <Leader>c macro. How is this possible? I thought <Esc> was valid in execute command if it was escaped.

nnoremap <Leader>_ :execute 'normal! mAo'.g:CommentChar.'\<esc>100a-\<esc>`A'
nnoremap <Leader>c :execute 'normal! mA^i'.g:CommentChar.'\<esc>`A'
nnoremap <Leader>C :execute 'normal! mA^mBi'.g:CommentChar.'\<esc>f'.g:CommentChar.'dl`Bdl`A'
vnoremap <Leader>c :execute ':s/^/'.g:CommentChar.'/<CR>:noh<CR>'
vnoremap <Leader>C :execute ':s/'.g:CommentChar.'//<CR>:noh<CR>'
  • You can insert ^M by pressing Ctrl and v and then M. Use ^M as an alternative for <CR> This might help you if none of the ways worked out. – SibiCoder Jul 16 '16 at 5:57
  • Replace double quotes " by single quotes '. – Sato Katsura Jul 16 '16 at 5:58
  • @SatoKatsura Tried it. That's not the problem. – Luke Davis Jul 16 '16 at 6:03
  • 1
    It's part of the problem. There is no such thing as single backslash inside double quotes. shrug. – Sato Katsura Jul 16 '16 at 6:04

Use <expr> instead of :execute 'normal! ...':

nnoremap <expr> <Leader>_ 'mao'.g:CommentChar.'<Esc>100a-<Esc>`a<CR>'
nnoremap <expr> <Leader>c 'mA^i'.g:CommentChar.'<Esc>`A<CR>'
nnoremap <expr> <Leader>C 'mA^mBi'.g:CommentChar.'<Esc>f'.g:CommentChar.'dl`Bdl`A<CR>'
vnoremap <expr> <Leader>c ':s/^/'.g:CommentChar.'/<CR>:noh<CR>'
vnoremap <expr> <Leader>C ':s/'.g:CommentChar.'//<CR>:noh<CR>'
  • Thanks! So <expr> just means evaluate the RHS as string, then that's your macro. Could you tell me why my first try didn't work? I was following the direction of this "learn Vimscript the hard way" article. – Luke Davis Jul 16 '16 at 17:14
  • @LukeDavis Pretty much, yes. See :h :map-<expr>. – Sato Katsura Jul 16 '16 at 17:15
  • Any idea for the question ^^ in my edit? – Luke Davis Jul 16 '16 at 17:17
  • @LukeDavis I'm not familiar with that part of the code. I presume it has to do with <Esc> breaking out of :exec. Ask on vim_dev for qualified opinions. – Sato Katsura Jul 16 '16 at 17:23

The problem with

nnoremap <Leader>c :execute 'normal! mA^i'.g:CommentChar.'\<esc>`A'

is that <esc> is valid in nnoremap, never mind execute and causes the command line up to that point to be executed. (Plus you're missing a <CR> at the end of the mapping.)

One way around this is:

nnoremap <Leader>c :execute 'normal! mA^i'.g:CommentChar.'^V^V^V^[`A'<CR>

where ^V is a literal Ctrl-V character and ^[ is a literal escape character.

The ^V^V^V^[ is translated to ^V^[ upon playback, which inserts an escape character.

If you really want to use execute, do it like this.

:exe 'nnoremap <Leader>c mA^i' . g:CommentChar . '<Esc>`A'

At this point you may as well use <expr> as shown in @SatoKatsura's answer. The difference with map <expr> is that the expression is evaluated at runtime, and a few operations are disallowed (see :h map-<expr>).

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.