From fe65975b419b8142961b2301cffe86f2b95c99fa Mon Sep 17 00:00:00 2001 From: JSDurand Date: Tue, 20 Apr 2021 09:03:43 +0800 Subject: Adaptation of prot-eww * eww-conf.el (eww): (eww-search-prefix): (global-map): (durand-eww-map): (eww-link-keymap): (eww-mode-map): (dired-mode-map): (eww-buffers-mode-map): (eww-bookmark-mode-map): (shr-use-colors): (shr-use-fonts): (shr-max-image-proportion): (shr-image-animate): (shr-width): (shr-discard-aria-hidden): (shr-cookie-policy): (eww-name-separator): (eww-rename-buffer): (eww-after-render-hook): (eww-back-url): (eww-forward-url): (eww-visited-history): (eww-record-history): (eww-dwim): (eww-visit-bookmark): (eww-visit-url-on-page): (eww-jump-to-url-on-page): (eww-occur-feed-regexp): (eww-find-feed): * view-conf.el (durand-view-map): (durand-open-targets): --- eww-conf.el | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- view-conf.el | 11 +-- 2 files changed, 227 insertions(+), 5 deletions(-) diff --git a/eww-conf.el b/eww-conf.el index 5e21db1..d3f3173 100644 --- a/eww-conf.el +++ b/eww-conf.el @@ -10,12 +10,49 @@ ;;; Code: (require 'eww) +(require 'shr) (setq eww-bookmarks-directory load-file-directory) (setq eww-search-prefix "https://searx.lukesmith.xyz/search?q=") +(setq eww-restore-desktop t) +(setq eww-desktop-remove-duplicates t) +(setq eww-suggest-uris '(eww-links-at-point thing-at-point-url-at-point)) +(setq eww-browse-url-new-window-is-tab nil) -;; This feels much quicker +;; key-bindings + +(define-key global-map (vector ?\s-w) #'durand-eww-map) + +;;;###autoload +(fset 'durand-eww-map + (let ((map (list 'keymap "EWW"))) + (define-key map (vector ?b) #'eww-visit-bookmark) + (define-key map (vector ?e) #'eww-dwim) + map)) + +(define-key eww-link-keymap (kbd "v") nil) ; stop overriding `eww-view-source' +(define-key eww-mode-map (kbd "L") #'eww-list-bookmarks) +(define-key eww-mode-map (vector ?f) #'eww-find-feed) +(define-key eww-mode-map (vector ?b) #'eww-visit-bookmark) +(define-key eww-mode-map (vector ?e) #'eww-dwim) +(define-key eww-mode-map (vector ?o) #'eww-open-in-new-buffer) +(define-key eww-mode-map (vector ?E) #'eww-visit-url-on-page) +(define-key eww-mode-map (vector ?J) #'eww-jump-to-url-on-page) +(define-key eww-mode-map (vector ?m) #'eww-add-bookmark) +(define-key dired-mode-map (kbd "E") #'eww-open-file) ; to render local HTML files +(define-key eww-buffers-mode-map (kbd "d") #'eww-bookmark-kill) ; it actually deletes +(define-key eww-bookmark-mode-map (kbd "d") #'eww-bookmark-kill) ; same + +(setq shr-use-colors nil) ; t is bad for accessibility +(setq shr-use-fonts nil) ; t is not for me +(setq shr-max-image-proportion 0.6) +(setq shr-image-animate nil) ; No GIFs, thank you! +(setq shr-width nil) ; check `prot-eww-readable' +(setq shr-discard-aria-hidden t) +(setq shr-cookie-policy nil) + +;; This feels quicker. (cond ((version<= "28" emacs-version)) ((setq eww-retrieve-command '("wget" "--quiet" "--output-document=-")))) @@ -34,6 +71,188 @@ Otherwise, just go to the beginning of the page." ((goto-char (point-min))))) (recenter 0)) +;;; the following are adapted from Protesilaos' dotemacs. + +;;;###autoload +(defconst eww-name-separator "-" + "The separator between the title and the mark EWW in the \ +names.") + +;;;###autoload +(defun eww-rename-buffer () + "Rename EWW buffer using page title or URL. +To be used by `eww-after-render-hook'." + (let ((name (cond + ((and (plist-get eww-data :title) + (not (string= (plist-get eww-data :title) ""))) + (plist-get eww-data :title)) + ((plist-get eww-data :url))))) + (rename-buffer (format "*%s %s eww*" name eww-name-separator) t))) + +(add-hook 'eww-after-render-hook #'eww-rename-buffer) +(advice-add 'eww-back-url :after #'eww-rename-buffer) +(advice-add 'eww-forward-url :after #'eww-rename-buffer) + +;;;###autoload +(defvar eww-visited-history nil + "History of visited URLs.") + +;;;###autoload +(defun eww-record-history () + "Store URL in `eww-visited-history'. +To be used by `eww-after-render-hook'." + (add-to-history 'eww-visited-history (plist-get eww-data :url))) + +(add-hook 'eww-after-render-hook #'eww-record-history) +(advice-add 'eww-back-url :after #'eww-record-history) +(advice-add 'eww-forward-url :after #'eww-record-history) + +;;;; Commands + +;;;###autoload +(defun eww-dwim (url &optional arg) + "Visit a URL, maybe from `eww-prompt-history', with completion. +With optional prefix ARG (\\[universal-argument]) open URL in a +new eww buffer. +If URL does not look like a valid link, run a web query using +`eww-search-prefix'. +When called from an eww buffer, provide the current link as +default candidate." + (interactive + (list + (completing-read "Run EWW on: " + (delete-dups (append eww-visited-history eww-prompt-history)) + nil nil nil 'eww-prompt-history (plist-get eww-data :url) t) + current-prefix-arg)) + (eww url (cond (arg 4)))) + +;;;###autoload +(defun eww-visit-bookmark (&optional arg) + "Visit bookmarked URL. +With optional prefix ARG (\\[universal-argument]) open URL in a +new EWW buffer." + (interactive "P") + (eww-read-bookmarks) + (let ((candidates (mapcar + (lambda (element) + (plist-get element :url)) + eww-bookmarks))) + (eww (completing-read "Visit EWW bookmark: " candidates) + (cond (arg 4))))) + +;;;###autoload +(defun eww-visit-url-on-page (&optional arg) + "Visit URL from list of links on the page using completion. +With optional prefix ARG (\\[universal-argument]) open URL in a +new EWW buffer." + (interactive "P") + (cond + ((derived-mode-p 'eww-mode) + (let (links) + (save-excursion + (goto-char (point-max)) + (while (text-property-search-backward 'shr-url nil nil t) + (cond + ((and (get-text-property (point) 'shr-url) + (not (get-text-property (point) 'eww-form))) + (setq links + (cons (format "%s @ %s" + (button-label (point)) + (propertize (get-text-property (point) 'shr-url) 'face 'link)) + links)))))) + (let* ((selection (completing-read "Browse URL from page: " links nil t)) + (match-ending (progn (string-match " @ " selection) + (match-end 0))) + (url (substring-no-properties selection match-ending))) + (eww url (cond (arg 4)))))))) + +;;;###autoload +(defun eww-jump-to-url-on-page () + "Jump to URL position on the page using completion. +With optional prefix ARG (\\[universal-argument]) open URL in a +new EWW buffer." + (interactive) + (cond + ((derived-mode-p 'eww-mode) + (let ((links)) + (save-excursion + (goto-char (point-max)) + (while (text-property-search-backward 'shr-url nil nil t) + (cond + ((and (get-text-property (point) 'shr-url) + (not (get-text-property (point) 'eww-form))) + (setq links + (cons (format "%s @ %s ~ %d" + (button-label (point)) + (propertize (get-text-property (point) 'shr-url) 'face 'link) + (point)) + links)))))) + (let* ((selection (completing-read "Jump to URL on page: " links nil t)) + (match-ending (progn (string-match " ~ " selection) + (match-end 0))) + (position (string-to-number + (substring-no-properties selection match-ending)))) + (goto-char position) + (durand-pulse-pulse-line)))))) + +(defvar eww-occur-feed-regexp + (concat "\\(rss\\|atom\\)\\+xml.\\(.\\|\n\\)" + ".*href=[\"']\\(.*?\\)[\"']") + "Regular expression to match web feeds in HTML source.") + +;;;###autoload +(defun eww-find-feed () + "Produce bespoke buffer with RSS/Atom links from XML source." + (interactive) + (let* ((url (or (plist-get eww-data :start) + (plist-get eww-data :contents) + (plist-get eww-data :home) + (plist-get eww-data :url))) + (title (or (plist-get eww-data :title) url)) + (source (plist-get eww-data :source)) + (buf-name (format "*feeds: %s %s eww*" title + eww-name-separator)) + (inhibit-read-only t) + (base-url (replace-regexp-in-string "\\(.*/\\)[^/]+\\'" "\\1" url))) + (cond + (source + (with-temp-buffer + (insert source) + (occur-1 eww-occur-feed-regexp "\\3" (list (current-buffer)) buf-name)) + ;; Comment by Protesilaos: + ;; Handle relative URLs, so that we get an absolute URL out of them. + ;; Findings like "rss.xml" are not particularly helpful. + ;; + ;; NOTE 2021-03-31: the base-url heuristic may not always be + ;; correct, though it has worked in all websites I have tested it + ;; in. + (cond + ((get-buffer buf-name) + (with-current-buffer (get-buffer buf-name) + (goto-char (point-min)) + (cond + ((re-search-forward browse-url-button-regexp nil t)) + ((re-search-forward ".*" nil t) + (replace-match (concat base-url "\\&")))))))) + (t + ;; Sometimes a page has no sources + (let ((nodes (dom-search + (plist-get eww-data :dom) + (lambda (node) + (and + (eq (dom-tag node) 'link) + (dom-attr node 'type) + (string-match "\\(?:rss\\|atom\\)\\+xml" + (dom-attr node 'type))))))) + (with-current-buffer (get-buffer-create buf-name) + (mapc (lambda (node) + (insert (dom-attr node 'title) + " - " + (dom-attr node 'href) + "\n")) + nodes)) + (display-buffer (get-buffer buf-name))))))) + (provide 'eww-conf) ;;; eww-conf.el ends here diff --git a/view-conf.el b/view-conf.el index 8556eff..65f5d9f 100644 --- a/view-conf.el +++ b/view-conf.el @@ -106,6 +106,7 @@ If ARG is '(16), view the battery information." (define-key map (vector ?c) #'calendar) (define-key map (vector ?r) #'choose-recent-file) (define-key map (vector ?n) #'novel) + (define-key map (vector ?w) #'durand-eww-map) map) "The keymap that is related to my custom functions about viewing.") ;;; Hyper key @@ -127,10 +128,12 @@ If ARG is '(16), view the battery information." ;;;###autoload (defvar durand-open-targets - (list (list "Safari" "open" "-a" "Safari" (list "https://www.youtube.com" - "https://www.gmail.com" - "https://www.facebook.com" - "https://protesilaos.com")) + (list (list "Safari" "open" "-a" "Safari" + (list "https://www.youtube.com" + "https://www.gmail.com" + "https://www.facebook.com" + "https://protesilaos.com" + "https://wmail1.cc.ntu.edu.tw/index.php?url=https%3A%2F%2Fwmail1.cc.ntu.edu.tw%2F")) (list "Terminal" "open" "-a" "Terminal" (list "/Users/durand/Desktop/Centre/Vidéos/" "/Users/durand/Desktop/Centre/Musique/" -- cgit v1.2.3-18-g5258