Reload buffer when file changes in Emacs

I’ve started learning typescript and one of the cool feature of compiler is –watch options that recompile the file when it change it’s content. In Emacs if file is changed the buffer still contain old file and if you try to edit that file you’re ask if you really want to ed it that file because it change content.

It found that it would be nice to have reload when file changes, so I wrote this little bit of Emacs Lisp:

;; http://emacs.stackexchange.com/questions/22647/reload-single-file-in-every-window
(defun reload ()
  "Revert buffer, then restore previous position."
  (interactive)
  (let ((pt  (point)))
    (revert-buffer t t)
    (goto-char pt)))

;; two helpers to work with alists

(defun add-to-alist (symbol name value)
  "Add new pair to ALIST"
  (let* ((list (symbol-value symbol))
         (pair (assoc name list)))
    (if pair
        (setcdr pair value)
      (let ((pair (cons name value)))
        (if list
            (setf (symbol-value symbol) (cons pair list))
          (setf (symbol-value symbol) (cons pair nil)))))
    (symbol-value symbol)))

(defun remove-alist (symbol name)
  "Remove pair from ALIST"
  (let* ((list (symbol-value symbol))
         (pair (assoc name list)))
    (if pair
        (let ((ptr list))
          (if (eq (caar ptr) name)
              (setf (symbol-value symbol) '())
            (while ptr
              (if (eq (caadr ptr) name)
                  (progn
                    (setcdr ptr (cddr ptr))
                    (setq ptr nil))
                (setq ptr (cdr ptr))))
            list)))))

(require 'filenotify)

(setq file-watchers '())


(defun watch ()
  "Function watch file changes and reload the file from buffer"
  (interactive)
  (let* ((fname (buffer-file-name))
         (pair (assoc fname file-watchers)))
    (if pair
        (progn
          (file-notify-rm-watch (cdr pair))
          (remove-alist 'file-watchers descritor)))

    (let ((descriptor (file-notify-add-watch fname
                                             '(change)
                                             (lexical-let ((filename fname))
                                               (lambda (event)
                                                 (with-current-buffer (get-file-buffer filename)
                                                   (if (not (buffer-modified-p))
                                                       (progn
                                                         (message "update %s" filename)
                                                         (reload)))))))))
      (add-to-alist 'file-watchers fname descriptor))))

Then to watch the file You just need to invoke the function using M-x watch. The function will not reload the buffer if you have modifications. In that case you need to invoke reload function using M-x reload.

This will probably don’t work on windows but I’m not sure, here is documentation for file-notify-* functions.

,

  1. #1 by greenius on July 8, 2018 - 15:28

    emacs already has a similar function: M-x auto-revert-mode
    https://www.gnu.org/software/emacs/manual/html_node/emacs/Reverting.html

    • #2 by jcubic on July 8, 2018 - 16:17

      Second time I write something in Emacs that already implemented, but the docs doesn’t say what happen if buffer was modified, but not saved. Also revert-buffer always ask to revert the buffer.

  1. Reload buffer when file changes in Emacs | Jakub Jankiewicz – SunDawning

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: