1

Cross-posting from Stackoverflow because I keep forgetting about this site...

Have a macro where a visually selected text will be made a markdown link and once the macro executes it leaves Vim in INSERT mode:

|  - VISUAL selection
i  - cursor position in INSERT mode
@l - invoke macro in "l" register

Some |text| saying stuff.   = @l => Some [text]() saying stuff.
                                                i

Register l holds the following:

:registers l
Type Name Content
  c  "l   S]%a()^Ohq<80>kb

Created it the following way:

  1. Visually select some text
  2. q then l
  3. S then ] (S is a visual selection command in vim-surround)
    ^ - normal mode cursor position
    
    |text|  =S]=>  [text]
                   ^
    
  4. % (jump to closing bracket)
  5. a and then type ()
  6. CTRL-O
  7. h
  8. CTRL-O then q (to finish the macro but to remain in INSERT mode)

So I selected this definition with the mouse (i.e., * register), and did let @l = "S]%a()^Ohq<80>kb" in the other Vim instance, resulting in

Some |text| saying stuff.   = @l => Some [text]()^Ohq<80>kb saying stuff.
                                                           i

It works if Vim is built with clipboard support (:let @+ = @l in one Vim instance, and :let @l = @+ in another), but I would like to learn the fundamentals of deciphering these representations.

UPDATE: There is a slight difference between the Vim representations of the recorded & clipboard-copied macros and the ones that are pasted manually: the sequences ^O and <80> are highlighted as special in the former case, but the string is shown with uniform color in the latter.

The l is the original recorded macro, + is created by :let @+ = @l, and c content has been typed in verbatim:

enter image description here


Found a couple other Stackoverflow threads with a similar premise, but they weren't helpful:

VIM macro editing

Tried to convert the ^O to <C-O> but it didn't work, and have no clue what <80>kb is.

Based on the creation steps above, I would have expected something like S]%a()^Oh^Oq instead of S]%a()^Ohq<80>kb anyway.

Reliable solution to copy/paste Vim macros

No replies, and based on what I understood, it is not applicable in my case.

Saving vim macros

Chewed my way through the answers and comments, but no joy.

2 Answers 2

3

The first Control-o has to be done with <C-v><C-o>; no idea about where the other bytes came from, but you can input the <80> with <C-v>x80.

On the other hand, macros in vim tend to be better-suited to interactive tasks. Once you want to start saving them, you'll need to either

  • let them be saved via viminfo files (this is done automatically if you use the default 'viminfo' setting, but you may need to set viminfofile?).
  • create a mapping/function/etc., which is a little more robust for automation tasks, especially persistent tasks (I treat macros a little more ephemerally, since they can be clobbered by using the register for other things.)

So personally I would add the following to ~/.vim/after/ftplugin/markdown.vim (since it looks you're creating markdown links):

xmap <buffer> <localleader>l S]%a()<C-o>h
  • xmap for visual-mode excluding select-mode (map instead of noremap for recursive mappings—S is a plugin-provided mapping that we want to re-use here)
  • <buffer> to keep it local
  • <localleader>l how to invoke it (probably \l with a default configuration)
  • S]%a()<C-o>h your mapping, without all the macro stuff in the way (and, benefit: it's easier to edit and read)
0
3

The explanation

D. Ben Knoble has given you a good alternative solution, and explained one way of setting the exact register contents with a :let command, but as you said you wanted to learn the fundamentals, I thought I'd add a little extra explanation.

As you noted, in the recorded macro, the ^O and <80> are highlighted. This is because they are not simple sequences of multiple characters, but instead Vim's representation of "special characters". The ^O is the ASCII SI (shift in) character, which can also be represented or typed as CTRL-O or the hex code 0x0f.

<80> is hex 0x80, but Vim in this instance Vim is using this as the first byte of <80>kb, which is its internal representation of a backspace.

You can add these to strings either by inserting them directly either by using Ctrl-V (as suggested by Ben), or by using Vim's backslash escapes:

:echo "\<C-O>"
:echo "\x0f"
:echo "\<BS>"
:echo "\x80kb"

Like Ben, I'm very unclear why there are a q and a backspace in your recorded macro (I can't reproduce this when recording my own macro: could be something to do with your configuration). Regardless, it's obviously not necessary for your macro to insert a q and then immediately delete it, so one way of achieving your goal would be with the following :let command:

The solution

:let @l = "S]%a()\<C-O>h"
2
  • 1
    Why there's a "q" => User wanted to end macro recording in Insert mode, so they typed "q" but that inserted a literal "q", then they used backspace to fix it (remove the "q") and finally used Ctrl-O + q to end the macro recording. That's my hypothesis. Yes, cleaning the macro not to include those two would be a great way to make the problem go away.
    – filbranden
    May 27, 2021 at 15:00
  • 1
    @filbranden :oooooh-emoji:
    – Rich
    May 27, 2021 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.