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

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 ;-)

Related

Vim: sync read-only status between buffer and file on disk

I'm working with Perforce and all files in my client are read-only by default. So when I'm browsing the source code in vim buffers are marked read-only as well (may be this is not an accurate wording: I can edit its content but cannot save it without '!'). At some point I'm starting to do some edits and discover that I have to checkout file in Perforce. I have a 'nice' command for that:
command PE !p4 edit %
But after it finishes vim offers me a choice to either:
Load content from disk (which I don't want to do, because I'll lost my edits).
Or keep buffer as it is, but this preserves read-only mode (which I don't want either).
Of course I can change RO manually by doing :set noro but obviously want to avoid that.
Currently I've added it to the PE command above, but this doesn't check the real status of the file, so seems to be a little bit dangerous:
command PE !p4 edit % | set noro
What I really want is "true" synchronization of read-only state between file on disk and buffer in vim.
UPD: Mysteriously, the last version works out of the box -- if p4 edit fails RO state on buffer is not removed. No ideas how it is working...
Vim has a filewritable() function to query the file's access state, why don't you use that?
command PE execute '!p4 edit %' | let &readonly = !filewritable(expand('%'))

How to automatically name a file when saving in vim

I'm trying to emulate in vim a behaviour similar to that of TextEdit.app.
As I work I often open a lot of files to take notes, and keep them there without saving them. When I restart the laptop, the TextEdit files will still be there and open thanks to AutoSave. If I do the same thing with vim (specifically MacVim) the files are (as expected) not saved and I lose their content.
My recipe for solving this problem has two bits. The first one is to automatically save the files when I'm not using them, so using a command like:
autocmd BufLeave,FocusLost * silent! wall
This works fine with files that have already been saved, but it ignores ones that have not yet been saved. This is where the second bit comes into play, I would like vim to automatically give these files a default name if it tries to save them and they don't already have a name. Possibly I would also like there to be a default save directory.
The ideal solution would be that when an unnamed file/buffer loses focus it gets saved as ~/Documents/notes/note_1.txt, the second one note_2.txt, etc etc.
I did look around for any pointers that could help in either direction (default name and default directory - the latter is not fundamental though), but couldn't find anything.
Can anybody help?
I don't like your idea, but it is doable.
You need a function:
function! SaveIt()
if bufname("%")==''
exec 'w /path/note_'.localtime()
else
w
endif
endfunction
and in your autocommand, just call the function. Some points you need to note:
the filename would be /path/note_( ms since 1970). your 1,2,3.. index will make vim check filesystem to find out the index. It could be a better name, e.g note_2013-09-11_11:11:11.233 You just change the localtime()
this may throw exception when you try to save a readonly buffer. (help, qf ...) You could check for them though.
Note that I didn't add the ! in w cmd.
it may not work for your autocmd wall. if you want to do it, you have to loop through all buffers, and for each buffer call the function.
after all the function shows the direction how it could be done, it (the quality) is still very far away from "production" level.

How to stop Vim from creating *-e files

Recently my Vim has been littering my folders with extra files ending with -e. For example, if I'm editing a file called test.php, sometimes (but not always!) I'll wind up with another file called test.php-e as well.
I have no idea what's causing this, but it's fairly annoying. I haven't changed anything recently, as far as I can tell. The backup files all wind up in my ~/.vim/backups directory, so I'm not sure where these things are coming from. Thoughts?
set nobackup
or set backup dir to something like /tmp and purge from time to time.
From VIM docs (:help nobackup)
'backup' 'bk' boolean (default off)
global
{not in Vi}
Make a backup before overwriting a file. Leave it around after the
file has been successfully written. If you do not want to keep the
backup file, but you do want a backup while the file is being
written, reset this option and set the 'writebackup' option (this is
the default). If you do not want a backup file at all reset both
options (use this if your file system is almost full). See the
|backup-table| for more explanations.
When the 'backupskip' pattern matches, a backup is not made anyway.
When 'patchmode' is set, the backup may be renamed to become the
oldest version of a file.
NOTE: This option is reset when 'compatible' is set.

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 get a versioned recovery from a VIM swap file?

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

Resources