2

It seems that mappings with @="^E" or @="<c-e>" result in @="" and do nothing.

For example if I use nnoremap ^N @="^E"^M then press ctrl-n I will get a @="" message and nothing happens. However, when I use nnoremap ^N @="^Y"^M then press ctrl-n I receive a @="^Y" message and the screen scrolls down.

I should also mention that if I enter @="^E"^M manually, -- and not as a mapping -- it works just fine.

To clarify I want to know how to pass <c-e> into the expression register because I want to be able to use it in repeatable mappings. Such as nnoremap <c-p> @="<c-e>j" to scroll the window and move cursor down n lines.

  • What do you expect to happen exactly? – romainl Apr 20 '16 at 4:20
  • I expect it to scroll one line up, and show a @="^E" message. I'm perplexed as to why it wont work for <c-e> but will for seemingly any other <c-...> character. – Eric Apr 20 '16 at 5:56
  • 1
    nnoremap <C-n> <C-e> – romainl Apr 20 '16 at 7:07
  • I ran into this problem because I wanted to have a mapping like nnoremap <c-n> @="<c-e>j"; that scrolls the window and moves my cursor down at the same time. The @= makes it so the operation is repeatable. ie I can press 10 ctrl-n to scroll the window, and move cursor 10 lines down. nnoremap <c-n> <c-e>j scrolls the window down 10 but the cursor only goes down 1. The mapping nnoremap <c-p> @="<c-y>k" which does the exact opposite, works perfectly fine. – Eric Apr 20 '16 at 18:32
5

From :help c_ctrl-e:

CTRL-E or <End>                 *c_CTRL-E* *c_<End>* *c_End*
                cursor to end of command-line

In command-line mode, a literal <C-e> moves the cursor to the end of the line, and when you are inside the expression register =, you are on the command-line.

So, when you hit <C-N> in normal mode, Vim does the following:

  • it types @="
  • it moves the cursor to the end of the command-line (it's already at the end anyway) because of ^E ; it doesn't insert the character ^E because it has just been translated as a motion
  • it types "^M

In the end, it's as if you had typed: @="", which is an empty string.
So, Vim doesn't execute anything.
It would work if there was something in the string, for example if you type @="dd" in normal mode, it will delete the current line. But here, there's nothing left in the string, because ^E has been translated as a motion.

For this reason, I don't think you can use ^E in your mapping.


Your mapping works for ^Y because of this (:help c_ctrl-y):

CTRL-Y      When there is a modeless selection, copy the selection into
            the clipboard. |modeless-selection|
            If there is no selection CTRL-Y is inserted as a character.

Like ^E, ^Y is associated with an action on the command-line. But not if there is no selection.
In this case, contrary to ^E, it simply inserts a literal control character.


Depending on the context, there are various ways of writing a control character like ^E:

  • ^E (Ctrl-VCtrl-E) to insert it on the command-line or in a buffer
  • <C-E> in a mapping
  • "\<C-E>" in a string
  • "\<lt>C-E>" in a string read by a mapping command such as :nnoremap

So, if for some reason you really wanted to use the expression register (maybe because you wanted to create a mapping accepting a count), you could use "\<lt>C-E>", like this:

nnoremap ^N @="\<lt>C-E>"^M

In this mapping, 2 translations occur at different times.

First, when your :nnoremap command is executed and add an entry in the mappings table, the keycode <lt> is translated as the character <, and the resulting string is "\<C-E>".
Then, when you will hit <C-N> in normal mode, the string "\<C-E>" will be translated as the control character ^E.

The keycode <lt> is necessary to protect <C-E> from being automatically translated as a literal control character when :nnoremap is executed.
If you don't protect <C-E> with <lt>, the same problem as before will repeat, ^E will be translated as a motion on the command-line instead of a character to insert.

  • Thank you so much! This is exactly the information I needed. – Eric Apr 20 '16 at 18:40
3

I think you're not using the good way to do what you want:

The expression register ("=) is a way to evaluate an expression but what you are trying to use (Ctrl-E) is simply a normal mode command.

So a in a normal mode mapping you can simply use it directly with :nnoremap <C-n> <C-e> (or :nnoremap <C-n> <C-y> or whatever). You don't need to consider that as an expression to be executed.

Generally speaking I don't think it is a good idea to use the expression register since it adds complexity to your mapping whereas you often have an other solution to do what you're trying to do.

  • 1
    I'm sorry, I oversimplified my original question to point out the problem. I need the expression register because I'm trying to create a repeatable command that uses ctrl-e j ie @="<c-e>j" to move the screen and cursor down n lines. You need an expression register for that to be executed properly. I was also curious as to why <c-e> wouldn't work in the mapping. – Eric Apr 20 '16 at 18:53

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.