summaryrefslogtreecommitdiffhomepage
path: root/custom/jao-custom-eww.el
diff options
context:
space:
mode:
Diffstat (limited to 'custom/jao-custom-eww.el')
-rw-r--r--custom/jao-custom-eww.el272
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)