Can I get a versioned recovery from a VIM swap file? - vim

I have a file x.cpp which a while ago contained, say, "AAAAAAA".
I accidentally copied over it with another file containing, say, "BBBBBBB".
PANIC!
Hang on, let's look at .x.cpp.swp -- there's a load of binary junk then "BBBBBBB" then more junk then "AAAAAAA", so it looks like the swap file contains both versions. Hooray!
So, how do I recover the "AAAAAAAA" version? If I do vim -r then I get "BBBBBBB". Unfortunately, I can't recover-then-hit-undo. Is there an incantation? Can I hack the swap file?
Massive gratitude if you know a trick here.

No, but if you use Vim 7.3+ you can enable undofiles
To get started:
:he undo-persistence
That way you can navigate the undo tree even after a (involuntary) close of your editor.
So yes, the usual trick of going back in time, yanking, going forward in time, pasting will work even after the editor was restarted.
100g- (locate text, yank into register), 100g+ (locate destination, put register).

Related

How to save buffer (preferably if changed) and then close the buffer but not VIM?

So, I just realized I could use marks with capital letters to go to different files. That's great! However, I'm trying to find a way to close the buffer and return to the previous one. Say I go to my header file to change or add the declaration of the function I'm writing, and then I'd like to save the file, but only if there's changes to it, to go back to working on the contents of the function. How can I do this?
There's :x, but it also quits VIM
There's :bd!, but it doesnt save the changes
There's :bw, but that's even worse (unfortunately that's w[ipeout], not w[rite]...)
There's ctrl+O, but it doesnt seem to work when I edit the file (also, it doesnt actually close the buffer)
There's :up followed by :bd, but that's two commands and VIM's about efficiency, so I'd prefer a single command if it exists
There's a few other options and variants, but none that do what I wanted, afaik
It feels like this should be simple enough to do with one command, preferably without macros/plugins/functions/snippets/etc; as close to vanilla as possible. I get the feeling I'm missing something obvious.
You could concatenate commands like so:
:w|bd
I'd like to save the file, but only if there's changes to it
:up[date]
to go back to working on the contents of the function
Press Ctrl^, or enter the command :e[dit] #
I'd prefer a single command if it exists
Set an option :set autowrite and then Vim will save the current buffer on pressing Ctrl^ automatically.

Pasting text to a new buffer

I've found questions that are similar, but don't really address what I'm trying to learn. I want to yank or delete text and append it to a new (or existing) buffer without changing buffers. I want to basically redirect the pasted text to its destination at the end of a separate buffer without leaving the original one, similar to what you might do with shell file redirection. I have a hard time believing vim/nvim can't do this, but haven't found an appropriate answer anywhere as of yet.
:'a, 'bw ~/path/to/file.txt
This will copy the text between the two marks 'a and 'b, and write it to a file in the filesystem. This is good, but the file can't be appended to... and it doesn't get opened in a buffer.
There is a :w >> {file} variant that lets you append to a file (:help :write_a).
As #Matt already commented, the usual way would involve switching buffers. Vimscript usage is closely aligned with (mostly Ex-) commands that the user would interactively use. With recent Vim versions, you can alternatively call the low-level appendbufline() function, though. This would bypass any autocmds, buffer setttings, etc. Depending on your use case, this can be desirable or not.
If the target buffer is already visible or can be kept visible as a side effect, temporarily switching to it is easy (mostly involving :sbuffer). My ingo-library plugin has a function ingo#buffer#visible#Execute() that also handles hidden buffers transparently.

Undo all changes since opening buffer in vim

How can I undo all changes since opening a buffer? I imagine there may be some form of :earlier that does this.
UPDATE: Many are suggesting solutions for traversing to earlier file writes. This isn't what I asked for. I want to return to the original state the file was in when I originally loaded it into a buffer, no matter how many writes were made since then.
To revert the current buffer to the original state prior to the very
first change recorded in its undo list (see :help undo-tree), one
can use the following two consecutive invocations of the :undo
command:
:u1|u
The first command (:undo 1) reverts to the state of the buffer just
after the very first registered change, while the second command
(:undo) reverts that first change itself.
Starting with version 8.1 (see :helpg Patch 8.0.1441), Vim accepts
the change number 0 as a valid argument to the :undo command,
finally providing a way to refer to the state prior to any registered
changes. This makes it possible to achieve the same effect in
a single-command invocation:
:u0
You can use the
:edit!
command to get into the earliest saved state. See :help edit! for more information.
You can also check something like gundo.vim (can be found here), which displays the whole undo tree graphically, and you can easily jump between points. Then there is the histwin plugin which I did not used yet, but offers similar functionality.
In vim 8.1+ as well as in neovim, you can just use :u0
From the documentation
:u[ndo] {N} Jump to after change number {N}. See |undo-branches|
for the meaning of {N}. {not in Vi}
If you type
:u 1
it appears to go to after the first change; pressing u or typing :u will then go back to the change.
Otherwise, you can use a very large count to :earlier or g-
e.g.
:earlier 100000000 or 100000000g-
If you put this into a mapping/command, it could do any of these without too much trouble.
e.g.
:nnoremap <C-F12> :earlier 100000000<CR>
To access previously saved file status, I think the following work :
:earlier 1f
From the documentation :
:earlier {N}f Go to older text state {N} file writes before.
When changes were made since the last write
":earlier 1f" will revert the text to the state when
it was written. Otherwise it will go to the write
before that.
When at the state of the first file write, or when
the file was not written, ":earlier 1f" will go to
before the first change.
:earlier {N}m Go to older text state about {N} minutes before.
That should help... And even you have {N}h which is about {N} hours before.
A graphic solution:
The Gundo plugin allows visual comparison of changes in the undo history.
Open Gundo's "undo history pane", type G go to the last line, then we can back to the original file.

Can I recover my code lost during my last change in vim?

I am very sad I deleted wrong function without commit to SVN server by using vim
After I compiled it I found I made the mistake. I 'make' the file also via vim.
Now I haven't closed the file and it has .swp file.
I tried to use 'u' command to restore my deletion but failed. vim said it's the latest changes. sigh.... Anyway I can restore my function?
Million thanks.
To make Drasils pointer a lot more explicit:
:undolist
g- to 'go back in time'
g+ to 'go forward in time'
Vim 7.3+ has undo 'branches': meaning that it will save state snapshots, even if linear history was overwritten (so it isn't reachable by simple u and )
Vim usually saves the previous version of any file edited as a backup with a ~ appended -- you could check to see whether that file is there and if so, whether it's got the right contents.
There are a couple of ways to recover text that you may have unwittingly lost due to a crash or because you closed your program unintentionally.
Use persistent-undo. Persistent undo provides almost all the features provided by swap/backup file option in points #2 and #3, along with some other options such as granular history traversal.
a. Set persistent-undo on:
Put this in your .vimrc:
set undofile
set undodir=~/.vim/undodir
b. Create the undodir
mkdir ~/.vim/undodir
c. To undo a change, use either of the following options
1) g+ in normal mode to go forward in history
2) g- in normal mode to go backward in history
3). :earlier 20s to go back in time by 20s or earlier 10m to go back in time by 10min etc
4) :later 20s to go forward in time by 20s or later 10m to go forward in time by 10min etc
5). Use :undolist to get a list of undo changes
d. To get a visualization of your undo-branches, you can use plugins like gundo.vim: http://bitbucket.org/sjl/gundo.vim/ to visualize the branches
Use backup files
a. Use this in your .vimrc
set backup
b. Set up the backup directory by putting this in your .vimrc
set backupdir=~/tmp/
c. Set up the backup file name to be added to the backup file by setting this in your .vimrc
set backupext=string
Use swap files
a. Use this in your .vimrc
set swapfile
b. Set up the swap directory by putting this in your .vimrc. This may not be a good idea, because it will prevent you from having two files with the same names, or cause conflicts in swap file names.
set directory=~/tmp/
A better option is to provide multiple paths, so if vim encounters a conflict it can then save it to the directory that it can write to using
set directory=,~/tmp/
In this case, it will try to write the swap file to the current directory. If it can't, then it will attempt to write it to the ~/tmp directory
c. Set up the backup file name to be added to the backup file by setting this in your .vimrc
set backupext=string
TL;DR Use persistent-undo. It provides almost all features of swap and backup, and provides additional features such as granular undo which is not provided by backup and swap file options.
References
1. ftp://ftp.vim.org/pub/vim/doc/book/vimbook-OPL.pdf
I don't know if you can recover something here, but for the future, if you user vim 7.3, you should active these options I explain in my previous comment.
I must say that the savevers plugin has saved me a lot of hours ;-)

