Vim forgetting its history when a file becomes read-only - vim

After I commit a file to Perforce with vi, it will become read-only.
If I have this file open in vim, then when it becomes readonline I lose my undo-redo history, without even being asked.
Is there an option in VI to preserve the undo-redo history when the file becomes read only while you are editing?

It is a Vim bug. Whenever you :edit filename, implicitly or explicitly it seams that Vim is zeroing all undo history for this file because ( I guess ) it think that it is newly opened file. And after perforce commit, your file is kind of “changed outside” and Vim should ask you “Reload file?” unless you set “autoread”.
Check you vimrc for “set autoread” option.

Maybe you could try to make it readable with modelines :
#vim : set noreadonly:
I wrote # but of course you must replace it with the adequate symbol for a comment.

Related

What are some use cases of :e in Vim?

I was reading :help :edit but I really don't understand the following sentence:
This is useful to re-edit the current file, when it has been changed outside of Vim
And what does start all over mean in :help :edit!?
This is useful if you want to start all over again
Could anyone please provide some use cases of them?
"Changed outside of Vim" means that the file that you're editing has been written to by another program. :e will load the latest version, and :e! will do that even if you have unsaved changes.
Loading the current file from the file system is useful if you're following a log, or viewing a generated file that gets updated when you run :make and other situations.
One use for this is to throw away the changes you've made since the last save with :w and go back to the most recent saved version. Which is to say, it's not necessary for the file to have changed behind Vim's back for this to be useful. Although Vim has enough undo depth that you can usually undo your way to back to the unmodified state, it's cumbersome. You can easily "overshoot" and then have to redo. The status line shows you whether the file is [Modified] or not, but as you undo, it gets overwritten with information about each undo, so you have to use Ctrl-G to re-display the file status.
I had no idea :e by itself with no argument did this re-loading, by the way; I have been using :e% for years!

automatically save the current buffer when is going to edit a new file

I've made some changes in the current buffer, and I want vim to automatically save the current buffer when I'm going to edit a new file with the following command:
:e another_file_which_is_not_a_buffer_in_vim_yet
I added the following line in my .vimrc file, but it didn't work.
autocmd BufLeave * update
Vim still prompted me No write since last change, why? How can I make it work? By the way, I only want to save the current buffer instead of all buffers, because saving all buffers seems to mess up the order of the buffers, which would bring trouble when I run :bp or :bn.
Vim has an option to save also for, among others, :edit in addition to what triggers autowrite:
set autowriteall
Relevant manual excerpts:
autowrite:
'autowrite' 'aw' boolean (default off)
global
Write the contents of the file, if it has been modified, on each
:next, :rewind, :last, :first, :previous, :stop, :suspend, :tag, :!,
:make, CTRL-] and CTRL-^ command; and when a :buffer, CTRL-O, CTRL-I,
'{A-Z0-9}, or `{A-Z0-9} command takes one to another file.
Note that for some commands the 'autowrite' option is not used, see
'autowriteall' for that.
and autowriteall:
'autowriteall' 'awa' boolean (default off)
global
{not in Vi}
Like 'autowrite', but also used for commands ":edit", ":enew", ":quit",
":qall", ":exit", ":xit", ":recover" and closing the Vim window.
Setting this option also implies that Vim behaves like 'autowrite' has
been set.
This line of code shold do the trick. Place it inside .vimrc file. Location of this .vimrc file can be found if you type :version inside of vim.
set autowrite
More about this topic can be found on this link

Recover a vim file from the .un~ file without the undo command

