eww-hacks/eww-hacks.el

230 lines
8.6 KiB
EmacsLisp
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; eww-hacks.el --- Hacks of doubtful provenance for eww -*- lexical-binding: t; -*-
;;
;; Author: rahguzar <rahguzar@zohomail.eu>
;; Maintainer: rahguzar <rahguzar@zohomail.eu>
;; Created: October 16, 2023
;; Version: 0.0.1
;; Keywords: comm eww convenience multimedia
;; Homepage: https://codeberg.org/rahguzar/eww-hacks
;; Package-Requires: ((emacs "29.1"))
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;; Hacks to make eww a better experience on some pages. For now these include
;; wikipedia especially its math pages, theurdudictionary.com and documentation
;; from dash docs.
;;
;; It requires shr and eww with the patches in
;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-10/msg01609.html
;; applied.
;;
;; To use these hacks require this package from your init file.
;;
;;; Code:
(require 'eww)
(require 'shr)
(require 'tex-mode)
(require 'tex-fold)
;;; Hacks to alter shr rendering
(defvar eww-hacks--d-outline-level 6)
(defun eww-hacks-tag-dl (dom)
"DOM."
(let ((eww-hacks--d-outline-level (1+ eww-hacks--d-outline-level))
(fun (lambda (prefix) (concat prefix " ")))
(start (point)))
(shr-tag-dl dom)
(alter-text-property start (point) 'line-prefix fun)
(alter-text-property start (point) 'wrap-prefix fun)))
(defun eww-hacks-tag-dt (dom)
"DOM."
(shr-ensure-newline)
(let ((start (point)))
(shr-generic dom)
(put-text-property
start (point) outline-level eww-hacks--d-outline-level)
(put-text-property start (point)
'outline-level eww-hacks--d-outline-level)
(add-face-text-property start (point) 'bold t))
(shr-ensure-newline))
(push '(dl . eww-hacks-tag-dl) shr-external-rendering-functions)
(push '(dt . eww-hacks-tag-dt) shr-external-rendering-functions)
(defvar eww-hacks-class-face-alist
'(("highlight" . org-block)
("mw-highlight" . org-block)
("warning" . font-lock-warning-face)
("admonition-title" . bold)
("gp" . comint-highlight-prompt)
("kn" . font-lock-keyword-face)
("kr" . font-lock-keyword-face)
("kt" . font-lock-type-face)
("nb" . font-lock-builtin-face)
("nn" . font-lock-function-name-face)
("nf" . font-lock-function-name-face)
("o" . font-lock-operator-face)
("ow" . font-lock-operator-face)
("p" . font-lock-punctuation-face)
("mi" . font-lock-number-face)
("c1" . font-lock-comment-face)
("s1" . font-lock-string-face)
("sig-prename descclassname" . font-lock-function-name-face)
("sig-name descname" . font-lock-type-face))
"An alist of (CLASS . FACE).
If a div or span tag has class attribute, FACE is applied to its rendering.")
(defvar eww-hacks-class-function-alist
'(("math" . eww-hacks-fold-math))
"Alist of (CLASS . FUNCTION).
If a div or span tag has class attribute, FUNCTION is called with the rendered
string as its argument. It should return a string which is then inserted in
place of the original string.")
(defvar eww-hacks--tex-buffer nil)
(defun eww-hacks-string-match (needle haystack)
"Return non-nil if NEEDLE is a word in string HAYSTACK."
(string-match (rx (or bos " ") (literal needle) (or eos " "))
haystack))
(defun eww-hacks-tag-span (dom)
"DOM."
(let ((start (point))
(face (alist-get (or (dom-attr dom 'class) "")
eww-hacks-class-face-alist
nil t #'eww-hacks-string-match)))
(shr-tag-span dom)
(when-let ((fun (alist-get (or (dom-attr dom 'class) "")
eww-hacks-class-function-alist
nil t #'eww-hacks-string-match)))
(insert (funcall fun (delete-and-extract-region start (point)))))
(when face (add-face-text-property start (point) face))))
(defun eww-hacks-tag-div (dom)
"DOM."
(let ((start (point))
(face (alist-get (or (dom-attr dom 'class) "")
eww-hacks-class-face-alist
nil t #'eww-hacks-string-match)))
(shr-tag-div dom)
(when-let ((fun (alist-get (or (dom-attr dom 'class) "")
eww-hacks-class-function-alist
nil t #'eww-hacks-string-match)))
(insert (funcall fun (delete-and-extract-region start (point)))))
(when face (add-face-text-property start (point) face))))
(push '(div . eww-hacks-tag-div) shr-external-rendering-functions)
(push '(span . eww-hacks-tag-span) shr-external-rendering-functions)
(defun eww-hacks-fold-math (str)
"Get a nicer representation of math string STR.
Uses `tex-fold-mode' and `prettify-symbols-mode'."
(unless (buffer-live-p " *eww-hacks-math*")
(with-current-buffer (get-buffer-create " *eww-hacks-math*" t)
(setq-local prettify-symbols-alist tex--prettify-symbols-alist)
(push '("\\qquad" . ?) prettify-symbols-alist)
(push '("\\quad" . ?) prettify-symbols-alist)
(make-local-variable 'TeX-fold-math-spec-list)
(push `(,(lambda (str) (propertize str 'face 'shr-text)) ("text"))
TeX-fold-math-spec-list)
(tex-fold-mode)
(prettify-symbols-mode)))
(with-current-buffer " *eww-hacks-math*"
(erase-buffer)
(insert (replace-regexp-in-string (rx "\\" (or ?\( ?\) ?\[ ?\])) "" str))
(insert "\n")
(TeX-fold-buffer)
(font-lock-ensure)
(TeX-fold-buffer-substring (point-min) (1- (point-max)))))
;;; Hacks to make some website better using shrface provided features
(require 'outline)
(defvar eww-hacks-url-prettify-list
`((,(rx any) outline-minor-mode)
(,(rx "wikipedia.org/wiki/")
eww-hacks-cleanup-wikipedia
outline-show-only-headings)
(,(rx (or "https://doc.sagemath.org/html/"
(and "file:///"
(eval (expand-file-name "~/.local/share/dashdocs/Sage")))))
eww-hacks-delete-till-first-heading
outline-show-only-headings)
(,(rx "https://theurdudictionary.com/?q=")
eww-hacks-delete-till-first-heading))
"A list of (REGEX . FUNCTIONS).
REGEX is a regular expression and FUNCTIONS is a list of functions.
If the current url matches REGEX, FUNCTIONS are run after rendering.
More precisely the are run by a hook in `eww-after-render-hook'.
The FUNCTIONS are run with `inhibit-read-only' bound to t so the buffer
can be freely modified.")
(add-hook 'eww-after-render-hook #'eww-hacks-prettify)
(defun eww-hacks-prettify ()
"Prettify using the rules in `eww-hacks-url-prettify-list'."
(setq-local outline-minor-mode-highlight nil)
(save-excursion
(let ((url (eww-current-url))
(inhibit-read-only t))
(pcase-dolist (`(,rx . ,funs) eww-hacks-url-prettify-list)
(when (string-match rx url)
(dolist (fun funs)
(funcall fun)))))))
(defun eww-hacks-delete-till-first-heading ()
"Delete everything till first heading. Useful for e.g. wikipedia."
(goto-char (point-min))
(outline-next-heading)
(while (and (> (funcall outline-level) 1) (not (eobp)))
(outline-next-heading))
(unless (eobp)
(delete-region (point-min) (pos-bol))))
(defvar eww-hacks-wikipedia-history nil)
(defvar savehist-additional-variables)
(cl-pushnew 'eww-hacks-wikipedia-history savehist-additional-variables)
(defun eww-hacks-cleanup-wikipedia ()
"Delete everything till first heading for a wikipedi page.
Also remove the table of contents."
(eww-hacks-delete-till-first-heading)
(let ((start (pos-eol))
(url (eww-current-url)))
(when (search-forward "From Wikipedia, the free encyclopedia" nil t)
(delete-region start (pos-eol)))
(when (string-match (rx "wikipedia.org/wiki/" (group (* any))) url)
(add-to-history 'eww-hacks-wikipedia-history
(url-unhex-string (match-string 1 url))))))
;;; Functions to get some web pages
;;;###autoload
(defun eww-hacks-wikipedia-article (query)
"Get Wikipedia article for QUERY."
(interactive (list (completing-read "Wikipedia: " eww-hacks-wikipedia-history
nil nil nil
(if (region-active-p)
(funcall region-extract-function)
(word-at-point)))))
(eww (format "https://en.wikipedia.org/wiki/%s" query)) )
;;;###autoload
(defun eww-hacks-urdu-lookup-word (word)
"Look up WORD in theurdudictionary.com ."
(interactive (list (if (or (eq (current-bidi-paragraph-direction) 'right-to-left)
current-prefix-arg)
(read-string "Word to translate to Urdu: ")
(if (region-active-p)
(funcall region-extract-function)
(word-at-point)))))
(eww (format "https://theurdudictionary.com/?q=%s" word)))
(provide 'eww-hacks)
;;; eww-hacks.el ends here