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?

  • While you might be able to do that with vim alone, the simplest solution would be to let the system do that. I'd write a bash script, did_my_file_change.sh, which tells you if it did change, and then you can call this script from vim with a system() call
    – Zorzi
    Jan 26 at 9:40
  • Or use a watcher (entr is one I know of but there are many)
    – D. Ben Knoble
    Jan 26 at 13:14

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'
    call timer_start(1000, {_ -> s:check(a:file, mtime)})

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.