From d81469b7d7fd979236badafbdf0b04c6c876e3f1 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Wed, 15 Sep 2021 17:09:52 +0800 Subject: EWW: integrate with the built-in bookmark framework * bookmark-conf.el (blist-eww-p): Group EWW bookmarks together. * eww-conf.el (durand-eww-bookmark-make-record) (durand-eww-set-bookmark-record-function, eww-mode-hook): Make records for EWW buffers. (durand-eww-bookmark-jump): Jump to EWW bookmarks. --- bookmark-conf.el | 13 +++-- eww-conf.el | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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 -- cgit v1.2.3-18-g5258