I refer to those 4 terms using terminology picked up by various sources:
- Steve Losh, in his Learn Vimscript the Hard Way's chapter 16 refers to things like
<cr>
(these 4 characters typed in a Vim script) as "special characters"; - as regards things like
\<esc>
(these 6 characters typed in a Vim script), he calls them string escape sequences in chapter 30; in the title of my question I'm using the term escaped special characters because\<esc>
looks a lot like (is?) an escaped<esc>
, and because... - Steve Losh also refers to
\r
(the 2 characters typed in a Vim script) as an escape sequence (also this in chapter 6); - Vim documentation, in
:help i_CTRL-V
, refers to stuff like^[
, 1 indivisible entity (visually represented as 2 characters) that can be obtained via Ctrl-VEscape, as a terminal code.
I'd like to consolidate my understanding of when each of those 4 ways of inserting special characters should be used, because I think I'm a bit confused on the matter.
Below is what I've understood so far.
Chapter 6 has this (valid) line:
:onoremap ih :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>
My understanding of :*map
commands is that their {rhs}
argument is truly the sequence of keystrokes that are "automatically hit" by Vim (right after the {lhs}
has been typed) from whatever mode(s) the specific :*map
is defined on.
Therefore, if I want the mapping to do the same action as when I press, say, Ctrl-U (resp. Enter), I have to type <c-u>
(resp. <cr>
) in the {rhs}
.
I can further note that if I had made a typo, e.g. typing <ccr>
instead of <cr>
in the above operator mode mapping, then pressing cih in normal mode would result in Vim populating the command line with
:execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<ccr>
without pressing enter, which means that Vim has not tried to interpret <ccr>
as a special character (otherwise it would have failed in doing so), and simply inserted the 5 characters in sequence.
However, I can't help but notice that my claim that
{rhs}
argument is truly the sequence of keystrokes
is not totally correct, because if the typo I made was to write <|cr>
instead of <cr>
the effect would not be that the command line is populated with
:execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<|cr>
but an error. Only if the typo was <\|cr>
, would the line be populated that way
So it looks like the {rhs}
of a :*map
is not exactly the keystrokes that Vim does, because of two aspects
- some sequences (such as
<cr>
or<c-u>
) are special, in the sense that when Vim sees them, it interprets them as a single keystroke of the key they name (Enter or Ctrl-U respectively); - some characters, such as
|
or\
, which would normally have a special behavior, need to be escaped via\
.
One thing which I'm pretty sure about, is that writing special characters like <esc>
, <cr>
, or <c-u>
in Vim script has the same effect as if pressing those keys after Ctrl-V, i.e. pressing Ctrl-VEscape, Ctrl-VEnter, and Ctrl-VCtrl-U respectively, thus obtaining the single-sequences ^[
, ^M
, and ^U
.
Going back to the onoremap
command above, my understanding of :execute
is that it takes a string and executes it, so it's clear to me that I can't put <cr>
or Enter/^M
in it, because that would mean that Vim presses Enter right after the $
, i.e. it would try to enter the following ex command, which is obviously erroneous (because it lacks a closing "
, beside being incomplete):
:execute "normal! ?^==\\+$
Instead, I have to use sequences like \r
(for <cr>
/Enter) and \e
(for <esc>
/Escape). And since \
is the escape character, I need to escape it too, to get a literal \
, just like in \\+
. (This probably also tells me that |
has a special meaning in ex command line, because I needed to escape it, if I wanted it to appear literally in the command line. Probably the fact is that |
is to separate commands, as explained at :help :bar
.)
Then, in chapter 30, Steve Losh presents this:
:execute "normal! mqA;\<esc>`q"
where I can deduce that <esc>
is meant to mean that Escape is pressed during the execution of normal!
, but it needs to be escaped for :execute
to understand that it is a special character within the double quoted string. Therefore, I reason, I could write \e
instad of \<esc>
:
:execute "normal! mqA;\e`q"
and indeed that works too.
However, while this
:onoremap ih :<c-u>execute "normal! mqA;\e`q"
is valid, this
:onoremap ih :<c-u>execute "normal! mqA;\<esc>`q"
isn't.