Redo after reopening a file in Vim - vim

I am using vim editor. I was writing a program and did some of the changes in the file after which I "undo" all the changes and by mistake closed the file. Later I realized that the approach that I was doing in the code is right, So I again opened the file and tried to do "redo" operation,but as I have closed the session I think I have lost all the history. Can somebody please tell me if I can do redo by some means as retyping the whole thing again is quite tedious.
Is there some way in which I can redo changes after opening a new session of Vim file

For that you need to have :help persistent-undo enabled:
When unloading a buffer Vim normally destroys the tree of undos created for
that buffer. By setting the 'undofile' option, Vim will automatically save
your undo history when you write a file and restore undo history when you edit
the file again.
Unfortunately, 'undofile' is off by default, so unless you've configured it (and if you've tried redo and failed, that looks like it's off), it's of no use for your current problem.
If the swap-file is still lying around (unlikely as there was a clean exit of Vim), you might be able to grab small incoherent bits of your edits from it.
soap box
To preempt the typical comments: You probably have to accept the loss right now, but take this as an opportunity to rethink your approach. Persistent undo is a really nice feature. With a modern revision control systems (like Git or Mercurial), you can commit often and only locally, and revising your edits is easy to do. Even if that's not an option, there are plugins for Vim (like my writebackup plugin) that make it very easy to frequently save "snapshots" of important editing states. Any of these could save you from the data loss next time!

Another approach, in case you have executed some commands, is recovering your command history by redirecting it into a register.
:redir #h
:history
:redir END
:set paste
"hp
:redir #h ............. start redirecting output to register "h"
:history .............. outputs all commands history
:redir END ............ stops redirecting
:set paste ............ to avoid wrong indentation
"hp ................... puts the "h" register in the current position
you can control where to put it by doing...
0put h .............. pastes the `h` register at the line zero
Once you have a series of commands into a file or register it makes easier to build a function like:
function! Helo()
echo "hello world"
endfunction
If by any change you have used a macro, let's say q, you can retrive it or even edite it, because macros are regular registers that you can reassign as you want. For example, on insert mode you can type:
Ctrl-r q .................... pastes register q
:let #q= ................... starts reassingning macro q
:let #q= ctrl-r q .......... pastes the q register on its reassignment
setting register q to "hello vim"
:let #q = "ihello\<Return>vim\<Esc>"
OBS: Using double quotes you can use control keys as seen above
Any complex command can be saved into the clipboard
:let #+ = #: .............. places last command on the clipboard
:#+ ......................... uses clipboard as command

Related

How to document all commands that I used in Vim editor in a special file?

I need to document all commands that I used to modify text using Vim editor. When I am in the terminal and need to save all my input in a file I usually write:
history > ~/some_file.txt
However, I am not sure how to do it while using vim. Can you tell me?
Any output can be redirected with :redir. So
redir >~/vim.history|silent history|redir END
Will redirect the output of :history to the file ~/vim.history. Here silent is used to prevent a -- More -- prompt.
You could also put the history into the current buffer with
:put =execute(':history')
Note that Vims history is limited to 50 entries by default (see :help 'history).
Use startup option -w. From the docs:
All the characters that you type are recorded in the file "scriptout", until you exit Vim. This is useful if you want to create a script file to be used with "vim -s" or ":source!".
Press qx, which causes Vim to start recording your keystrokes.
Press q to finish recording.
Move your cursor to wherever you would like Vim to paste the record it has just made.
Press "xp to paste the record.
The x identifies a buffer. Buffers y, z and so on also exist, so you can use a different letter than x if you wish.
Nothing requires you to paste the record into the file you were editing when the record was made, incidentally. To paste into a different file, give the command :tabedit name-of-different-file, press [Enter], and then press "xp to paste. (Since :tabedit opens the second files in another tab, you can then press gt to toggle between the two if you wish.)

Vim-commands pasted from clipboard inserts commands instead of executing them

For quick execution of some commands I want to type them somewhere, then paste them into vim for execution. A while (some years or 10 years ago) this worked. Nowadays, vim enters insert mode and my commands get inserted into my file. I know that I can have macros for that, but for quick repetition of some commands this was very useful. Couldnt find anything about it, coz when asking for vim and paste only answers related to :set paste etc show up. Example of pasted text:
/foo
yy?bar
p/foo
j
Should, when pasted in command mode, search for the next foo, yank the line, search backwards for next bar, then paste the yanked foo-line, then go behind that foo-line.
Again, to make it clear: I dont want to know about workarounds (makros, scripts, and so on), I want to know how to disable (temporarily) vim from distinguishing between text typed with keyboard and text pasted.
This is the result of "bracketed paste mode". See :help xterm-bracketed-paste.
Disable "bracketed paste mode" by clearing 't_BE':
set t_BE=
If your Vim has been compiled with clipboard support then you can just leave 't_BE' as is and instead execute clipboard as a register via #* or #+ which will probably be more "idiomatic" way to handle such use case.
For more informations see :h #.
I had this same problem...
I have LARGE files of vim commands that I use to bulk reformatting hundreds of plain text files. That is I would: paste commands, next file, paste commands, next file, and in so doing edit hundreds of files, with the given set of vim commands, in just a minute or so...
Then it all suddenly stopped working because Bracketed Paste mode was added... (part of patch 8.0.0238 I believe).
However I still liked the added ability to paste text when in insert mode, without vim auto-indent making a mess of the inserted text, so did not want to lose that either...
My solution, was to disable paste while in normal or command modes,
while leaving brackets paste as in for insert mode...
nmap <PasteStart> <NOP>
nmap <PasteEnd> <NOP>
cmap <PasteStart> <NOP>
cmap <PasteEnd> <NOP>

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 :) ).

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.