How can I restore a vim file from the undo file without hitting undo?
I had a vim file that I saved while adding text. Then I ran a python command that emptied the file's contents, and I can see some of the words the file contained in the file's .un~ file. When I try to undo in the file, it says Already at latest change. I can't find the swap file in my swap files directory.
As the other answers have noted, you can't recover the whole file from vim's undo files, simply because vim seems to only keep diffs in the undo files, not the whole contents. (That makes a lot of sense, as it's space efficient.)
One thing you can try though, is to extract what's possible from your undo file:
$ strings <undo-file>
The output will not be pretty, but you could end up finding something that's valuable to you.
You can't. The undo information is linked to Vim's last knowledge of the file's contents; when they don't correspond any more, Vim cannot re-apply the changes. This is documented at :help undo-persistence:
Vim will detect if an undo file is no longer synchronized with the file it was
written for (with a hash of the file contents) and ignore it when the file was
changed after the undo file was written, to prevent corruption.
Best you can do is try to manually salvage recognizable bits in the undo file, e.g. with a hex editor, or Vim's binary mode.
It is not exactly possible, as the undo file only contains the text that was changed in a single change. If you at some point reloaded the file, the undofile should contain the complete buffer for that and starting from there one could theorectically recover the file (by going through the undo states).
I have written about this before at the vim_use mailinglist here and here (which even contains a patch, that let's you force reading in the undo-file)
You could try to patch vim and see if you can recover at least some data.
A reminder that if you have set in your .vimrc file
set backupdir=$HOME/tmp
You may have temp copies of the files that are readable and that can be renamed

Stop Vim from saving a file if content has not changed

In GUI text editors I've seen, when text has not changed (or has changed and been reverted to its original state), the Save option is greyed out to indicate so.
For something similar, can Vim disable saving a file in such a case? That is, doing the :w would not actually change the mtime of the file.
You can use the :update command (:up for short) which writes the file only if the buffer has been modified. If you felt strongly you could add an update option to gvim's File menu, but maybe the Ex command is sufficient.
WRITING WITH MULTIPLE BUFFERS *buffer-write*
*:wa* *:wall*
:wa[ll] Write all changed buffers. Buffers without a file
name or which are readonly are not written. {not in
Vi}
:wa[ll]! Write all changed buffers, even the ones that are
readonly. Buffers without a file name are not
written. {not in Vi}
:wa will save all changed files
:xa will save all changed files, and then quit vim.

Vim: Maintain the history of a file after it has been changed and reloaded

If I'm editing a file in Vim, then some external program changes the file, Vim tells me:
W11: Warning: File "test.erl" has changed since editing started
See ":help W11" for more info.
[O]K, (L)oad File:
If I Load the file, though, all the undo history is lost.
Is there any way to avoid that?
Update: it appears that this is one of the new features in Vim 7.3: https://groups.google.com/group/vim_announce/browse_thread/thread/66c02efd1523554b
I don't believe this is possible.
There is a very useful patch available for the vim source code available here that keeps the undo history after exiting vim and restarting. However, I've just tried it and it seems to fail when the file is edited externally. It might be worth contacting the author or reporting a bug on the patch website to see if this can be overcome.
G'day,
I'm not sure but does setting autoread, i.e. entering :set autoread leave the undo history for the file when it changes?
Hmmmm. I'm thinking probably not because the change history is maintained as line numbers and vim doesn't know if those line numbers are still relevant to the changed file.
BTW WTF are you editing a file that is being changed by external forces anyway? Sounds dangerous to me. (-:
This is a workaround I used before Vim 7.3:
" :e usually clears undo history, so we don't really do :e any more.
" Instead we delete the contents of the buffer, then read the file in, which
" is an operation we can undo. We must delete the top (empty) line also.
:map :e<Enter> :%d<Enter>:r<Enter>:0<Enter>dd
When you see the warning prompt, you would have to hit ok instead of load, and then perform the load yourself: :e<Enter>
There are two disadvantages (although I found the tradeoff acceptable):
You lose the line you were on. Your cursor is left sitting at the top of the file.
Vim still thinks the buffer is out of sync with the file, so when you next save, you may need to do :w! instead of the normal :w, and you will need to hit y to confirm the overwrite.
Edit: There might be a workaround for the second problem.
Edit: The first problem could be addressed with a bit more scripting (see :h line.)
I don't see how vim could keep track of something it didn't do.
So, as to the question, I would suggest - source control ... but that's probably not the answer you're looking for.

Resources