diff options
author | Case Duckworth | 2023-01-20 13:14:49 -0600 |
---|---|---|
committer | Case Duckworth | 2023-01-20 13:14:49 -0600 |
commit | 71b97e7871ed5eed8e03202daaf8124c3a2b7e1e (patch) | |
tree | 9133fa453a19356ce1c2468b02a5ee6d349b94fa /lisp | |
parent | changes (diff) | |
download | emacs-71b97e7871ed5eed8e03202daaf8124c3a2b7e1e.tar.gz emacs-71b97e7871ed5eed8e03202daaf8124c3a2b7e1e.zip |
Add link-hint
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/+link-hint.el | 146 | ||||
-rw-r--r-- | lisp/acdw-web.el | 73 |
2 files changed, 218 insertions, 1 deletions
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 @@ | |||
1 | ;;; +link-hint.el -*- lexical-binding: t; -*- | ||
2 | |||
3 | ;;; Code: | ||
4 | |||
5 | (require 'cl-lib) | ||
6 | (require 'link-hint) | ||
7 | |||
8 | (defgroup +link-hint nil | ||
9 | "Extra customizations for `link-hint'." | ||
10 | :group 'link-hint) | ||
11 | |||
12 | (defcustom +link-hint-open-secondary-types '(gnus-w3m-image-url | ||
13 | gnus-w3m-url | ||
14 | markdown-link | ||
15 | mu4e-attachment | ||
16 | mu4e-url | ||
17 | notmuch-hello | ||
18 | nov-link | ||
19 | org-link | ||
20 | shr-url | ||
21 | text-url | ||
22 | w3m-link | ||
23 | w3m-message-link) | ||
24 | "Link types to define `:open-secondary' for.") | ||
25 | |||
26 | (defvar +link-hint-map (make-sparse-keymap) | ||
27 | "Keymap for `link-hint' functionality.") | ||
28 | |||
29 | (cl-defmacro +link-hint-define-keyword (keyword handler docstring | ||
30 | &optional (types 'link-hint-types) | ||
31 | &rest rest | ||
32 | &key multiple &allow-other-keys) | ||
33 | "Set up a `link-hint' KEYWORD, with optional TYPES. | ||
34 | If TYPES is not present, use `link-hint-types'. | ||
35 | |||
36 | KEYWORD defines the link-hint type. It will be used to create a | ||
37 | function for opening links of the form \"link-hint-openKEYWORD\". | ||
38 | |||
39 | HANDLER is the function to open a link with. | ||
40 | |||
41 | DOCSTRING is the macro's documentation. | ||
42 | |||
43 | Keyword arguments are passed to `link-hint-define-type' prefixed | ||
44 | with the KEYWORD." | ||
45 | (declare (indent 2) | ||
46 | (doc-string 3)) | ||
47 | (let ((types (symbol-value types)) | ||
48 | (func-sym (intern (format "+link-hint-open%s" keyword))) | ||
49 | (mult-sym (intern (format "%s-multiple" keyword))) | ||
50 | (expr)) | ||
51 | ;; Define the type | ||
52 | (push `(dolist (type ',types) | ||
53 | (link-hint-define-type type | ||
54 | ,keyword ,handler | ||
55 | ,@(mapcar (lambda (el) | ||
56 | (if (eq el :multiple) | ||
57 | mult-sym | ||
58 | el)) | ||
59 | rest))) | ||
60 | expr) | ||
61 | ;; Define an opener | ||
62 | (push `(defun ,func-sym () | ||
63 | ,(format "%s\n\nDefined by `+link-hint-define'." docstring) | ||
64 | (interactive) | ||
65 | (avy-with link-hint-open-link | ||
66 | (link-hint--one ,keyword))) | ||
67 | expr) | ||
68 | ;; Handle `:multiple' | ||
69 | (when multiple | ||
70 | (push `(defun ,(intern (format "+link-hint-open-multiple%s" keyword)) () | ||
71 | ,(format "Open multiple links with `%s'.\n\nDefined by `+link-hint-define'." | ||
72 | func-sym) | ||
73 | (avy-with link-hint-open-multiple-links | ||
74 | (link-hint--multiple ,keyword))) | ||
75 | expr) | ||
76 | (push `(defun ,(intern (format "+link-hint-open-all%s" keyword)) () | ||
77 | ,(format "Open all visible links with `%s'.\n\nDefined by `+link-hint-define'." | ||
78 | func-sym) | ||
79 | (avy-with link-hint-open-all-links | ||
80 | (link-hint--all ,keyword))) | ||
81 | expr)) | ||
82 | ;; Return the built expression | ||
83 | `(progn ,@(nreverse expr)))) | ||
84 | |||
85 | (+link-hint-define-keyword :secondary browse-url-secondary-browser-function | ||
86 | "Open a link in the secondary browser." | ||
87 | +link-hint-open-secondary-types | ||
88 | :multiple t) | ||
89 | |||
90 | (defun +link-hint-open-secondary-setup (&optional types) | ||
91 | "Define the `:open-secondary' link-hint type for TYPES. | ||
92 | If TYPES is nil, define it for `+link-hint-open-secondary-types'." | ||
93 | (dolist (type (or types +link-hint-open-secondary-types)) | ||
94 | (link-hint-define-type type | ||
95 | :open-secondary browse-url-secondary-browser-function | ||
96 | :open-secondary-multiple t))) | ||
97 | |||
98 | (defun +link-hint-open-secondary () | ||
99 | "Open a link in the secondary browser." | ||
100 | (interactive) | ||
101 | (avy-with link-hint-open-link | ||
102 | (link-hint--one :open-secondary))) | ||
103 | |||
104 | (defun +link-hint-open-chrome-setup (&optional types) | ||
105 | "Define the `:open-chrome' link-hint type for TYPES. | ||
106 | If TYPES is nil, define it for `+link-hint-open-secondary-types'." | ||
107 | (dolist (type (or types +link-hint-open-secondary-types)) | ||
108 | (link-hint-define-type type | ||
109 | :open-chrome #'browse-url-chrome | ||
110 | :open-chrome-multiple t))) | ||
111 | |||
112 | (defun +link-hint-open-chrome () | ||
113 | "Open a link with chrome." | ||
114 | (interactive) | ||
115 | (avy-with link-hint-open-link | ||
116 | (link-hint--one :open-chrome))) | ||
117 | |||
118 | (defun +link-hint-open-link (prefix) | ||
119 | "Open a link. | ||
120 | Without a PREFIX, open using `browse-url-browser-function'; with | ||
121 | a PREFIX, use `browse-url-secondary-browser-function'." | ||
122 | (interactive "P") | ||
123 | (let ((current-prefix-arg nil)) | ||
124 | (avy-with link-hint-open-link | ||
125 | (link-hint--one (if prefix :open-secondary :open))))) | ||
126 | |||
127 | ;; test: https://www.acdw.net | ||
128 | |||
129 | (defun +link-hint-open-multiple-links (prefix) | ||
130 | "Open multiple links. | ||
131 | Without a PREFIX, open using `browse-url-browser-function'; with | ||
132 | a PREFIX, use `browse-url-secondary-browser-function'." | ||
133 | (interactive "P") | ||
134 | (avy-with link-hint-open-multiple-links | ||
135 | (link-hint--one (if prefix :open-secondary :open)))) | ||
136 | |||
137 | (defun +link-hint-open-all-links (prefix) | ||
138 | "Open all visible links. | ||
139 | Without a PREFIX, open using `browse-url-browser-function'; with | ||
140 | a PREFIX, use `browse-url-secondary-browser-function'." | ||
141 | (interactive "P") | ||
142 | (avy-with link-hint-open-all-links | ||
143 | (link-hint--one (if prefix :open-secondary :open)))) | ||
144 | |||
145 | (provide '+link-hint) | ||
146 | ;;; +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 @@ | |||
2 | 2 | ||
3 | ;;; Code: | 3 | ;;; Code: |
4 | 4 | ||
5 | (require 'cl-lib) | ||
6 | |||
5 | (defcustom +browse-url-other-safe-browser-functions nil | 7 | (defcustom +browse-url-other-safe-browser-functions nil |
6 | "Other safe browser functions." | 8 | "Other safe browser functions." |
7 | :type '(repeat function)) | 9 | :type '(repeat function)) |
@@ -162,6 +164,25 @@ This function only tests URL's domain." | |||
162 | 164 | ||
163 | ;;; Packages | 165 | ;;; Packages |
164 | 166 | ||
167 | (use-package eww | ||
168 | :config | ||
169 | (setopt eww-use-browse-url ".") | ||
170 | (add-hook 'eww-mode-hook | ||
171 | (defun eww-mode@setup () | ||
172 | (add-hook 'visual-fill-column-mode-hook | ||
173 | (defun visual-fill-column@eww-reload () | ||
174 | (eww-reload :local)))) | ||
175 | nil :local) | ||
176 | (keymap-set eww-mode-map "&" | ||
177 | (defun eww-browse-url-external (&optional url) | ||
178 | (interactive nil eww-mode) | ||
179 | (condition-case e | ||
180 | (funcall | ||
181 | browse-url-secondary-browser-function | ||
182 | (or url (plist-get eww-data :url))) | ||
183 | (:success (when (null url) (quit-window))) ; Interactive use | ||
184 | (t (signal (car e) (cdr e))))))) | ||
185 | |||
165 | (use-package browse-url | 186 | (use-package browse-url |
166 | :demand t | 187 | :demand t |
167 | :config | 188 | :config |
@@ -171,8 +192,9 @@ This function only tests URL's domain." | |||
171 | ;; Dispatch browser based on URL | 192 | ;; Dispatch browser based on URL |
172 | browse-url-handlers | 193 | browse-url-handlers |
173 | `(;; Videos | 194 | `(;; Videos |
174 | (,(+browse-url-matches "youtube\\.com" "yoiutu\\.be" | 195 | (,(+browse-url-matches "youtube\\.com" "youtu\\.be" |
175 | "invidious" "yewtu\\.be" | 196 | "invidious" "yewtu\\.be" |
197 | "twitch\\.tv" | ||
176 | (rx "." (or "mp4" "gif" "mov" "MOV" "webm") | 198 | (rx "." (or "mp4" "gif" "mov" "MOV" "webm") |
177 | eos)) | 199 | eos)) |
178 | . +browse-url-with-mpv) | 200 | . +browse-url-with-mpv) |
@@ -218,5 +240,54 @@ This function only tests URL's domain." | |||
218 | (setopt browse-url-chrome-program chrome | 240 | (setopt browse-url-chrome-program chrome |
219 | browse-url-generic-program chrome))) | 241 | browse-url-generic-program chrome))) |
220 | 242 | ||
243 | (use-package browse-url-transform | ||
244 | :after browse-url | ||
245 | :load-path "~/src/emacs/browse-url-transform/" | ||
246 | :config | ||
247 | (setopt browse-url-transform-alist | ||
248 | `(;; Privacy-respecting alternatives | ||
249 | ("twitter\\.com" . "nitter.snopyta.org") | ||
250 | ("\\(?:\\(?:old\\.\\)?reddit\\.com\\)" . "libreddit.de") | ||
251 | ("medium\\.com" . "scribe.rip") | ||
252 | (".*substack\\.com.*" . ,substack-proxy) | ||
253 | ;; Text-mode of non-text-mode sites | ||
254 | ("www\\.npr\\.org" . "text.npr.org") | ||
255 | ;; Ask for raw versions of paste sites | ||
256 | ("^.*dpaste\\.com.*$" . "\\&.txt") | ||
257 | ("bpa\\.st/\\(.*\\)" . "bpa.st/raw/\\1") | ||
258 | ("\\(paste\\.debian\\.net\\)/\\(.*\\)" . "\\1/plain/\\2") | ||
259 | ("\\(pastebin\\.com\\)/\\\(.*\\)" . "\\1/raw/\\2") | ||
260 | ("\\(paste\\.centos\\.org/view\\)/\\(.*\\)" . "\\1/raw/\\2"))) | ||
261 | (browse-url-transform-mode)) | ||
262 | |||
263 | ;;; Link hint | ||
264 | |||
265 | (use-package link-hint | ||
266 | :ensure t :demand t | ||
267 | :preface (keymap-global-unset "M-l") | ||
268 | :bind | ||
269 | (("M-l M-l" . +link-hint-open-link) | ||
270 | ("M-l l" . +link-hint-open-link) | ||
271 | ("M-l M-o" . +link-hint-open-secondary) | ||
272 | ("M-l o" . +link-hint-open-secondary) | ||
273 | ("M-l M-m" . +link-hint-open-multiple-links) | ||
274 | ("M-l m" . +link-hint-open-multiple-links) | ||
275 | ("M-l M-w" . link-hint-copy-link) | ||
276 | ("M-l w" . link-hint-copy-link) | ||
277 | ("M-l M-c" . +link-hint-open-chrome) | ||
278 | ("M-l c" . +link-hint-open-chrome)) | ||
279 | :config | ||
280 | (require '+link-hint) | ||
281 | (setopt link-hint-avy-style 'at-full | ||
282 | link-hint-avy-all-windows t) | ||
283 | ;; For some reason, `link-hint-completion-list-candidate' freezes Emacs. | ||
284 | ;; Removing it fixes the problem, so ... that's what I've done. It's quite | ||
285 | ;; possible this problem isn't caused by `link-hint' at all, but rather by | ||
286 | ;; another package's configuration, but I don't care enough to fix it. | ||
287 | (setq link-hint-types | ||
288 | (delq 'link-hint-completion-list-candidate link-hint-types)) | ||
289 | (+link-hint-open-secondary-setup) | ||
290 | (+link-hint-open-chrome-setup)) | ||
291 | |||
221 | (provide 'acdw-web) | 292 | (provide 'acdw-web) |
222 | ;;; acdw-web.el ends here | 293 | ;;; acdw-web.el ends here |