4

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.

4
  • What do you expect to happen exactly?
    – romainl
    Commented Apr 20, 2016 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
    Commented Apr 20, 2016 at 5:56
  • 1
    nnoremap <C-n> <C-e>
    – romainl
    Commented Apr 20, 2016 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
    Commented Apr 20, 2016 at 18:32

2 Answers 2

7

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, <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, here's what Vim does:

  • type @="
  • move 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 the latter was interpreted as a motion
  • type "^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 was interpreted as a motion.

For this reason, you can't 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 to write 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 hit <C-N> in normal mode, the string "\<C-E>" is translated into the control character ^E.

The keycode <lt> is necessary to protect <C-E> from being automatically translated into 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 intepreted as a motion on the command-line instead of a character to insert.

1
  • Thank you so much! This is exactly the information I needed.
    – Eric
    Commented Apr 20, 2016 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
  • 2
    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
    Commented Apr 20, 2016 at 18:53

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.