Vim / vi Survival Guide

What are the essential vim commands? What does a new-user need to know to keep themselves from getting into trouble? One command per comment, please.
What I find irreplaceable (because it works in vi also, unlike vim's visual mode) are marks. You can mark various spots with m (lower case) and then a letter of your choice (eg x). Then you go elsewhere, and can go back with ``x(backquote letter) to the exact spot, or with'x` (apostrophe letter) to go to the line.
These movements can be used as arguments to commands (yank, delete, etc). For example, you want to delete 10 lines; instead of counting and then moving to the topmost line and entering 10dd, you go to either the start or the end of the block, press mm (mark m), then go to the other end of the block, and press d'm (delete apostrophe m). If you use backquote instead of apostrophe in this example, then the deletion will work character-wise, not line-wise. Try marking in the middle of the line with "mark m", moving to the middle of another line, then entering "d backquote m" and you will see what I mean.
I was very happy the day I learned about using * or # to search, down or up respectively, for the word under the cursor. Make sure to :set incsearch and :set hlsearch first.
I like this QRC!
http://www.fsckin.com/wp-content/uploads/2007/10/vi-vim_cheat_sheet.gif
When you have some repetitive action to take Macros are usually faster than regex.
Just type
q[0-9a-z] in normal mode
Many people use
qq
because it's fast.
Press
q in normal mode
again to stop recording.
Then just type
#[0-9a-z] in normal mode
to repeat what you just recorded.
#q
for the example like above.
Edited to add: you can also repeat the macro. Let's say you programed a macro to jump to the head of a line, insert a tab, and then jump down one line. You then test your macro by typing "#q" to run it once. Then you can repeat the action nine more times by typing "9#q".
:q -> quit
:w -> save
:q! -> quit and don't save
:x -> save and quit
:[number] -> go to line number
G -> go to end of file
dd -> delete line
p -> "put" line
yy -> "copy" line
:s/[searchfor] -> search
I guess those are the basic one to start from
Use the 'J' (J for Join; upper-case) command to delete the newline at the end of a line. You'll find it tricky otherwise.
This recent Vim tutorial from IBM is pretty good
First of all you need to know how to close vi:
ctrl-c : q!
Rest can be found from vimtutor. Launch vimtutor by typing vimtutor at your command line
Although this is a matter of personal preference I've found that one of the essential things to do is to remap Esc to something else.
I find it very uncomfortable to reach for the Esc key to exit insert mode, but the beautiful thing about Vim is that allows key mappings.
I'm currently using the following mapping using Control + S:
inoremap <C-s> <Esc>:w<CR>
This has the advantage of being a key mapping I have already committed to memory and has the added value of saving my work every time I go to normal mode. Yeah, I know it is crazy but I would be hitting the save command that frequently anyway. It's like a bad habit, you know.
" ~/.vimrc
" Turn on line numbering
set nu
" Turn on syntax highlighting
syntax on
" Set 4 space expanding tabs
set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
"turn off line wrapping
set nowrap
" Map CTRL-N to create a new tab
:map <C-n> <ESC>:tabnew<RETURN>
" Map Tab and CTRL-Tab to move between tabs
:map <Tab> <ESC>:tabn<RETURN>
:map <C-Tab> <ESC>:tabp<RETURN>
If you're using vim, the 'u' command (in command mode) will Undo the last command you typed. You can use this command repeatedly to undo mistakes you may have made before saving the file.
See http://www.rayninfo.co.uk/vimtips.html for a great collection of Vim tips, from the basic can't-live-without to very sophisticated stuff that you might never have thought of trying.
Lots of great commands are listed at the Vim Tips Wiki.
It's also good to run the vimtutor when learning these commands
alias vi nedit :)
all humor aside..
for vi WHEN NOT using nedit..
i (switch to insert mode)
a (append = move to end of line and switch to insert mode)
esc (exit insert mode)
dd delete a line
x delete a character
:wq (save and quit)
/ start a search
n find Next
? search backwards..
yy (yank) copy a line to the buffer
pp (paste) paste it here
r (replace a character)
<N> <command> this is a neat - but aggravating feature that lets you type digits and then a command so
5dd will delete 5 lines
but at this point you might as well
- man vi and refresh your memory
While there are LOTS more, I switched from Vi to nedit several years ago, which I find has more features I can use on a regular basis more easily. Tabbed editing, incremental search bar, column select, copy and paste. sort selected lines, search and destroy within selection, whole doc or all open docs..
tear-off drop down menus..
and it supports syntax highlighting for all the languages I use.. (with pattern files I've used a long time over the years. VIM many now be equivalent, but It has to introduce a feature that Nedit doesn't and an easy way to migrate my pattern files before I switch again.
I like the Vim 5.6 Reference Guide, by Bram Moolenaar and Oleg Raisky.
You can directly print it in booklet form, easy to read, I always have it laying around.
It's a tad old, but what are 8 years in Vi's lifespan ?
:set ignorecase smartcase
Makes searching case-insensitive, unless your search includes a capital letter. Not the most indispensable perhaps, but I find myself setting this option any time I'm editing in a new place. It's in any vimrc file I own.
:%!xxd
View the contents of a buffer in hexadecimal. To revert:
:%!xxd -r
My biggest tip: ctrl+q saves the day when you accidentally hit ctrl+s to save the file you are working on
I have this in my vimrc
set number
set relativenumber
This gives me a line numbering system which makes j, k keys really productive.
I use vi very lightly, and I only use the following commands:
a - switch to insert mode (after the cursor)
esc - return to command mode
:wq - save and quit
:q - quit (no save, only without modification)
:q! - force quit (no save, also with modification)
x - delete one character (in command mode)
dd - delete the whole line (in command mode)
I know there are many many more, but those are enough to get you by.
One of my favourite commands is %G which takes to directly to the end of a file. Especially useful in log-files.
How to switch between modes (i to enter insert mode (one of many ways), esc to exit insert mode, colon for command mode) and how to save and exit. (:wq)
Another useful command is to search something: /
e.g. /Mon will search (and in case of vim highlight) any occurences of Mon in your file.
As a couple of other people have already mentioned, vimtutor is the way to go. It will teach you everything you need to know in vim. The one piece of general advice I would give you is to stay out of insert mode as much as possible. There is enormous power in the other modes, it just takes a little bit of practice to get used to it.
i - insert mode (escape to exit)
dd - delete line
shift-y - 'Yank' (copy) line
p - 'Put' (paste) line(s)
shift-v - Visual mode used to select text (tryin 'yanking' this text and 'putting' it somewhere.
ctrl-w n - create new window (you can open a file or start new file here)
ctrl-w v - split existing window vertically
ctrl-n (in insert mode) - autocomplete (if supported)
:! to run a shell command, usually with standard in as the file or a selection (shift-V)
Useful plugins to look at:
* Buffer Explorer - use \be to view files in the buffer (and select to re-open)
NB vi is not vim! vim is rapidly turning into the emacs of the new century. nvi is probably the closest thing to the original vi. Here's a nice hint: "xp" will exchange two characters (try it).
replace 'foo' with 'bar' everywhere in the file
:%s/foo/bar/gc
The real power is in the searching. Here are the essential commands:
/Steve will find the first instance of "Steve" in the text.
n will find the next "Steve" in the text.
:%s//Stephen/g will replace all those instances of "Steve" you just searched for with "Stephen".
Not to promote myself, but I wrote a blog post on this subject. It focuses on the critical parts of Vim for a beginner.
My favorites:
% find matching bracket/brace
* and # next/previous match
gg top of page
G end of the page
<Ctrl-v> Change to visual mode and select column
<Ctrl-a> increase current number by 1
<Ctrl-x> decrease current number by 1
Running macros

Resources