# Why doesn't this macro work? (expression register)

According to this:

nnoremap Q @='n.'<CR>: The @ key tells Vim to execute a macro. Rather than using a named register we use the expression register, which lets us specify the contents in place. The characters inside of the quotes are interpreted as keystrokes, and the carriage return enters the string into the expression register.

But I tried this:

nnoremap K @='k<C-Y>'<CR> and it doesn't work. Edit: nevermind, this one works, but this one doesn't: noremap J @="j<C-E>"<CR>

Edit: I was also trying to make noremap J @="j<C-E>"<CR> work. But one of the comments below links to a question and explains why this one doesn't work: this

• it works for me (although I'm not sure why you'd use this instead of nnoremap K k<c-y> – Mass May 11 '20 at 2:57
• '<C-Y>' is not ctrl-y. – Matt May 11 '20 at 3:07
• @Matt doesn't matter, since nnoremap replaces <c-y> for you. It works fine on my vim. – Mass May 11 '20 at 3:09
• I meant nnoremap K @="k\<lt>C-Y>"<CR> but, as it turns out, that one should also work. @Zaid You probably have some other mapping for <C-Y> or such. – Matt May 11 '20 at 3:35
• However, nnoremap K @='k<C-Y>'<CR> still doesn't work. It works for me. Try to reproduce without config vim -Nu NONE +"nnoremap K @='k<C-Y>'<CR>". – user938271 May 14 '20 at 3:16

There are two types of quotes in Vim, '...', and "...". These are treated differently.

The first '...' is a literal string. It is taken as-is. No characters have a special meaning, including <,>,\.

The second "..." is a quoted string. It accepts special characters, which are prepended with a backslash (\).

In your case, <C-Y> is denotes the special character CTRL-Y. Thus, to include this character in your expression, you should use the double quotes with a backslash ("\<C-Y>").

Putting it together, the mapping would be changed to

nnoremap K @="k\<C-Y>"<CR>


For more, see

• :h expr-'

• :h expr-"

Edit: For a similar mapping to J, nnoremap J @="j\<C-E>"<CR> would not work, as <C-E> gets 'used up' in the (expression register) command line. This is further explained here, and in the comments. A better way would be to escape it with \<lt>, as proposed in the comments.

Thus,

nnoremap K @="k\<lt>C-Y>"<CR>
nnoremap J @="j\<lt>C-E>"<CR>

• For some reason, nnoremap J @="j\<C-E>"<CR> doesn't work. nnoremap K @="k\<C-Y>"<CR> does. :S This is the error I get: ="j\" E114: Missing quote: "j\" Press ENTER or type command to continue – Zaid Gharaybeh May 14 '20 at 2:52
• I think the latest comment added by user938271 to the question explains it: vi.stackexchange.com/a/7437/17449 – Zaid Gharaybeh May 14 '20 at 3:06
• Good find. TIL. – husB May 14 '20 at 3:15
• The :map commands are special in that they expand the <...> key sequences. So to get what you're proposing here, you actually need nnoremap K @="k\<lt>C-Y>"<CR>, more specifically use a <lt> to prevent :map from expanding the <C-Y> prematurely. But having said that, since :map expands the <C-Y>, it actually should work with the single quotes, having the :map expand the special characters... – filbranden May 14 '20 at 3:44
• Agreed, thank you :) Allow me to edit my answer – husB May 14 '20 at 3:46