5

If I load a local file, I'd like eww to refresh when the source is changed. This would be similar to auto-revert mode. Is there any way to do this? Right now I have to manually refresh by hitting g in the *eww* buffer.

  • If you're comfortable with elisp, then How can I make ibuffer auto-refresh the list of buffers? has some useful details on implementing custom support for auto-revert-mode, which may point you in the right direction. – phils Oct 22 '14 at 6:36
  • 1
    You should probably fill a bug report requesting eww to respect auto-revert-mode for local files (also file-buffer-name for that matter). If you don't want to that you can try to combine (info "(elisp) File Notifications") and eww-current-url. You might have to map through all *eww* buffers when something changes to find the right one. – rasmus Oct 24 '14 at 14:35
3

Solution

  • Start a file-notify watch when opening a file in eww.
  • In the callback function for that watch, do 2 things:
    • Reload the *eww* buffer every time the function is triggered by file-notify event.
    • Log the event descriptors specific to file opening actions in eww. This is because you need to know which file-notify watches to remove when you quit eww (especially if you use the watches for other purposes than this too).
  • On quitting eww remove all the watches related to eww. You have to make sure that you call this specific function to quit eww and clean up the now-not-required watches.

How to use

  • Copy the below implementation to your init.el.
  • Launch any file you want to load in eww using C-u M-x eww-open-file.
  • Make sure you quit eww by calling modi/eww-quit-and-update-fn-descriptors. For convenience, the default binding q in eww-mode-map is now bound to this function. If you use any other binding to quit eww or to kill windows, make sure you call this function. modi/eww-quit-and-update-fn-descriptors ensures that the eww-specific file-notify watches are removed.

Implementation

(defvar modi/eww--file-notify-descriptors-list ()
  "List to store file-notify descriptor for all files that have an
associated auto-reloading eww buffer.")

(defun modi/advice-eww-open-file-to-auto-reload (orig-fun &rest args)
  "When `eww-open-file' is called with \\[universal-argument], open
the file in eww and also add `file-notify' watch for it so that the eww
buffer auto-reloads when the HTML file changes."
  (prog1
      (apply orig-fun args)
    (when current-prefix-arg ; C-u M-x eww-open-file
      (require 'filenotify)
      (let ((file-name (car args)))
        (file-notify-add-watch file-name
                               '(change attribute-change)
                               #'modi/file-notify-callback-eww-reload)
        ;; Show the HTML file and its rendered form in eww side-by-side
        (find-file-other-window file-name))
      ;; Redefine the `q' binding in `eww-mode-map'
      (bind-key "q" #'modi/eww-quit-and-update-fn-descriptors eww-mode-map))))
(advice-add 'eww-open-file :around #'modi/advice-eww-open-file-to-auto-reload)

(defun modi/file-notify-callback-eww-reload (event)
  "On getting triggered, switch to the eww buffer, reload and switch
back to the working buffer. Also save the `file-notify-descriptor' of the
triggering event."
  (let* ((working-buffer (buffer-name)))
    (switch-to-buffer-other-window "eww")
    (eww-reload)
    (switch-to-buffer-other-window working-buffer))
  ;; `(car event)' will return the event descriptor
  (add-to-list 'modi/eww--file-notify-descriptors-list (car event)))

(defun modi/eww-quit-and-update-fn-descriptors ()
  "When quitting `eww', first remove any saved file-notify descriptors
specific to eww, while also updating `modi/eww--file-notify-descriptors-list'."
  (interactive)
  (dotimes (index (safe-length modi/eww--file-notify-descriptors-list))
    (file-notify-rm-watch (pop modi/eww--file-notify-descriptors-list)))
  (quit-window :kill))

Assumptions

  • You have only one *eww* buffer open.
  • This solution requires emacs 24.4 or newer.
  • Awesome. Unfortunately file notification doesn't work yet on OS X. I'll give this a shot on my other machine which runs Linux. – Jack Moffitt Oct 29 '14 at 2:33

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.