How can I make vim check automatically if the file has changed externally?
Asked Answered
F

7

9

I usually open many files in tabs with vim -p. Is it possible to check if any of the files was changed outside of Vim since editing started?

Florance answered 20/2, 2010 at 19:33 Comment(1)
"Is it possible to check if any of the files was changed since editing started (e.g. by some external program)?" As it stands, your question is ambiguous. You should be able to remove statements in parenthesis without changing the meaning of the sentence. Please fix.Odette
F
12

Add these lines to your .vimrc:

au FocusGained,BufEnter * :silent! checktime
au FocusLost,WinLeave * :silent! w

Basically, check for and reload (or discard) external changes when Vim or the current buffer gains focus, and optionally, auto-save when leaving focus.

Source: Vim Wiki.

Florance answered 24/2, 2010 at 20:6 Comment(1)
FocusGained and BufEnter could be complemented with VimResume to check as soon as you resume vim after a Ctrl-Z and with CursorHold if you want to check for changes everytime you are "idle"Corner
S
6

I came across an interesting find related to this question today...

Hidden in /usr/share/vim/vim71/vimrc_example.vim there is this command:

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
        \ | wincmd p | diffthis

It will open a vimdiff-like window with the current buffer and the underlying file highlighting all of the changes between the two.

Shuffle answered 25/2, 2010 at 18:7 Comment(0)
I
3

vim usually warns me automatically if it detects an external change to a file; however, from perusing the documentation it looks like you can invoke that check manually with :checktime

Unfortunately I don't know how to disable that aforementioned automatic check to test and see if checktime does the right thing, so this answer might be completely off-base.

Imogen answered 20/2, 2010 at 19:41 Comment(1)
au CursorHold * checktime - close to it. But I need to move the cursor for it to detect a change :(Florance
S
2

Use :edit

:help :edit for more info.

Shuffle answered 20/2, 2010 at 19:38 Comment(0)
O
1

You can find out if the buffer in the active window is modified by running the command:

:set mod?

If it returns nomodified, then the contents of the buffer match those of the corresponding file. If it returns modified, then the buffer has unsaved changes.

By default, the status-line shows a [+] symbol if the current buffer has been modified. The status line is generally only visible if you have split windows. If you want to show the status line, even when you have just a single window, run:

:set laststatus=2

There's a good article about customizing your status line on Vim Recipes.

Odette answered 22/2, 2010 at 12:27 Comment(3)
I believe he means if the file on disk was modified by something other than vim since opening the file.Paten
The question is poorly worded: the crucial detail I missed is in parenthesis. Thanks for the downvote.Odette
Actually I have a [+] in the tabline if the file was modifiedFlorance
C
1

If using neovim lua put the following on ~/.config/nvim/init.lua:

vim.opt.autoread = true
vim.api.nvim_create_autocmd({"FocusGained","BufEnter","VimResume", "CursorHold"}, {
  pattern = '*',
  command = 'checktime'
})

It uses autoread, :checktime and autocmds events VimResume, FocusGained, BufEnter

  • The autocmd will run :checktime when you switch between buffers or when you ctrl-z/fg (VimResume) or just when you are idle (CursorHold)
  • autoread will automatically read the file if it has changed and you don't have changed the file inside vim
  • if you have changed the file in vim and :checktime detects a change outside of vim then you will be presented with the W12: Warning: File "xxxxx" has changed and the buffer has changed in Vim as well (see :help W12)
Corner answered 17/5 at 6:11 Comment(0)
Z
0
let s:pid=system("ps -p $$ -o ppid=")+0
if !exists('g:watches')
    let g:watches={}
else
    finish
endif
function! ModWatch(fname, match)
    let fname=fnamemodify(a:fname, ':p')
    if has_key(g:watches, fname)
        return
    endif
    let shellscript=
                \"while true ; do".
                \"    inotifywait ".shellescape(fname)." ; ".
                \"    kill -WINCH ".s:pid." ; ".
                \"done"
    echo shellscript
    echo shellescape(shellscript)
    let pid=system("sh -c ".shellescape(shellscript)." &>/dev/null & echo $!")+0
    call extend(g:watches, { fname : pid })
    augroup ModWatch
        execute "autocmd! BufWipeOut ".a:match
        execute "autocmd BufWipeOut ".a:match.' call DeleteWatch("'.
                    \escape(fname, '\"|').'")'
    augroup END
endfunction
function! DeleteWatch(fname)
    call system("kill ".g:watches[a:fname])
    unlet g:watches[a:fname]
endfunction
augroup ModWatch
    autocmd!
    autocmd VimResized * checktime
    autocmd BufNew * call ModWatch(expand("<afile>"), expand("<amatch>"))
augroup END
Zarla answered 20/2, 2010 at 23:17 Comment(1)
Yes, on linux with inotify installed.Zarla

© 2022 - 2024 — McMap. All rights reserved.