elisp: File Notifications

 
 38.20 Notifications on File Changes
 ===================================
 
 Several operating systems support watching of filesystems for changes of
 files.  If configured properly, Emacs links a respective library like
 ‘inotify’, ‘kqueue’, ‘gfilenotify’, or ‘w32notify’ statically.  These
 libraries enable watching of filesystems on the local machine.
 
    It is also possible to watch filesystems on remote machines, See
 Remote Files (emacs)Remote Files. This does not depend on one of the
 libraries linked to Emacs.
 
    Since all these libraries emit different events on notified file
 changes, there is the Emacs library ‘filenotify’ which provides a unique
 interface.
 
  -- Function: file-notify-add-watch file flags callback
      Add a watch for filesystem events pertaining to FILE.  This
      arranges for filesystem events pertaining to FILE to be reported to
      Emacs.
 
      The returned value is a descriptor for the added watch.  Its type
      depends on the underlying library, it cannot be assumed to be an
      integer as in the example below.  It should be used for comparison
      by ‘equal’ only.
 
      If the FILE cannot be watched for some reason, this function
      signals a ‘file-notify-error’ error.
 
      Sometimes, mounted filesystems cannot be watched for file changes.
      This is not detected by this function, a non-‘nil’ return value
      does not guarantee that changes on FILE will be notified.
 
      FLAGS is a list of conditions to set what will be watched for.  It
      can include the following symbols:
 
      ‘change’
           watch for file changes
      ‘attribute-change’
           watch for file attribute changes, like permissions or
           modification time
 
      If FILE is a directory, changes for all files in that directory
      will be notified.  This does not work recursively.
 
      When any event happens, Emacs will call the CALLBACK function
      passing it a single argument EVENT, which is of the form
 
           (DESCRIPTOR ACTION FILE [FILE1])
 
      DESCRIPTOR is the same object as the one returned by this function.
      ACTION is the description of the event.  It could be any one of the
      following symbols:
 
      ‘created’
           FILE was created
      ‘deleted’
           FILE was deleted
      ‘changed’
           FILE’s contents has changed; with ‘w32notify’ library, reports
           attribute changes as well
      ‘renamed’
           FILE has been renamed to FILE1
      ‘attribute-changed’
           a FILE attribute was changed
      ‘stopped’
           watching FILE has been stopped
 
      Note that the ‘w32notify’ library does not report
      ‘attribute-changed’ events.  When some file’s attribute, like
      permissions or modification time, has changed, this library reports
      a ‘changed’ event.  Likewise, the ‘kqueue’ library does not report
      reliably file attribute changes when watching a directory.
 
      The ‘stopped’ event reports, that watching the file has been
      stopped.  This could be because ‘file-notify-rm-watch’ was called
      (see below), or because the file being watched was deleted, or due
      to another error reported from the underlying library.
 
      FILE and FILE1 are the name of the file(s) whose event is being
      reported.  For example:
 
           (require 'filenotify)
                ⇒ filenotify
 
           (defun my-notify-callback (event)
             (message "Event %S" event))
                ⇒ my-notify-callback
 
           (file-notify-add-watch
             "/tmp" '(change attribute-change) 'my-notify-callback)
                ⇒ 35025468
 
           (write-region "foo" nil "/tmp/foo")
                ⇒ Event (35025468 created "/tmp/.#foo")
                   Event (35025468 created "/tmp/foo")
                   Event (35025468 changed "/tmp/foo")
                   Event (35025468 deleted "/tmp/.#foo")
 
           (write-region "bla" nil "/tmp/foo")
                ⇒ Event (35025468 created "/tmp/.#foo")
                   Event (35025468 changed "/tmp/foo")
                   Event (35025468 deleted "/tmp/.#foo")
 
           (set-file-modes "/tmp/foo" (default-file-modes))
                ⇒ Event (35025468 attribute-changed "/tmp/foo")
 
      Whether the action ‘renamed’ is returned, depends on the used watch
      library.  Otherwise, the actions ‘deleted’ and ‘created’ could be
      returned in a random order.
 
           (rename-file "/tmp/foo" "/tmp/bla")
                ⇒ Event (35025468 renamed "/tmp/foo" "/tmp/bla")
 
           (delete-file "/tmp/bla")
                ⇒ Event (35025468 deleted "/tmp/bla")
 
  -- Function: file-notify-rm-watch descriptor
      Removes an existing file watch specified by its DESCRIPTOR.
      DESCRIPTOR should be an object returned by ‘file-notify-add-watch’.
 
  -- Function: file-notify-valid-p descriptor
      Checks a watch specified by its DESCRIPTOR for validity.
      DESCRIPTOR should be an object returned by ‘file-notify-add-watch’.
 
      A watch can become invalid if the file or directory it watches is
      deleted, or if the watcher thread exits abnormally for any other
      reason.  Removing the watch by calling ‘file-notify-rm-watch’ also
      makes it invalid.
 
           (make-directory "/tmp/foo")
                ⇒ Event (35025468 created "/tmp/foo")
 
           (setq desc
                 (file-notify-add-watch
                   "/tmp/foo" '(change) 'my-notify-callback))
                ⇒ 11359632
 
           (file-notify-valid-p desc)
                ⇒ t
 
           (write-region "bla" nil "/tmp/foo/bla")
                ⇒ Event (11359632 created "/tmp/foo/.#bla")
                   Event (11359632 created "/tmp/foo/bla")
                   Event (11359632 changed "/tmp/foo/bla")
                   Event (11359632 deleted "/tmp/foo/.#bla")
 
           ;; Deleting a file in the directory doesn't invalidate the watch.
           (delete-file "/tmp/foo/bla")
                ⇒ Event (11359632 deleted "/tmp/foo/bla")
 
           (write-region "bla" nil "/tmp/foo/bla")
                ⇒ Event (11359632 created "/tmp/foo/.#bla")
                   Event (11359632 created "/tmp/foo/bla")
                   Event (11359632 changed "/tmp/foo/bla")
                   Event (11359632 deleted "/tmp/foo/.#bla")
 
           ;; Deleting the directory invalidates the watch.
           ;; Events arrive for different watch descriptors.
           (delete-directory "/tmp/foo" 'recursive)
                ⇒ Event (35025468 deleted "/tmp/foo")
                   Event (11359632 deleted "/tmp/foo/bla")
                   Event (11359632 deleted "/tmp/foo")
                   Event (11359632 stopped "/tmp/foo")
 
           (file-notify-valid-p desc)
                ⇒ nil