Detect file change, offer to reload file
Asked Answered
M

7

63

I normally use gVim for editing, but I sometimes use vim when remotely connecting to my machine.

When I have a file opened in gVim and it has changed from outside (e.g. new updates from repository), gVim offers to reload it.

However when such a thing happens with Vim, it does nothing until you try to save the file. It just warns you that file has changed, but does not offer to reload it.

It there a setting to make Vim's behavior match gVim?

Meatiness answered 28/5, 2009 at 23:38 Comment(1)
possible duplicate #2158414Schrock
B
27

This is done using an auto command called FileChangedShell. I'm too new to post links, but your best bet would be to read the autocmd part of the vim documentation (Google for that)

but the gist is to set something like the following line in your vimrc

:au FileChangedShell * echo "Warning: File changed on disk"
Bhatt answered 29/5, 2009 at 4:41 Comment(7)
I don't think that's necessary, vim should warn you about the change automatically.Boob
Though it does not, unfortunately.Meatiness
Sorry Matt, it actually did, was looking at wrong file. It does display warning, but not actual prompt to reload thoughMeatiness
Ah, ok. No worries. Hope you can find what you're looking for!Bhatt
I entered that into my Konsolse vim session and it did not detect that I changed the file with kate behind vim's back. If I refocus the terminal, it does nothing. I guess the event is not fired. Any ideas?Trainee
Event "FileChangedShell" is a consequence of file change detection, not a reason. So it absolutely has no sense to have :au FileChangedShell * somecommand in config if you want vim to detect a file has been changed from outside. You need to trigger that event, not capture it. Matt, so your answer is misleading. I vote for Brian Carper's answer: #924237Templia
Did not work for me, I am using au CursorHold * checktime as recommended belowLanlana
C
61

If you want to open the updated file use

:e

It should reload the open file.

Cormorant answered 28/4, 2010 at 20:41 Comment(1)
Yes. But the question if how to detect the file change automatically, not how to reload it.Durbin
A
56

As ashcatch said, the :checktime command will check for changes on disk and prompt you to reload. So set Vim to run checktime automatically after some event. Which event to use is up to you. One possibility is to use CursorHold, which fires after you move the cursor and then let it sit still for updatetime milliseconds. (Default 4 seconds.)

:au CursorHold * checktime

You could also set it on WinEnter or BufWinEnter so it changes every time you switch between buffers/windows. If you're really paranoid you could set it on CursorMoved so it checks the file on disk every time you move the cursor, but that's probably overkill and may lag a bit.

See :h checktime, :h updatetime, :h autocmd-events-abc.

Amber answered 29/5, 2009 at 19:9 Comment(8)
I am so bad reading vim help... I am not sure why it just numbs my mind for some reason.Gilleod
Brian, vim says "No such group or event: CurshorHold * checktime "Meatiness
Sorry, typo. CurshorHold should have been Cursorhold.Amber
Thanks ^^ I've been wonderning how to do that for quite some time now. This works nice with set autoread to, which will re-read the file if its contents did not change.Perceive
Didn't work for me. I tried CurshorHold and Cursorhold. I am using Windows 7 64 bits.Nepheline
This works badly if you try to enter the "Command Line" (q:). See my answer for a workaround.Palatine
Use :au CursorHold,CursorHoldI * checktime % to only check (and reload if autoread is set) the current file. Note that this doesn't work if buftype is set, i.e. it is not a normal file (e.g. buftype=nowrite or is the quickfix or help buffers.)Ripon
You need to use getcmdwintype() (as in @DBedrenko's answer below) otherwise you get errors in the command window.Eon
B
27

This is done using an auto command called FileChangedShell. I'm too new to post links, but your best bet would be to read the autocmd part of the vim documentation (Google for that)

but the gist is to set something like the following line in your vimrc

:au FileChangedShell * echo "Warning: File changed on disk"
Bhatt answered 29/5, 2009 at 4:41 Comment(7)
I don't think that's necessary, vim should warn you about the change automatically.Boob
Though it does not, unfortunately.Meatiness
Sorry Matt, it actually did, was looking at wrong file. It does display warning, but not actual prompt to reload thoughMeatiness
Ah, ok. No worries. Hope you can find what you're looking for!Bhatt
I entered that into my Konsolse vim session and it did not detect that I changed the file with kate behind vim's back. If I refocus the terminal, it does nothing. I guess the event is not fired. Any ideas?Trainee
Event "FileChangedShell" is a consequence of file change detection, not a reason. So it absolutely has no sense to have :au FileChangedShell * somecommand in config if you want vim to detect a file has been changed from outside. You need to trigger that event, not capture it. Matt, so your answer is misleading. I vote for Brian Carper's answer: #924237Templia
Did not work for me, I am using au CursorHold * checktime as recommended belowLanlana
P
10

To improve on Carper's answer:

" Run checktime in buffers, but avoiding the "Command Line" (q:) window
au CursorHold * if getcmdwintype() == '' | checktime | endif

Without this check Vim will spout errors if you try to use the "Command Line" (q:) buffer, because this buffer doesn't support the :checktime command. Found this out thanks to kdlv on #vim.

Palatine answered 25/9, 2014 at 9:56 Comment(3)
Looks like getcmdwintype() may require vim 7.4? I seem to have it working on 7.3 using getcmdtype() instead.Telesthesia
You can use au CursorHold,CursorHoldI * silent! checktime to ignore errors. This will work in earlier Vim versions too.Ripon
It is also nice to use FocusGained,CursorHold instead of just CursorHold to ensure that the buffer is updated immediately after re-focussing it.Quass
K
9

You can manually trigger the checking with :checktime. gvim does this everytime it regains focus, so it is not necessary that often to do the manual checking.

I don't know if there is a different approach (like automatically checking in a certain time interval).

Kotto answered 29/5, 2009 at 5:41 Comment(2)
Why can't vim also trigger :checktime when it gains focus? Is this a curses program limitation?Durbin
@Durbin ansi escape sequences exist for gaining/losing focus, so in theory this is doable. It depends on your specific terminal emulator if these are sent. iTerm2 does for example.Grannias
M
4

from this answer (refering to an answer by PhanHaiQuang and a comment by flukus)

One can run this oneliner from ex (whithin vim) when needed (or put each command in vimrc, for when log-files are opened.)

:set autoread | au CursorHold * checktime | call feedkeys("lh")

Explanation:
- autoread: reads the file when changed from the outside (but it doesnt work on its own, there is no internal timer or something like that. It will only read the file when vim does an action, like a command in ex :!
- CursorHold * checktime: when the cursor isn't moved by the user for the time specified in 'updatetime' (which is 4000 miliseconds by default) checktime is executed, which checks for changes from outside the file
- call feedkeys("lh"): the cursor is moved once, right and back left. and then nothing happens (... which means, that CursorHold is triggered, which means we have a loop)

Megaera answered 17/1, 2018 at 8:53 Comment(0)
T
0

You can use autoread, :checktime and autocmds events VimResume, FocusGained, BufEnter

In neovim using lua you would need something like this in your init.lua:

vim.opt.autoread = true
vim.api.nvim_create_autocmd({"FocusGained","BufEnter","VimResume", "CursorHold"}, {
  pattern = '*',
  command = 'checktime'
})
  • 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)
Trimetallic answered 17/5 at 5:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.