1

How can I show if a file has changed on disk, in the mode-line?

(I'm trying to troubleshoot why auto-revert doesn't work for me, and such an indication would help.)

1
  • Not a full solution, but you will probably want to call function verify-visited-file-modtime as part of whatever solution you end up using. Mar 28, 2023 at 19:10

2 Answers 2

1

Your question are actually two questions asked:

  • How can I show if a file has changed on disk?
  • How can I show a notification in the mode-line?

From what you provide as additional information:

I'm trying to troubleshoot why auto-revert doesn't work for me, and such an indication would help.

I conclude that the more important one and your actual question is:

How can I show if a file has changed on disk

One part required to arrive at a solution was already given in the comment to your question by Phil Hudson mentioning verify-visited-file-modtime . The missing part was how to run this function periodically and give a visual feedback if a file was modified by an external application.

The code below if placed in the initialization file does what you ask for:

(defun check-external-file-modification ()
  (if (verify-visited-file-modtime)
      nil
      (message "%s" "Info: BUFFER changed by external application")
  )
  (run-with-timer 5 nil 'check-external-file-modification)
)
(check-external-file-modification)

Notice that the value 5 in the code above means that the check is done each 5 seconds, but you can change it also to any (also a floating point) other value.

The notification about changed file status is shown each 5 seconds in the minibuffer and mirrored in *Messages*.

Your other question:

  • How can I show notifications in the mode-line?

is worth another question if the code you have written yourself for this purpose and for your specific Mode Line layout should for some reason not work as expected.

0

This is my different implementation of auto-revert just wrapping revert-buffer with change detection using file-attributes that is provided only to retrieve file information, instead of verify-visited-file-modtime used by the original auto-revert. I haven't tested this much, but if you don't mind, try using this to find out if the cause is auto-revert or other environmental factors, HTH.

(setq-default my-file-attributes-table (make-hash-table)) ;; global hash table to store file attributes at visiting and saving.

;; to store file attributes.
(defun my-update-file-attributes (&optional buffer)
  (let ((buf (or buffer (current-buffer))))
    (puthash buf
             (file-attributes (buffer-file-name buf)) ;; using `file-attributes` to get file info more directly than `verify-visited-file-modtime`
             my-file-attributes-table)))

(add-hook 'find-file-hook 'my-update-file-attributes) ;; update at visiting.
(add-hook 'after-save-hook 'my-update-file-attributes) ;; update at saving.

;; to read modified date field in `file-attributes`
(defun my-read-modified-time (attributes)
  (current-time-string (nth 5 attributes))) ;; the 5th element is "The time of last modification as a Lisp timestamp (file-attribute-modification-time). This is the last time when the file’s contents were modified." (ref: 26.6.4 File Attributes)

;; to check file difference and prompt `revert-file`
(defun my-check-files-diff ()
  (maphash
   (lambda (buf attrs)
     (unless (string= (my-read-modified-time attrs) (my-read-modified-time (file-attributes (buffer-file-name buf))))
       (switch-to-buffer buf)
       (revert-buffer) ;; prompt
       (my-update-file-attributes buf))) ;; update to prevent from asking again after canceling revert.
   my-file-attributes-table))

(setq-default my-check-files-diff-interval 5) ;; check interval seconds.
(run-with-timer my-check-files-diff-interval my-check-files-diff-interval 'my-check-files-diff)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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