dotfiles/emacs/.emacs.d/config/init-eww.el

161 lines
7.5 KiB
EmacsLisp

;; -*- lexical-binding: t; -*-
(use-package eww
:straight (:type built-in)
:config
(defun eww-before-advice (&rest args)
(interactive
(let* ((uris (eww-suggested-uris))
(browser-history (mapcar (lambda (h) (plist-get h :url)) eww-history))
(bookmarks (mapcar (lambda (b) (plist-get b :url)) eww-bookmarks))
(suggestions (delete-dups (append uris eww-prompt-history browser-history)))
(current-uri (plist-get eww-data :url)))
(list (completing-read "URL or keywords: " suggestions nil nil current-uri 'eww-prompt-history)
current-prefix-arg))))
(advice-add 'eww :before #'eww-before-advice)
(defun eww-rename-buffer-to-title ()
(rename-buffer (format "*eww: %s*" (plist-get eww-data :title)) t))
(add-hook 'eww-after-render-hook #'eww-rename-buffer-to-title)
;; Copied from https://protesilaos.com/emacs/dotemacs#h:abc20037-7a4f-4555-809a-dc4165c5db6a
(defun eww-capture-urls-on-page (&optional position)
"Capture all the links on the current web page.
Return a list of strings. Strings are in the form LABEL @ URL.
When optional argument POSITION is non-nil, include position info
in the strings too, so strings take the form
LABEL @ URL ~ POSITION."
(let (links match)
(save-excursion
(goto-char (point-max))
;; NOTE 2021-07-25: The first clause in the `or' is meant to
;; address a bug where if a URL is in `point-min' it does not get
;; captured.
(while (setq match (text-property-search-backward 'shr-url))
(let* ((raw-url (prop-match-value match))
(start-point-prop (prop-match-beginning match))
(end-point-prop (prop-match-end match))
(url (when (stringp raw-url)
(propertize raw-url 'face 'link)))
(label (replace-regexp-in-string "\n" " " ; NOTE 2021-07-25: newlines break completion
(buffer-substring-no-properties
start-point-prop end-point-prop)))
(point start-point-prop)
(line (line-number-at-pos point t))
(column (save-excursion (goto-char point) (current-column)))
(coordinates (propertize
(format "%d,%d (%d)" line column point)
'face 'shadow)))
(when url
(if position
(push (format "%-15s ~ %s @ %s"
coordinates label url)
links)
(push (format "%s @ %s"
label url)
links))))))
links))
(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")
(when (derived-mode-p 'eww-mode)
(let* ((links (eww-capture-urls-on-page))
(selection (completing-read "Browse URL: " links nil t))
(url (replace-regexp-in-string ".*@ " "" selection)))
(eww url (when arg 4)))))
(defun eww-jump-to-url-on-page (&optional arg)
"Jump to URL position on the page using completion."
(interactive "P")
(when (derived-mode-p 'eww-mode)
(let* ((links (eww-capture-urls-on-page t))
(prompt (format "Jump to URL: "))
(selection (completing-read prompt links nil t))
(position (replace-regexp-in-string "^.*(\\([0-9]+\\))[\s\t]+~" "\\1" selection))
(point (string-to-number position)))
(goto-char point))))
(defun eww-visit-bookmark (bookmark &optional arg)
"Visit BOOKMARK in EWW."
(interactive (list (let* ((bookmarks (mapcar (lambda (b)
(cons (format "%s | %s"
(plist-get b :title)
(plist-get b :url))
(plist-get b :url)))
eww-bookmarks))
(bookmark (completing-read "Bookmark: " bookmarks)))
(cdr (assoc bookmark bookmarks)))
current-prefix-arg))
(eww bookmark arg))
;; Don't try to render SVGs, for some reason they are not rendered correctly
(add-to-list 'shr-external-rendering-functions
'(svg . ignore))
;; https://github.com/alphapapa/unpackaged.el/commit/3b46f9c0e0195d78df8c4ca6e1953b69539e2844
(defun imenu-eww-headings ()
"Return alist of HTML headings in current EWW buffer for Imenu.
Suitable for `imenu-create-index-function'."
(let ((faces '(shr-h1 shr-h2 shr-h3 shr-h4 shr-h5 shr-h6 shr-heading)))
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(cl-loop for next-pos = (next-single-property-change (point) 'face)
while next-pos
do (goto-char next-pos)
for face = (get-text-property (point) 'face)
when (cl-typecase face
(list (cl-intersection face faces))
(symbol (member face faces)))
collect (cons (buffer-substring (point-at-bol) (point-at-eol)) (point))
and do (forward-line 1))))))
(add-hook 'eww-mode-hook
(lambda ()
(setq-local imenu-create-index-function #'imenu-eww-headings)))
:general
(leader-map "E" #'eww)
(normal eww-mode-map
"go" #'eww
"gb" #'eww-visit-bookmark
"gB" #'eww-list-bookmarks
"gJ"#'eww-jump-to-url-on-page
"gV" #'eww-visit-url-on-page))
(use-package shr-tag-pre-highlight
:ensure t
:after shr
:config
(add-to-list 'shr-external-rendering-functions
'(pre . shr-tag-pre-highlight)))
(use-package browse-url
:straight (:type built-in)
:config
(defun browse-url-or-search (url-or-symbol)
"If URL-OR-SYMBOL is a URL, browse it. Otherwise, search for it."
(interactive (list (thing-at-point 'symbol)))
(if (ffap-url-p url-or-symbol)
(browse-url url-or-symbol)
(browse-url (format "https://www.google.com/search?q=%s" url-or-symbol))))
:custom
(browse-url-browser-function 'eww-browse-url)
(browse-url-handlers '(("\\`https?://docs.aws.amazon.com" . browse-url-default-browser)
("\\`https?://github.com" . browse-url-default-browser)
("\\`https?://.*.console.aws.amazon.com" . browse-url-default-browser))))
(use-package webjump
:straight (:type built-in)
:init
(defalias 'web-search #'webjump)
:general
(leader-map "S" #'web-search)
:custom
(webjump-sites '(("Emacs Wiki" . [simple-query "www.emacswiki.org" "www.emacswiki.org/cgi-bin/wiki/" ""])
("DuckDuckGo" . [simple-query "duckduckgo.com" "duckduckgo.com/?q=" ""])
("Wikipedia" . [simple-query "wikipedia.org" "https://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s" ""])
("Google" . [simple-query "google.com" "https://www.google.com/search?ie=utf-8&oe=utf-8&q=" ""])
("StackOverflow" . [simple-query "stackoverflow.com" "https://stackoverflow.com/search?q=" ""])
("AWS Docs" . [simple-query "docs.aws.amazon.com" "https://docs.aws.amazon.com/search/doc-search.html?searchPath=documentation&searchQuery=" ""]))))
(provide 'init-eww)