From 71b97e7871ed5eed8e03202daaf8124c3a2b7e1e Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Fri, 20 Jan 2023 13:14:49 -0600 Subject: Add link-hint --- lisp/+link-hint.el | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lisp/acdw-web.el | 73 ++++++++++++++++++++++++++- 2 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 lisp/+link-hint.el (limited to 'lisp') diff --git a/lisp/+link-hint.el b/lisp/+link-hint.el new file mode 100644 index 0000000..469ed15 --- /dev/null +++ b/lisp/+link-hint.el @@ -0,0 +1,146 @@ +;;; +link-hint.el -*- lexical-binding: t; -*- + +;;; Code: + +(require 'cl-lib) +(require 'link-hint) + +(defgroup +link-hint nil + "Extra customizations for `link-hint'." + :group 'link-hint) + +(defcustom +link-hint-open-secondary-types '(gnus-w3m-image-url + gnus-w3m-url + markdown-link + mu4e-attachment + mu4e-url + notmuch-hello + nov-link + org-link + shr-url + text-url + w3m-link + w3m-message-link) + "Link types to define `:open-secondary' for.") + +(defvar +link-hint-map (make-sparse-keymap) + "Keymap for `link-hint' functionality.") + +(cl-defmacro +link-hint-define-keyword (keyword handler docstring + &optional (types 'link-hint-types) + &rest rest + &key multiple &allow-other-keys) + "Set up a `link-hint' KEYWORD, with optional TYPES. +If TYPES is not present, use `link-hint-types'. + +KEYWORD defines the link-hint type. It will be used to create a +function for opening links of the form \"link-hint-openKEYWORD\". + +HANDLER is the function to open a link with. + +DOCSTRING is the macro's documentation. + +Keyword arguments are passed to `link-hint-define-type' prefixed +with the KEYWORD." + (declare (indent 2) + (doc-string 3)) + (let ((types (symbol-value types)) + (func-sym (intern (format "+link-hint-open%s" keyword))) + (mult-sym (intern (format "%s-multiple" keyword))) + (expr)) + ;; Define the type + (push `(dolist (type ',types) + (link-hint-define-type type + ,keyword ,handler + ,@(mapcar (lambda (el) + (if (eq el :multiple) + mult-sym + el)) + rest))) + expr) + ;; Define an opener + (push `(defun ,func-sym () + ,(format "%s\n\nDefined by `+link-hint-define'." docstring) + (interactive) + (avy-with link-hint-open-link + (link-hint--one ,keyword))) + expr) + ;; Handle `:multiple' + (when multiple + (push `(defun ,(intern (format "+link-hint-open-multiple%s" keyword)) () + ,(format "Open multiple links with `%s'.\n\nDefined by `+link-hint-define'." + func-sym) + (avy-with link-hint-open-multiple-links + (link-hint--multiple ,keyword))) + expr) + (push `(defun ,(intern (format "+link-hint-open-all%s" keyword)) () + ,(format "Open all visible links with `%s'.\n\nDefined by `+link-hint-define'." + func-sym) + (avy-with link-hint-open-all-links + (link-hint--all ,keyword))) + expr)) + ;; Return the built expression + `(progn ,@(nreverse expr)))) + +(+link-hint-define-keyword :secondary browse-url-secondary-browser-function + "Open a link in the secondary browser." + +link-hint-open-secondary-types + :multiple t) + +(defun +link-hint-open-secondary-setup (&optional types) + "Define the `:open-secondary' link-hint type for TYPES. +If TYPES is nil, define it for `+link-hint-open-secondary-types'." + (dolist (type (or types +link-hint-open-secondary-types)) + (link-hint-define-type type + :open-secondary browse-url-secondary-browser-function + :open-secondary-multiple t))) + +(defun +link-hint-open-secondary () + "Open a link in the secondary browser." + (interactive) + (avy-with link-hint-open-link + (link-hint--one :open-secondary))) + +(defun +link-hint-open-chrome-setup (&optional types) + "Define the `:open-chrome' link-hint type for TYPES. +If TYPES is nil, define it for `+link-hint-open-secondary-types'." + (dolist (type (or types +link-hint-open-secondary-types)) + (link-hint-define-type type + :open-chrome #'browse-url-chrome + :open-chrome-multiple t))) + +(defun +link-hint-open-chrome () + "Open a link with chrome." + (interactive) + (avy-with link-hint-open-link + (link-hint--one :open-chrome))) + +(defun +link-hint-open-link (prefix) + "Open a link. +Without a PREFIX, open using `browse-url-browser-function'; with +a PREFIX, use `browse-url-secondary-browser-function'." + (interactive "P") + (let ((current-prefix-arg nil)) + (avy-with link-hint-open-link + (link-hint--one (if prefix :open-secondary :open))))) + +;; test: https://www.acdw.net + +(defun +link-hint-open-multiple-links (prefix) + "Open multiple links. +Without a PREFIX, open using `browse-url-browser-function'; with +a PREFIX, use `browse-url-secondary-browser-function'." + (interactive "P") + (avy-with link-hint-open-multiple-links + (link-hint--one (if prefix :open-secondary :open)))) + +(defun +link-hint-open-all-links (prefix) + "Open all visible links. +Without a PREFIX, open using `browse-url-browser-function'; with +a PREFIX, use `browse-url-secondary-browser-function'." + (interactive "P") + (avy-with link-hint-open-all-links + (link-hint--one (if prefix :open-secondary :open)))) + +(provide '+link-hint) +;;; +link-hint.el ends here diff --git a/lisp/acdw-web.el b/lisp/acdw-web.el index 28fcd02..36a5ba4 100644 --- a/lisp/acdw-web.el +++ b/lisp/acdw-web.el @@ -2,6 +2,8 @@ ;;; Code: +(require 'cl-lib) + (defcustom +browse-url-other-safe-browser-functions nil "Other safe browser functions." :type '(repeat function)) @@ -162,6 +164,25 @@ This function only tests URL's domain." ;;; Packages +(use-package eww + :config + (setopt eww-use-browse-url ".") + (add-hook 'eww-mode-hook + (defun eww-mode@setup () + (add-hook 'visual-fill-column-mode-hook + (defun visual-fill-column@eww-reload () + (eww-reload :local)))) + nil :local) + (keymap-set eww-mode-map "&" + (defun eww-browse-url-external (&optional url) + (interactive nil eww-mode) + (condition-case e + (funcall + browse-url-secondary-browser-function + (or url (plist-get eww-data :url))) + (:success (when (null url) (quit-window))) ; Interactive use + (t (signal (car e) (cdr e))))))) + (use-package browse-url :demand t :config @@ -171,8 +192,9 @@ This function only tests URL's domain." ;; Dispatch browser based on URL browse-url-handlers `(;; Videos - (,(+browse-url-matches "youtube\\.com" "yoiutu\\.be" + (,(+browse-url-matches "youtube\\.com" "youtu\\.be" "invidious" "yewtu\\.be" + "twitch\\.tv" (rx "." (or "mp4" "gif" "mov" "MOV" "webm") eos)) . +browse-url-with-mpv) @@ -218,5 +240,54 @@ This function only tests URL's domain." (setopt browse-url-chrome-program chrome browse-url-generic-program chrome))) +(use-package browse-url-transform + :after browse-url + :load-path "~/src/emacs/browse-url-transform/" + :config + (setopt browse-url-transform-alist + `(;; Privacy-respecting alternatives + ("twitter\\.com" . "nitter.snopyta.org") + ("\\(?:\\(?:old\\.\\)?reddit\\.com\\)" . "libreddit.de") + ("medium\\.com" . "scribe.rip") + (".*substack\\.com.*" . ,substack-proxy) + ;; Text-mode of non-text-mode sites + ("www\\.npr\\.org" . "text.npr.org") + ;; Ask for raw versions of paste sites + ("^.*dpaste\\.com.*$" . "\\&.txt") + ("bpa\\.st/\\(.*\\)" . "bpa.st/raw/\\1") + ("\\(paste\\.debian\\.net\\)/\\(.*\\)" . "\\1/plain/\\2") + ("\\(pastebin\\.com\\)/\\\(.*\\)" . "\\1/raw/\\2") + ("\\(paste\\.centos\\.org/view\\)/\\(.*\\)" . "\\1/raw/\\2"))) + (browse-url-transform-mode)) + +;;; Link hint + +(use-package link-hint + :ensure t :demand t + :preface (keymap-global-unset "M-l") + :bind + (("M-l M-l" . +link-hint-open-link) + ("M-l l" . +link-hint-open-link) + ("M-l M-o" . +link-hint-open-secondary) + ("M-l o" . +link-hint-open-secondary) + ("M-l M-m" . +link-hint-open-multiple-links) + ("M-l m" . +link-hint-open-multiple-links) + ("M-l M-w" . link-hint-copy-link) + ("M-l w" . link-hint-copy-link) + ("M-l M-c" . +link-hint-open-chrome) + ("M-l c" . +link-hint-open-chrome)) + :config + (require '+link-hint) + (setopt link-hint-avy-style 'at-full + link-hint-avy-all-windows t) + ;; For some reason, `link-hint-completion-list-candidate' freezes Emacs. + ;; Removing it fixes the problem, so ... that's what I've done. It's quite + ;; possible this problem isn't caused by `link-hint' at all, but rather by + ;; another package's configuration, but I don't care enough to fix it. + (setq link-hint-types + (delq 'link-hint-completion-list-candidate link-hint-types)) + (+link-hint-open-secondary-setup) + (+link-hint-open-chrome-setup)) + (provide 'acdw-web) ;;; acdw-web.el ends here -- cgit 1.4.1-21-gabe81