Undo many times in Vim? - vim

Suppose state A in my document, I make change to B, C then D.
Now I typed 'u', the state goes to C.
I type 'u' again it goes back to D. (the second undo looks like redo to me).
In my understanding, undo means that I undo it once it will return to C, then undo again to it will return to B then undo again it will return to A.
Also, I know 'u3' can work here but in most cases I have no way to keep track of the number of state changes.
How can I achieve unlimited undo in Vim?

You have only 1 level of undo if you are in Vi compatible mode. You are missing out on a number of features by being in 'compatible' mode. Just create a ~/.vimrc file and you will automatically disable 'compatible' mode.
What wonderful undo features do you get by using 'nocompatible'?
Unlimited undo
Persistent undo
Undo branches (like an undo tree)

I like the old vi undo/redo commands which allows undo (u) or redo (CTRL-R) to be pressed multiple times rather than browsing history to figure out the number of changes to undo.
The vi command uses the ~/.exrc file, not ~/.vimrc so just add "set nocompatible" to the file.
Note that I like using a single undo/redo to jump back to the last place in a file that I changed, and "u" followed by CTRL-R does the trick. And I can always hold down the "u" until all changes are undone including those I might have already saved.

Related

Ctrl-o with ignore "No write since last change"

I can press ctrlO to go to the last jump point. However, if there are any changes in the current document it warns me with:
E37: No write since last change (add ! to override)
Is there a way to ignore that message and do ctrl-o and either (1) discard any changes; or (2) save any changes and do ctrl-o?
Discard any changes --- No.
Save any changes --- set autowrite or set autowriteall
Hide buffer but keep it in memory (can ask for saving it later) --- set hidden
Ask if you want to save a buffer --- set confirm
Note: (2), (3) and (4) are global options and change Vim behaviour for many(!) commands.
2) Here is a simple command for your .vimrc that will save the file before jumping:
noremap <C-O> :update<C-M><C-O>
EDIT: Use :update instead of :w to avoid re-writing the file when it was not previously modified.
1) I looked for the equivalent solution to discard the changes instead of saving them, using :e! instead of :w, but that modifies the list of jump points in a way that break <C-O> completely.

How to undo pressing Ctrl-U in Insert mode to avoid accidentally losing my work

If you're like me and often use Ctrl+Shift+U to enter special characters (like Ctrl+Shift+U 2014 to enter —), you may have occasionally accidentally gotten the timing wrong and pressed Ctrl+U+Shift instead (pressing the U while holding Ctrl but just before pressing Shift).
(For me, it's even easier to fat finger since I usually press all 3 of those keys with my left hand (I use Dvorak) so that I can leave my right hand on their home keys.)
But if you make this mistake while in Insert mode, you can inadvertently and permanently lose an entire line of input—without any way to get it back. Wait, wat!?
(Ctrl+U "Deletes all entered characters before the cursor in the current line." See :help i_CTRL-U or this question)
Pressing Esc U does not undo this deletion, like it would if I had deleted the line with dd. (Even pressing Ctrl+O U without leaving insert mode does not work).
Needless to say, if you've just spent several minutes or an hour composing a really long paragraph (which will be considered a single line if you haven't inserted any line breaks) without leaving Insert mode, it can be very disheartening and disconcerting to vainly press u, expecting to get your line back but having it instead revert back to an even earlier undo state! The confidence you've placed in your trusty editor, vim, suddenly gets dashed to pieces as you dolefully realize that you now have to try to remember what you just wrote and compose it all over again.
I can think of a few workarounds to try to make editing safer, like trying to remember to exit insert mode frequently so that a new undo block is created (see :help undo-blocks)...
But I shouldn't have to tread so carefully when composing something. I should be able to stay in the flow (that is, keep composing without leaving Insert mode) as long as the words keep flowing. (And it's probably safe to say that most editors don't have this problem. In most editors, Undo would undo your changes one character at a time since they don't have any way to group multiple characters together as a single "insert").
Since I probably won't remember to be so careful, I ended up simply disabling use of Ctrl-U altogether in Insert mode, for now, with this:
imap <C-U> <Nop>
But what I'd like to know is if there's any decent way to make Ctrl-U still work in case I ever want to use it, but create an undo state so that this deletion can be easily undone with U. Is this possible? (And why isn't this the default behavior?)

Redo after reopening a file in 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

How to revert changes in Vim?

I'm editing code in a server using Vim.
I pressed J instead of j many times, because CapsLock was enabled.
How can I revert the changes made by Js? Pressing u says it is the oldest change.
See the undolevel settings in your session. Type below command to see current undolevels setting.
:set undolevels ?
You can change the setting either in the session or in .vimrc
:set undolevels=1001 # In vi/vim session
set undolevels=1001 # In .vimrc
In vi/vim, you can keep pressing u to undo the changes, based on the undolevels.
In vi/vim, if you want to undo all the changes, since you had last saved, you can do below things.
You can go to command mode by pressing Esc and then give below command
:e! or :edit!
It will clear all the changes in buffer. The file will return to last saved version.

Multiple selections in VIM

Is it possible to select multiple non-consecutive lines (or sections) in VIM's visual mode? If so, how?
No, this is not possible without plugins.
But you can copy multiple lines into the same buffer, if that solves your problem.
To start the 'Accumulation Buffer':
mark a section to copy in visual mode,
press "a to operate on the buffer a with the next command and
yank it as usual (y).
To add to that buffer:
mark the next section and
press "A (capitalizing the buffer name means "do not overwrite the buffer, append to it instead")
and yank again using y.
You can then paste the accumulated buffer a at any time using "ap.
You have to install the multiselect plugin to get this capability. Find it here: http://www.vim.org/scripts/script.php?script_id=953
A more up-to-date answer is this plugin.
(disclaimer: I personally don't actually use it, it interferes too much with the rest of my vim setup. If your vim is relatively clean and you are moving over from sublime, this may certainly be your cup of tea.)
I would also like to point out the record/replay functionality of vim (the q key). Quite often recording is also unnecessary, I can do the tasks normally done with sublime's multi-select by doing it iteratively (e.g. search for something, perform the fix on the first instance of it, and then subsequent repeats are achieved by hitting n and N to move around and . to repeat the edit operation).
I do have my , comma key nnoremap'd to #q, this repeats the sequence that is recorded by pressing qq (record into q register).

Resources