Wikia

Vim Tips Wiki

Reload file without losing undo history

Talk0
1,612pages on
this wiki

Redirected from VimTip1627

Tip 1627 Printable Monobook Previous Next

created 2009 · complexity basic · version 7.0


This tip is deprecated for the following reasons:

The persistent undo feature added in Vim 7.3 provides built-in undo through reload (and much more).

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.

ReloadEdit

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

CommentsEdit

After :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.

Around Wikia's network

Random Wiki