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 Answers
Solution
- Start a
file-notify
watch when opening a file ineww
. - 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 whichfile-notify
watches to remove when you quiteww
(especially if you use the watches for other purposes than this too).
- Reload the *eww* buffer every time the function is triggered by
- On quitting
eww
remove all the watches related toeww
. You have to make sure that you call this specific function to quiteww
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
usingC-u M-x eww-open-file
. - Make sure you quit
eww
by callingmodi/eww-quit-and-update-fn-descriptors
. For convenience, the default binding q ineww-mode-map
is now bound to this function. If you use any other binding to quiteww
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. Commented Oct 29, 2014 at 2:33
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)
-
2You can probably advantageously replace the
windmove-left
withsave-window-excursion
(or even bettersave-current-buffer
if you can replace thewindmove-right
with a function which changes the current buffer rather than the selected window).– StefanCommented Oct 13, 2019 at 14:02
auto-revert-mode
, which may point you in the right direction.eww
to respectauto-revert-mode
for local files (alsofile-buffer-name
for that matter). If you don't want to that you can try to combine(info "(elisp) File Notifications")
andeww-current-url
. You might have to map through all*eww*
buffers when something changes to find the right one.