In Vim, what is the "alternate file"?

I just ran :help registers in Vim and noticed that # 'contains the name of the alternate file'.
I have seen an example for renaming files that goes like this:
" Save the current file, foo.txt, as bar.txt
:w bar.txt
" Start editing bar.txt
:e#
So apparently in that case, the file you just saved out is the "alternate file."
Can someone give me a more general definition for the "alternate file" and what else you might use it for?
The alternate file is the file that was last edited in the current window. Actually when you use some command to open a new buffer, if the buffer that was displayed had a filename associated with it, that filename is recorded as alternate file name.
See :help alternate-file.
Very useful for...
Pasting in the name of a file I've just been looking at into the current file.
You can use <C-R># for this in insert mode or "#p in normal mode.
Not that useful for...
Jumping back and forth between two files. It does the job very well, but this is just something I don't generally need to do.
Even in the example given, I'd probably use:saveas bar.txt instead.
An Example:
Say if you're doing a bit of C programming and want to call some function. You can't remember the name of the function, so you place a mark on your current location mA and jump into several different files using tags or grep to find out where the function is declared and what it's actually called.
Ah - found it. You can copy the name and return to the mark yiw'A
Uh-oh - we also need to #include the file! Easy - just use the alternate file name register to paste the file name in... Gi#include"<C-R>#"
Be pleased that you've avoided the distraction of having to go back to the function's declaration and copy out the file name via :let #"=#% or something similar.
What I'd rather do when jumping between files:
When editing two files, it's probably easier to split them, so you can keep both on screen at the same time. If I'm editing 2 files I'll usually be comparing them in some way.
Usually I'm interested in 1-3 files (any more and I get confused). I'll often jump into or directly open many other files. Marking the interesting files, or traversing the jump list is usually the way to get around in this case.
If you're editing C/C++ where you're switching between a file and it's header, use a plugin! It will be much more convenient.
I use it in the buffer context to return to the last buffer that I was editing
vim foo bar
:n
:e#
will take you back to foo in that case
I 've always interpreted the "alternate file" as being the "previous file", so it is an handy way to jump back to the buffer you were editing.

Resources