diff options
Diffstat (limited to 'custom/jao-custom-eww.el')
-rw-r--r-- | custom/jao-custom-eww.el | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/custom/jao-custom-eww.el b/custom/jao-custom-eww.el new file mode 100644 index 0000000..0409fc5 --- /dev/null +++ b/custom/jao-custom-eww.el @@ -0,0 +1,272 @@ +;; -*- lexical-binding: t -*- + +;;; integration with browse-url and afio +(defun jao-eww-browse-url (url &rest _r) + "Browse URL using eww." + (if (derived-mode-p 'eww-mode) + (eww url) + (jao-afio-goto-www) + (select-window (frame-first-window)) + (let* ((url (url-encode-url url)) + (bf (seq-find `(lambda (b) + (with-current-buffer b + (string= ,url + (url-encode-url (eww-current-url))))) + (jao-eww-session-eww-buffers)))) + (cond (bf (switch-to-buffer bf)) + ((string-match-p url "^file://") (eww-open-file url)) + (t (eww url 4)))))) + +(setq jao-browse-url-function #'jao-eww-browse-url) +(setq eww-use-browse-url "^\\(gemini\\|gopher\\):") + +;;; multipart html renderer +(defun jao-shr-html-renderer (handle) + (let ((fill-column nil) + (shr-width 150) + (shr-max-width 150)) + (mm-shr handle))) + +(setq mm-text-html-renderer #'jao-shr-html-renderer) + +;;; opening URLs +(defun jao-eww-copy-link () + (interactive) + (when-let (lnk (or (car (eww-links-at-point)) (eww-current-url))) + (message "%s" lnk) + (kill-new lnk))) + +(defun jao-eww-browse (arg) + (interactive "P" eww-mode) + (setq eww-prompt-history + (cl-remove-duplicates eww-prompt-history :test #'string=)) + (let ((url (completing-read (if arg "eww in new buffer: " "eww: ") + eww-prompt-history nil nil nil + 'eww-prompt-history (eww-current-url)))) + (eww url (when arg 4)))) + +(defun jao-eww-browse-new () + (interactive nil eww-mode) + (jao-eww-browse t)) + +(defun jao-eww-reload (images) + (interactive "P" eww-mode) + (if images + (let ((shr-blocked-images nil)) + (eww-reload t)) + (call-interactively 'eww-reload))) + +;;; consult narrowing +(with-eval-after-load "consult" + (defvar jao-eww-consult-history nil) + (defvar jao-eww-buffer-source + (list :name "eww buffer" + :category 'eww-buffer + :hidden t + :narrow (cons ?e "eww") + :annotate (lambda (c) (get-text-property 0 'url c)) + :history 'jao-eww-consult-history + :action (lambda (b) + (jao-afio-goto-www) + (switch-to-buffer (get-text-property 0 'buffer b))) + :items + (lambda () + (seq-map (lambda (b) + (with-current-buffer b + (let ((tl (or (plist-get eww-data :title) "")) + (url (or (eww-current-url) (buffer-name)))) + (propertize (if (string-blank-p tl) url tl) + 'buffer b 'url url)))) + (seq-filter #'jao-www--buffer-p (buffer-list)))))) + (jao-consult-add-buffer-source 'jao-eww-buffer-source)) + +;;; images +(defun jao-eww-next-image () + (interactive nil eww-mode) + (when-let (p (text-property-search-forward 'image-displayer nil nil t)) + (goto-char (prop-match-beginning p)))) + +;;; close page and reopen +(defvar jao-eww--closed-urls ()) + +(defun jao-eww-close () + (interactive nil eww-mode) + (when-let (current (eww-current-url)) + (add-to-list 'jao-eww--closed-urls current)) + (let ((nxt (car (jao-eww-session-invisible-buffers)))) + (kill-current-buffer) + (when nxt (switch-to-buffer nxt nil t)))) + +(defun jao-eww-reopen (arg) + (interactive "P") + (if (> (length jao-eww--closed-urls) 0) + (let ((url (completing-read "URL: " jao-eww--closed-urls))) + (jao-afio-goto-www) + (setq jao-eww--closed-urls (remove url jao-eww--closed-urls)) + (eww url (when arg 4))) + (message "No previously closed URLs."))) + +(defun jao-eww-reopen-new () + (interactive) + (jao-eww-reopen t)) + +;;; sessions +(use-package jao-eww-session + :custom ((jao-eww-session-file "~/.emacs.d/cache/eww-session.eld"))) + +;;; eww to org +(defun jao-eww-to-org (&optional dest) + (interactive) + (unless (org-region-active-p) + (let ((shr-width 80)) (eww-readable))) + (let* ((start (if (org-region-active-p) (region-beginning) (point-min))) + (end (if (org-region-active-p) (region-end) (point-max))) + (buff (or dest (generate-new-buffer "*eww-to-org*"))) + (link (eww-current-url)) + (title (or (plist-get eww-data :title) ""))) + (with-current-buffer buff + (insert "#+title: " title "\n#+link: " link "\n\n") + (org-mode)) + (save-excursion + (goto-char start) + (while (< (point) end) + (let* ((p (point)) + (props (text-properties-at p)) + (k (seq-find (lambda (x) (plist-get props x)) + '(shr-url image-url outline-level face))) + (prop (and k (list k (plist-get props k)))) + (next (if prop + (next-single-property-change p (car prop) nil end) + (next-property-change p nil end))) + (txt (buffer-substring (point) next)) + (txt (replace-regexp-in-string "\\*" "·" txt))) + (with-current-buffer buff + (insert + (pcase prop + ((and (or `(shr-url ,url) `(image-url ,url)) + (guard (string-match-p "^http" url))) + (let ((tt (replace-regexp-in-string "\n\\([^$]\\)" " \\1" txt))) + (org-link-make-string url tt))) + (`(outline-level ,n) + (concat (make-string (- (* 2 n) 1) ?*) " " txt "\n")) + ('(face italic) (format "/%s/ " (string-trim txt))) + ('(face bold) (format "*%s* " (string-trim txt))) + (_ txt)))) + (goto-char next)))) + (pop-to-buffer buff) + (goto-char (point-min)))) + +;;; rdrview +;; https://jiewawa.me/2024/04/another-way-of-integrating-mozilla-readability-in-emacs-eww/ +(define-minor-mode eww-rdrview-mode + "Toggle whether to use `rdrview' to make eww buffers more readable." + :lighter " R" + (if eww-rdrview-mode + (progn + (setq eww-retrieve-command '("rdrview" "-T" "title,sitename,body" "-H")) + (add-hook 'eww-after-render-hook #'eww-rdrview-update-title)) + (progn + (setq eww-retrieve-command nil) + (remove-hook 'eww-after-render-hook #'eww-rdrview-update-title)))) + +(defun eww-rdrview-update-title () + "Change title key in `eww-data' with first line of buffer. +It should be the title of the web page as returned by `rdrview'" + (save-excursion + (goto-char (point-min)) + (plist-put eww-data :title (string-trim (thing-at-point 'line t)))) + (eww--after-page-change)) + +(defun eww-rdrview-toggle-and-reload () + "Toggle `eww-rdrview-mode' and reload page in current eww buffer." + (interactive) + (if eww-rdrview-mode (eww-rdrview-mode -1) + (eww-rdrview-mode 1)) + (eww-reload)) +;;; package +(use-package shr + :custom ((shr-width nil) + (shr-use-colors t) + (shr-use-fonts nil) + (shr-max-width 160) + (shr-blocked-images nil) + (shr-inhibit-images t) + (shr-max-image-proportion 0.8) + (shr-hr-line ?―))) + +(use-package eww + :demand t + :custom ((eww-browse-url-new-window-is-tab nil) + (eww-download-directory jao-sink-dir) + (eww-header-line-format " %u") + (eww-form-checkbox-selected-symbol "☒") + (eww-buffer-name-length 180) + (eww-readable-urls '("guardian\\.co\\.uk" + "theguardian\\.com" + "eldiario\\.es" + "theconversation"))) + + :config + (with-eval-after-load "org" (require 'ol-eww nil t)) + + (defun jao-eww-buffer-name () + (when-let ((s (or (plist-get eww-data :title) + (plist-get eww-data :url)))) + (when (not (string-blank-p s)) (format "%s" s)))) + (setq eww-auto-rename-buffer #'jao-eww-buffer-name) + + (defun jao-eww-readable (rdrview) + (interactive "P" eww-mode) + (if rdrview + (eww-rdrview-toggle-and-reload) + (eww-readable))) + + :bind (:map eww-mode-map (("b" . eww-back-url) + ("B" . eww-forward-url) + ("d" . jao-download) + ("f" . link-hint-open-link) + ("F" . embark-on-link) + ("L" . eww-forward-url) + ("N" . jao-eww-next-image) + ("o" . jao-eww-browse) + ("O" . jao-eww-browse-new) + ("r" . jao-eww-reload) + ("R" . jao-eww-readable) + ("s" . eww-search-words) + ("S" . jao-eww-browse-new) + ("T" . jao-mastodon-toot-url) + ("u" . jao-eww-reopen) + ("U" . jao-eww-reopen-new) + ("w" . jao-eww-to-org) + ("q" . jao-eww-close) + ("x" . jao-rss-subscribe) + ("y" . jao-eww-copy-link) + ("\\" . eww-view-source) + ("C-c C-w" . jao-eww-close) + ("M-i" . eww-toggle-images)))) + +;;; fixes for shr image rendering +(require 'shr) + +(defun jao-shr--kill-nl (p) + (save-excursion + (goto-char p) + (when (looking-at-p "\n") (delete-char 1)))) + +(defun jao-shr-tag-img (fn &rest args) + (let ((p (point))) + (prog1 (apply fn args) + (when (> (point) p) (jao-shr--kill-nl p))))) + +(defun jao-shr-insert (fn &rest args) + (let ((p (when (and (not (bolp)) + (get-text-property (1- (point)) 'image-url)) + (point)))) + (prog1 (apply fn args) + (when (and p (> (point) p)) (jao-shr--kill-nl p))))) + +(advice-add 'shr-tag-img :around #'jao-shr-tag-img) +(advice-add 'shr-insert :around #'jao-shr-insert) + +;;; . +(provide 'jao-custom-eww) |