7

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.

2
  • 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
    Commented Oct 22, 2014 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
    Commented Oct 24, 2014 at 14:35

2 Answers 2

4

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.
1
  • Awesome. Unfortunately file notification doesn't work yet on OS X. I'll give this a shot on my other machine which runs Linux. Commented Oct 29, 2014 at 2:33
2

I fixed the same issue with a noob solution so here it is:

I basically added a hook that calls eww-reload on the "other frame" -that supposedly has the web page open- once the markdown gets saved.

This works fine for me as I usually have my window split into two frames only when I'm writing in markdown, one for md and the other for preview -using either doc-view or eww-

So here is the snippet I added to my init.el, please read carefully and edit according to your situation:

(defun compile-md ()
  "Run available makefile that should compile markdown to whatever."
  (interactive)
  (when (derived-mode-p 'markdown-mode)
    (shell-command "make")); that make file uses pandoc to compile md to html
  (windmove-right); supposing the eww frame is on the right 
  (when (derived-mode-p 'eww-mode)
    (eww-reload))
  (windmove-left); get back to the md buffer
 )

(add-hook 'after-save-hook #'compile-md)
1
  • 2
    You can probably advantageously replace the windmove-left with save-window-excursion (or even better save-current-buffer if you can replace the windmove-right with a function which changes the current buffer rather than the selected window).
    – Stefan
    Commented Oct 13, 2019 at 14:02

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.