diff options
-rw-r--r-- | init.el | 15 | ||||
-rw-r--r-- | lisp/+link-hint.el | 144 |
2 files changed, 159 insertions, 0 deletions
diff --git a/init.el b/init.el index 0bd11d4..bf52e4f 100644 --- a/init.el +++ b/init.el | |||
@@ -906,6 +906,21 @@ CAPES defaults to `+capes'. CAPF will be made un-exclusive." | |||
906 | (sesman "https://github.com/vspinu/sesman")) | 906 | (sesman "https://github.com/vspinu/sesman")) |
907 | :when (executable-find "clojure")) | 907 | :when (executable-find "clojure")) |
908 | 908 | ||
909 | (yoke (link-hint "https://github.com/noctuid/link-hint.el/") | ||
910 | :depends ((avy "https://github.com/abo-abo/avy")) | ||
911 | (require '+link-hint) | ||
912 | (+link-hint-open-secondary-setup) | ||
913 | (+link-hint-open-chrome-setup) | ||
914 | (setf link-hint-avy-style 'at-full | ||
915 | link-hint-avy-all-windows t) | ||
916 | (global-set-key (kbd "M-l") +link-hint-map) | ||
917 | (define-key* +link-hint-map | ||
918 | "M-l" #'+link-hint-open-link "l" #'+link-hint-open-link | ||
919 | "M-o" #'+link-hint-open-secondary "o" #'+link-hint-open-secondary | ||
920 | "M-m" #'+link-hint-open-multiple-links "m" #'+link-hint-open-multiple-links | ||
921 | "M-w" #'link-hint-copy-link "w" #'link-hint-copy-link | ||
922 | "M-c" #'+link-hint-open-chrome "c" #'+link-hint-open-chrome)) | ||
923 | |||
909 | (yoke browse-url | 924 | (yoke browse-url |
910 | (require '+browse-url) | 925 | (require '+browse-url) |
911 | (setf browse-url-browser-function #'eww-browse-url | 926 | (setf browse-url-browser-function #'eww-browse-url |
diff --git a/lisp/+link-hint.el b/lisp/+link-hint.el new file mode 100644 index 0000000..926a266 --- /dev/null +++ b/lisp/+link-hint.el | |||
@@ -0,0 +1,144 @@ | |||
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 | (defun +link-hint-open-multiple-links (prefix) | ||
128 | "Open multiple links. | ||
129 | Without a PREFIX, open using `browse-url-browser-function'; with | ||
130 | a PREFIX, use `browse-url-secondary-browser-function'." | ||
131 | (interactive "P") | ||
132 | (avy-with link-hint-open-multiple-links | ||
133 | (link-hint--one (if prefix :open-secondary :open)))) | ||
134 | |||
135 | (defun +link-hint-open-all-links (prefix) | ||
136 | "Open all visible links. | ||
137 | Without a PREFIX, open using `browse-url-browser-function'; with | ||
138 | a PREFIX, use `browse-url-secondary-browser-function'." | ||
139 | (interactive "P") | ||
140 | (avy-with link-hint-open-all-links | ||
141 | (link-hint--one (if prefix :open-secondary :open)))) | ||
142 | |||
143 | (provide '+link-hint) | ||
144 | ;;; +link-hint.el ends here | ||