VIM macro editing - vim

Suppose that I have recorded a long macro with many commands and special characters. Odds are I have made an error somewhere :) How can I edit a macro, correct errors and save it again?
For example:
I wish to copy a line and then increase the digit in it by one.
Macro for this is
yyp/\d<C-A>
but it is saved as
yyp/\d^M^A
and I can't see this special characters when I paste the register. I also have to play with 'let' when I wish to copy a register, because standard paste to screen and copy to another register doesn't work. How can I efficiently edit register with special characters?
Thanks

What do you mean when you say you "can't see the special characters"? What special characters? You should be able to see the ^A and ^M fine, which represent <C-A> and the <carriage return> respectively. That's all you need.
So do just paste the register into a buffer. Then edit and yank back into a register and execute as a normal macro. If you want to edit the <C-A> to be something else, say, <C-E>, then just delete the ^A that shows up on paste and put a <C-E> in by pressing <C-V><C-E> (or <C-Q><C-E> if you're on Windows with windows compatibility on). It will show up as ^E, but that's how it's supposed to be.

Press <C-r><C-r>q (here q is the register name) in insert mode. Execute :h ctrl-r_ctrl-r to see the details.

Related

How to use different registers in Vim to copy/paste from/to OS clipboard -- how exactly?

I've read this How to make vim paste from (and copy to) system's clipboard? and I know what the hotkeys are. But I'm unable to execute any of those commands. For example, what exactly should I press to call
"* or "+? In which mode also? I've tried different things and none of them worked.
I am assuming you've double-checked that :echo has('clipboard') returns 1. If it returns 0, you're out of luck since vim isn't compiled with access to the system clipboard.
If you have clipboard powers, then yanking and pasting inside of vim is done with pressing just the letter y and the letter p, in normal mode. Start doing this first, to confirm that you can yank and paste inside of vim. For instance, yank a line: yy and paste it p.
Next, confirm that you can yank inside of vim to the system clipboard with "*y. (That means pressing the double-quote (shift-'), then an asterix (shift-8), then the letter y, all in quick-ish succession. Toggle over to another app and paste with the regular control-V. (You may be able to look at the bottom left of status line to see what you are literally typing, which might help).
If that works, then the clipboard functionality is "good to go." If it doesn't you might need to tweak your .vimrc to get things working. Try setting the clipboard to unnamed: set clipboard=unnamed and retest step 3 again.

Pasting text in vim. A tedious operation?

I've been using vim for somewhat longer than a year now and during this time I have never feel really comfortable with the way vim works with yanking and pasting text (or maybe it is just me not using it in the most efficient way)
For example, I have the word "World" yanked onto a register, and I want to paste it after "Hello". (Note that there are no spaces on either of the words). So, what I would do is
Hello
|
Place cursor here, and press "p". Then, what I will end up with is
HelloWorld
So, in order to avoid this, I have always to swith into insert mode, insert a espace, and go back into normal mode (or either make sure that the yanked word has a space before it). Be as it may, this is quite annoying behaviour I can't think of a solution for... Am I missing something here?
Suggestions will be appreciated.
Thanks
option zero
just live with what you have now.
option one
create a mapping for your workflow. for example
nnoremap <leader>p i<space><esc>p
option two
:set ve=all
then you could move your cursor to anywhere and paste
option three
you could in insert mode use <c-o> do normal mode stuff or <c-r> to get register values
I recommend option zero
You can use the Smartput : Adjust spaces and commas when putting text plugin for that. It modifies the p / P commands (this can be toggled on / off).

Duplicating line in Vim and appending few letters

I am editing a dictionary in a text file, containing Russian words - one word per line.
Some nouns are missing their derivatives, which are usually the same word appended by few more letters - in 6-7 variations as shown in this screenshot:
In Vim I would like to put the cursor in the first column and scroll down line by line. And when I recognize a noun, I'd like to press some (as few as possible!) keystrokes to take that word, copy it in separate lines and append the letters.
I can get rid of the duplicates by issuing %sort u later.
If I could run that command on the whole file it would be something like:
%s/\(.\+\)$/\1^M\1а^M\1ам^M\1ами^M\1ах^M\1е^M\1ном^M/
Do you please have an idea, how to create such a "macro" in Vim?
There are a couple of ways that you can handle this. You can create a macro or you can create a map. Either can be done while running VIM. Either can be placed in another file (your .vimrc, for example, or a file with bindings specific to this project) and sourced when needed.
I will also give you a bit more advice with regular expressions: if you are writing something particularly complex, you can greatly decrease the number of \s needed by starting the regular expression with \v (i.e., :s/\v([0-9a-f]+\s)/0x\1/g).
Creating a Macro in VIM
You can start a macro in VIM by pressing q in Normal mode, followed by the key that you wish to use for the macro. You can then invoke the macro by pressing # followed by the macro's letter. Press q again in Normal mode to stop recording.
You can therefore enter this macro as follows (using the q register):
qq:s/\(.\+\)$/\1\r\1а\r\1ам\r\1ами\r\1ах\r\1е\r\1ном\r/Enterq
Then, when you are on a line and you want to run this command, enter #q from Normal mode.
Storing a macro in a file and sourcing it
When you created a macro in the last step, what you were actually doing was setting the q register. You can check this by entering the registers in command mode. You can instead set this macro in your .vimrc file as follows and it will be available every time you start VIM.
Create the file you want to store this macro in (:new).
Add the following line to the file:
let #q=":s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"
(If you yank the line and paste it in VIM with Ctrl+R", there will be a proper ^M character at the end of the line. You'll need to do some manual editing to make sure that it's inside the quotes. Alternatively, you can enter Ctrl+VCtrl+M to enter the ^M character.)
Save the file (:w testmacro.vim).
Source it (:so % or :source %).
Test your macro by typing #q on one of the lines you'd like to do this to.
Later, you will be able to load this macro by running :so testmacro.vim.
Create a Mapping
You can instead create a mapping. The following mapping copies the last word in a given line, pastes it onto the following six lines, and then appends to each of the given lines.
nnoremap <c-j> yy6pAа<esc>jAам<esc>jAами<esc>jAах<esc>jAе<esc>jAном<esc>j
n at the beginning of "nnoremap" indicates that it only functions in Normal mode.
noremap means that this command won't engage in any recursive remapping (whereas with nmap, this could happen).
<c-j> maps to Ctrl+J
yy6p yanks the line and pastes it 6 times.
Aa<esc>j appends to the end of the current line, enters the text (in this case a), exits Insert mode, and moves down a line.
You can enter this command in VIM's command mode or you can store it in a file and load it with the :source command.
Combining Registers with Mappings
You can access a register in your mappings. This means that if you know that entering a given replacement regex will do what you want, you can save that in a register and then enter your command on the current line.
To do this, enter the following commands in a file and then source it:
nnoremap <c-i> :<c-r>f<cr>
let #f="s/\\(.\\+\\)$/\\1\\r\\1a\\r\\1b\\r\\1ам\\r\\1ами\\r\\1ах\\r\\1е\\r\\1ном\\r/^M"
Now you can enter Ctrl+I to run the replacement regex in register f on the current line.
Alternatively, dedicate a few registers to the purpose - let's say a-f.
nnoremap <c-l> yy6p$"apj"bpj"cpj"dpj"epj"fpj
let #a="a"
let #b="ам"
let #c="ами"
let #d="ax"
let #e="e"
let #f="ном
In this case, we're using the ability to press " and the name of a register before hitting a command that uses it, such as paste.
You can record macros by pressing q in the escape mode. For example,
position your cursor on the noun you want to edit.
press qa to start recording macro and store it in register a (other alphabet and digits may also be used for registers) .
do whatever general actions you want to do (copy line, paste, append letters, etc. as in you have tried to show in your search string).
once you are done with the changes, in escape mode press q again.
Your macro is now created in register a. Whenever, you want to repeat your key sequences, just press #a.
Note that you can do anything in recording mode, including any kinds of commands, insertions, cursor movements, and so on. For more information on macros and related options, check out Vim help :h complex-repeat.
Vim registers are shared as place holders for both macros and yanked test; this feature allows you to even save and edit your macros in a file. See this question for details.
Here is a map solution - which copies the line into a buffer and then pastes using p.
The A appends at the end of the line
map <F2> 0dwpo<esc>pAa<enter><esc>pAam<enter><esc>pAax ...etc
If your goal is, when your cursor on a special word, and press something, vim will append different "suffixes" (I hope I used the right word, but you knew what I mean). You could go macro (q). However since you have already written the :s command, you could create a mapping using that command do the same, and it would be shorter.
in command line, you can get the word under cursor by pressing <c-r><c-w>. so you could try:
nnoremap <leader>z :s/<c-r><c-w>/& & &..../<cr>
I didn't write the & & &... part, since I don't know (never tried, I don't have vim under windows. I don't even have windows) if the line break \n could be used here under windows. & means the whole matched part, which in this case is the word under your cursor.
So you just move your cursor to the word, type <leader>z, vim will do the job for you. (if the replacement part is correct :) ).

How do I repeatedly search & replace a long string of text in vim?

I'm aware of the vim replace command, which is of the form, eg:
:%s/old/new/gc
But what if either of these strings is long? How can I use something like visual selection mode, the clipboard or vim registers instead of having to type the old/new text in?
You can use q: to bring up a command-line window. This lets you use all the vim editing commands to edit the vim command line, including p to paste. So, you could copy the text into a register, paste it into the command line window, and execute it that way.
I recently discovered this feature via vimcasts.
According to the manual, you can use Ctrl+R to insert the contents of a register into the current position in the command line. The manual also claims that Ctrl+Y inserts the text highlighted with the mouse into the command line. Remember that in X11 and some other systems, you can also paste text into a program from the system clipboard using the middle mouse button or a menu command in your terminal emulator.
I think to avoid have your command line be huge you can use this to solve your issue
:%s/foo/\=#a/g
That replaces "foo" with whatever is in register a.
If you're trying to do a substitute with a long complicated search pattern, here's a good way of going about it:
Try out the search pattern using some test cases and refine it until you have the pattern you want. I find incsearch really helps, especially with complicated regular expressions.
You can then use :%s//new to replace all instances of the last searched for pattern.
If you've entered a pattern and want to copy it out of the search history, you can use q/ to bring up a command line window containing recent search patterns very similar to the q: one that contains recent command history.
On the other hand, if you're asking about how to copy and paste text into the substitute command:
I'd write the pattern out in insert mode and yank the search and replacement into two distinct registers using, say, "ay and "by and then use :%s/<C-R>a/<C-R>b/gc to do the substitute. There are lots of variations of the yank command, but this one should also work automatically when using a visual selection.
If you're copying in text from the clipboard, you can use <C-R>* to paste it's contents in insert mode.
I have the following mapping in my .vimrc
vnoremap <leader>r "ry:%s/^Rr/
So I visually select the thing I want to replace, and hit ,r, type the replacement and hit return. If I want to paste the replacement, I yank it before selecting the text to replace, and then use <C-r>" to paste it as the replacement before hitting return.
Note: to insert ^R in your .vimrc, you actually type <C-v><C-r>.

Saving vim macros

Does anyone know how to properly save/reuse macros recorded inside of a vim editor?
Use q followed by a letter (for example 'x') to record a macro, then press q to end the macro definition. The pattern surrounded by the starting and ending 'q' during this definition just goes into one of the copy/paste registers (in this case, register 'x') so you can paste it with the"xp or "xP commands in normal mode, where x is the register to paste. Typing "xp in normal mode inserts the contents in register x and exits back to normal mode.
To save it, you open up .vimrc and paste the contents while defining the macro using let #x, then the register will be around the next time you start vim.
The format is something like:
let #q = 'macro contents'
Be careful of quotes, though. They would have to be escaped properly.
So to save a macro 'x', you can do:
From normal mode: qx
enter whatever commands
From normal mode: q
open .vimrc
insert a line let #x = '...' (see the following)
For the above ... pattern, you can use "xp just at the place where the pattern should be placed. But this is not essential, you can just type in the macro definition.
For a more robust solution you can checkout Marvim.
It lets you save a macro in a specific namespace (or use the filetype as a default namespace) and you can later search for your saved macros and load them in a register ready for use.
If you reuse a lot of macros, this is pretty helpful.
Write your macros inside your ~/.vimrc, to define a macro launched by CTRL+O by example, add the following line to your ~/.vimrc :
map <C-O> MACROTEXT
when you record a macro by typing qa you can retrieve your macro text by typing "ap
You can do like this on your ~/.vimrc
:let #a="iHello World!\<CR>bye\<Esc>"
NOTE: You must use double quotes to be able to use special keys like in \<this silly example>.
The :mkexrc (or :mkvimrc) command can be used to save all the current :map and :set settings to a file. See :help mkexrc for details.
Vim 8.0 on MacOS Mojave (10.14.6) actually persists macros and named buffers automatically (by default, although I haven't looked for a way of turning this behavior off). Closing a Vim session will update the ~/.viminfo file with any named buffers / macros.

Resources