1

I used to store macros in insert mode as <c-r><c-r>q, but that fails if the macro contains a special character such as <C-Right>

If I record a macro as

qq<C-Right>q.

the result of <c-r><c-r>q in insert mode is :

<80>ýV

the result of "qp in normal mode is :

<80><fd>V

If I copy the result back to a new register "ay$ , only the "qp approach works. The first character in the newly copied register of the <c-r><c-r>q approach is <c2>, I have no idea what <c2> is, it's echo result is 0.

So my question is what's the difference between these two methods?

0

2 Answers 2

4

what's the difference between these two methods?

p inserts the content of a register as it is, regardless of the encoding, but CTRL-R CTRL-R encodes sequences of bytes before inserting them.

Explanation

Special key combinations, such as Ctrl+, are translated into terminal keycodes like ^[[1;5C, then into vim keycodes like <C-Right>, and finally into a sequence of bytes starting with 0x80 like <80><fd>V (<80> is 0x80) [1] [2] [3] [4] [5]. This is a special case where the vim keycode is different than the terminal keycode [6].

After assigning the register q like this:

let @q="\<C-Right>"

the sequence of bytes is what's actually saved:

:registers q
Type Name Content
  c  "q   <80><fd>V
Press ENTER or type command to continue

If I went to insert mode and put this sequence by hand as Unicode code points [7] [8] [9] (V is 0x56 here)

  • Ctrl+V u0080 for <80>
  • Ctrl+V u00fd for <fd>
  • Ctrl+V u0056 for V

This is what I would get:

<80>ýV

which is the same result as the one I would get if I pressed

Ctrl+r Ctrl+r q in insert mode.

I have no idea what <c2> is

If the cursor is moved on the opening angle bracket < in the previous output:

<80>ýV

and then press g8 in normal mode, this is the output I'd get [10][11]:

c2 80

These are the hexadecimal numbers for the two-byte UTF-8 character under the cursor; so the <c2> is the first byte of the two.

As a final note, what follows is the output of "qp in normal mode:

<80><fd>V

If I again move the cursor on the first < and press g8 the output would be different:

80

because that's not a UTF-8 character but just a binary one.

Thanks to all the Vi and Vim community (including you) who made this answer possible. I hope this answer is useful.

2
  • 1
    Very well explained! Great answer.
    – dedowsdi
    Dec 21, 2019 at 23:33
  • Thank you @dedowsdi Dec 21, 2019 at 23:43
2

There are several ways to insert the content of a registers. I'm going to briefly discuss some that are inserted when in :h Insert-mode:

  • :h i_CTRL-R : Insert the content of a register. Unlike, :h p or :h P i.e. "qp, how the texts are inserted will be affected by options like :h textwidth, :h formatoptions or :h autoindent.
  • :h i_CTRL-R_CTRL-R : Works like using a single CTRL-R, but the text is inserted literally, not as if typed. So, if you record hitting a backspace, e.g. type^Hing, would insert typing when inserted with single CTRL-R but will insert type^Hing when inserted with double CTRL-R. (^H is CTRL-H, used for <BS> in terminal emulators, i.e. they emit same code <U+0008). Still is affected by auto-indent options.
  • :h i_CTRL-R_CTRL-O : Insert text literally and isn't affected by auto-indent.
  • :h i_CTRL-R_CTRL-P : Insert the contents of a register literally and fix the indent.

Now, when you pressed <Ctrl-Right> after starting the recording, your terminal emulator emits some keycodes. I don't exactly know what they might be and most probably they even differ from computer to computer. So, it's a wildcard why the characters <80> <fd> (both hexadecimal values) and most confusingly why V is there! I have no answer to these. The only thing I have advanced on your observations is that both ý and <fd> are basically same character, i.e. they both have same HEX values which is 00FD. Double CTRL-R, i.e. i_CTRL-R_CTRL-R, inserts literal characters. That's why it inserted the literal value of <fd> and not the HEX value which is saved in its :h digraph.

So, to wrap it up:

  • Check out the documentations to know about various ways to insert content of a register and differences among them.
  • <fd> and ý are same character, former is HEX value and latter is ASCII value.
  • No idea why there is a literal V in the <C-Right> :h key-codes recording
  • No idea how to make sense of these nonsensical key-codes. And I suppose, in order to not have to think about these key-codes, vim provides us sensible :h key-codes for mappings and such.

Edit

You can't use the literal string that you got when you inserted it with :h i_CTRL-R_CTRL-R to use as a recording. Because the literal string that the extended ASCII key-code spews out is not within one of :h key-codes. For example, if you want to insert <C-Right> into a register and use it, you need to do it in the following way:

:let @q = "\<C-Right>"

The backslash and double-quote is necessary to evaluate to special characters, see :h string and :h literal-string.

In other words, the weird character that the HEX value of <fd> evaluates to in extended ASCII chart is not going to be converted to special characters or key-codes in :h key-codes.

7
  • I know <c-r><c-r> insert literal content, i should've mensioned it. The question is why can't you copy literal macro text back to reqister, and use it as a macro, while the normal "qp approach works, help p only says "put the text ..... ".
    – dedowsdi
    Apr 7, 2019 at 10:54
  • I edited my answer. Check if it helps
    – 3N4N
    Apr 7, 2019 at 11:20
  • I'm not sure, i just tried let @q = "<c-v><C-Right>" , then @q, vim works, neovim failed. I also tried let @q = "\<C-Right>", both vim and neovim works.
    – dedowsdi
    Apr 7, 2019 at 11:49
  • <c-v><C-Right> is "<C-Right>" in neovim, "^[[1;5C" in vim.
    – dedowsdi
    Apr 7, 2019 at 11:54
  • 1
    Yes, you can because it is keycode, not a special key-code. The confusions are arising due to my misuse of terms. The special characters provided in :h key-codes can be used as literal or non-literal strings, e.g. '<C-Right>' or "\<C-Right>". Now, when you're using <80><fd> directly, it is being used as you expect. But if you copy <80>ý, it's not gonna work because ý would not work as <fd>, it will be another usual ASCII character. So, basically, you can use direct codes like <fd> but not their ASCII values like ý in a macro. And you can use special keys like <C-Right>
    – 3N4N
    Apr 7, 2019 at 12:25

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .