summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bookmark-conf.el13
-rw-r--r--eww-conf.el143
2 files changed, 153 insertions, 3 deletions
diff --git a/bookmark-conf.el b/bookmark-conf.el
index a8244e5..fc95cb8 100644
--- a/bookmark-conf.el
+++ b/bookmark-conf.el
@@ -50,6 +50,7 @@
blist-filter-groups
(list
(cons "Eshell" #'blist-eshell-p)
+ (cons "EWW" #'blist-eww-p)
(cons "Gnus" #'blist-gnus-p)
(cons "PDF" #'blist-pdf-p)
(cons "ELisp" #'blist-elisp-p)
@@ -64,9 +65,15 @@
;; There seems to be only two GNUS bookmark handlers (or one?)
(blist-define-criterion "gnus" "Gnus"
- (let ((handler (bookmark-get-handler bookmark)))
- (memq handler (list #'gnus-summary-bookmark-jump
- #'gnus-bookmark-jump))))
+ (memq (bookmark-get-handler bookmark)
+ (list #'gnus-summary-bookmark-jump
+ #'gnus-bookmark-jump)))
+
+;;;; EWW group
+
+(blist-define-criterion "eww" "EWW"
+ (eq (bookmark-get-handler bookmark)
+ #'durand-eww-bookmark-jump))
;;;; Info group
diff --git a/eww-conf.el b/eww-conf.el
index 4b2c8ae..86b2cd8 100644
--- a/eww-conf.el
+++ b/eww-conf.el
@@ -385,6 +385,149 @@ For the meanings of NAME and DIR, see the documentation of
(write-region (point) (point-max) file))
(message "Saved %s" file)))
+;;; Bookmark integration
+
+;; This section defines functions to make bookmarks for EWW buffers
+;; and to jump to those bookmarks.
+
+;;;; Making records
+
+(defun durand-eww-bookmark-make-record ()
+ "Return a bookmark record for the current page."
+ (cond
+ ((not (derived-mode-p 'eww-mode))
+ (user-error "Making an EWW bookmark for a non-EWW buffer")))
+ (let* ((url (plist-get eww-data :url))
+ (title (format "(EWW) %s" (plist-get eww-data :title)))
+ (position (point))
+ (defaults (delq nil (list 'defaults title url))))
+ (cond
+ ((null url) (user-error "No link for the current page")))
+ (append
+ (list
+ title
+ (cons 'location url)
+ (cons 'handler #'durand-eww-bookmark-jump)
+ defaults)
+ (bookmark-make-record-default 'no-file nil position))))
+
+;; Copied from Protesilaos' dotemacs
+(defun durand-eww-set-bookmark-record-function ()
+ "Set appropriate `bookmark-make-record-function'.
+Intended for use with `eww-mode-hook'."
+ (setq-local
+ bookmark-make-record-function #'durand-eww-bookmark-make-record))
+
+(add-hook 'eww-mode-hook #'durand-eww-set-bookmark-record-function)
+
+;;;; Jumping
+
+;; NOTE: It works with jumping in another window.
+
+;;;###autoload
+(defun durand-eww-bookmark-jump (bookmark)
+ "Jump to BOOKMARK in EWW.
+This is intended to be the handler for bookmark records created
+by `durand-eww-bookmark-make-record'.
+
+If there is already a buffer visiting the URL of the bookmark,
+simply jump to that buffer and try to restore the point there.
+Otherwise, fetch URL and afterwards try to restore the point."
+ (let ((handler (bookmark-get-handler bookmark))
+ (location (bookmark-prop-get bookmark 'location))
+ (front (cons 'front-context-string
+ (bookmark-get-front-context-string bookmark)))
+ (rear (cons 'rear-context-string
+ (bookmark-get-rear-context-string bookmark)))
+ (eww-buffers
+ (delq
+ nil
+ (mapcar
+ (lambda (buffer)
+ (cond
+ ((provided-mode-derived-p
+ (buffer-local-value
+ 'major-mode buffer)
+ 'eww-mode)
+ buffer)))
+ (buffer-list))))
+ buffer)
+ (cond
+ ((and (stringp location)
+ (not (string= location ""))
+ (eq handler #'durand-eww-bookmark-jump))
+ (let (reuse-p)
+ (mapc
+ (lambda (temp-buffer)
+ (cond
+ ((string=
+ (plist-get
+ (buffer-local-value 'eww-data temp-buffer)
+ :url)
+ location)
+ (setq reuse-p temp-buffer)
+ (setq buffer temp-buffer))))
+ eww-buffers)
+ ;; Don't switch to that buffer, otherwise it will cause
+ ;; problems if we want to open the bookmark in another window.
+ (cond
+ (reuse-p
+ (bookmark-default-handler
+ (list "" (cons 'buffer buffer) front rear)))
+ ;; eww will pop the buffer, so we manually do the jobs: the
+ ;; codes are adapted from the codes for `eww'.
+
+ ;; the buffer will be renamed afterwards, so it does not
+ ;; matter here
+ ((let ((temp-buffer (generate-new-buffer "*eww*")))
+ (setq buffer temp-buffer)
+ (set-buffer temp-buffer)
+ (with-current-buffer temp-buffer
+ (eww-setup-buffer)
+ ;; Check whether the domain only uses "Highly
+ ;; Restricted" Unicode IDNA characters. If not,
+ ;; transform to punycode to indicate that there may be
+ ;; funny business going on.
+ (let ((parsed (url-generic-parse-url location)))
+ (when (url-host parsed)
+ (unless (puny-highly-restrictive-domain-p
+ (url-host parsed))
+ (setf (url-host parsed)
+ (puny-encode-domain (url-host parsed)))))
+ ;; When the URL is on the form "http://a/../../../g",
+ ;; chop off all the leading "/.."s.
+ (when (url-filename parsed)
+ (while (string-match
+ "\\`/[.][.]/" (url-filename parsed))
+ (setf (url-filename parsed)
+ (substring (url-filename parsed) 3))))
+ (setq location (url-recreate-url parsed)))
+ (plist-put eww-data :url location)
+ (plist-put eww-data :title "")
+ (eww-update-header-line-format)
+ (let ((inhibit-read-only t))
+ (insert (format "Loading %s..." location))
+ (goto-char (point-min)))
+ (let ((url-mime-accept-string
+ eww-accept-content-types))
+ (eww-retrieve
+ location #'eww-render
+ (list location nil (current-buffer)))
+ ;; Now the buffer is setup, we shall try to restore
+ ;; the point. But the buffer might not be ready yet,
+ ;; so we use the render hook for this purpose.
+ (add-hook
+ 'eww-after-render-hook
+ (defun durand-eww-bookmark-restore-point-hook ()
+ "Restore the point after render."
+ (remove-hook
+ 'eww-after-render-hook
+ #'durand-eww-bookmark-restore-point-hook)
+ (bookmark-default-handler
+ (list
+ "" (cons 'buffer buffer) front rear)))))))))))
+ ((user-error "Cannot jump to this bookmark")))))
+
(provide 'eww-conf)
;;; eww-conf.el ends here