I want vim to notify me if the contents of a certain file path/to/file changes, but that file won't be open in the vim instance.
How can I achieve this?
Vim doesn't really include a mechanism for this; but it does include "timers" for running functions in the background.
With this, we can add a timer to check the modification time of a file every n seconds and issue an error if this changes. For example:
fun s:check(file, last) abort
let mtime = getftime(a:file)
if a:last isnot 0 && mtime isnot a:last
echom 'File ' . a:file . ' changed'
return
endif
call timer_start(1000, {_ -> s:check(a:file, mtime)})
endfun
command! -complete=file -nargs=1 CheckFile call timer_start(1000, {_ -> s:check(<f-args>, 0)})
The :CheckFile command starts a timer after 1000ms (1 second); this reads the modification time with getftime(), and if it's different from the last one then it issues a message. If it's identical then we start a new timer to run again in a second.
This polling technique is not ideal and potentially slow; which is why modern systems come with notify mechanisms such as inotify and kqueue, but for a single file (or a small number of files) it should be fine for most cases, and this method doesn't rely on any external tools.
You may want to modify the above to suit the behaviour you want; this will stop watching after the first change. You can also extend it by allowing people to stop watching files, and so forth, but this should give you an idea.
There is also one big caveat with all of this: echoing messages from background functions is not very reliable; :echom can easily be overridden with something you're doing, and it won't show if you're in insert mode at all. You can use :echoerr instead, but that's kind of ugly. "How can I reliably notify users from a background function?" is another question, and something I don't really have an answer to at the moment.
did_my_file_change.sh, which tells you if it did change, and then you can call this script from vim with asystem()call – Zorzi Jan 26 '21 at 09:40