Reload file without losing undo history
From Vim Tips Wiki
While editing a file, you might decide to abandon your edits by using the
:e command to reload the current file (
:e! if you have modified the file).
Once the file is reloaded, your edits prior to the reload are lost (you cannot undo past the reload). Following is an alternative procedure so you can reload and keep your undo list.
The following line (which you could add to your vimrc) defines a
:Reload command that replaces the current buffer by the current file contents, while preserving the undo history:
command! Reload %d|r|1d
When you type
:Reload and press Enter, the Ex commands shown will be executed:
%d deletes the contents of the buffer (leaving a single blank line);
r reads the current file after the blank line;
1d deletes the first line (the blank).
Warning It is easy to disable undo (for example
:set ul=-1 :help 'undolevels'). If you have disabled undo, the
Reload command will still undo all your unsaved changes and you won't be able to undo that. Also, if the
r command fails for some reason (for example, if you forgot that you are editing a new file or a new buffer with no file), you will be left with a blank screen. You should be able to paste the deleted text by pressing
:Reload, the buffer will be marked as modified. If wanted, the command
:set nomodified could be added.
The command should restore the cursor position, at least to the correct line, if possible.
- This seems to work (Spiiph 12:39, 29 July 2009 (UTC))
command! -bang Reload call ReloadFile(<bang>0) function! ReloadFile(is_force_pos) " save the current cursor position let position = getpos(".") " delete all lines %d " read the file back into the buffer r " remove the superfluous line 1d " restore the cursor position if a:is_force_pos if a:is_force_pos call setpos(".", position) endif endfunc
Another variant of function ReloadFile:
function s:Reload() " Load content of new file into a list of lines. Note that without last " argument (1) it may fail to load file that does not contain "\n" " character, and may consume last "\n" character try let filecontents=readfile(expand('%'), 1) catch " We return 0 on error return 0 endtry " Get the number of lines let fclen=len(filecontents) " If number of lines was reduced if fclen<line('$') " Delete some last lines to “black hole” register in order to leave " registers untouched execute fclen.",$d _" " Join previous change with call setline() so that reloading can be " undone in one step undojoin endif " Overwrite lines with new contents. That does not move cursor. " It returns 0 on success, so we need to invert that let r=!setline(1, filecontents) " Indicate that file was not modified: buffer contents after reload is equal " to file contents set nomodified return r endfunction command -nargs=0 R call s:Reload()
It does not move cursor position, adds only one change that could be undone and does not modify any registers.