-
Notifications
You must be signed in to change notification settings - Fork 50
/
setup-eww.el
320 lines (291 loc) · 15.7 KB
/
setup-eww.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
;; Time-stamp: <2017-10-17 08:14:29 kmodi>
;; Eww - Emacs browser (needs emacs 24.4 or higher)
(use-package eww
:bind (:map modi-mode-map
("M-s M-w" . modi/eww-search-words) ;Bound by default to `eww-search-words'
("M-s M-l" . modi/eww-get-link))
:chords (("-=" . eww))
:commands (modi/eww-im-feeling-lucky
modi/eww-browse-url-of-file)
:init
(progn
(bind-to-modi-map "e" #'eww-open-file))
:config
(progn
(defvar modi/eww-google-search-url "https://www.google.com/search?q="
"URL for Google searches.")
(setq eww-search-prefix modi/eww-google-search-url)
;; (setq eww-search-prefix "https://duckduckgo.com/html/?q=")
(setq eww-download-directory "~/downloads")
(setq eww-form-checkbox-symbol "[ ]")
;; (setq eww-form-checkbox-symbol "☐") ; Unicode hex 2610
(setq eww-form-checkbox-selected-symbol "[X]")
;; (setq eww-form-checkbox-selected-symbol "☑") ; Unicode hex 2611
;; Improve the contract of pages like Google results
;; http://emacs.stackexchange.com/q/2955/115
(setq shr-color-visible-luminance-min 80) ; default = 40
;; Auto-rename new eww buffers
;; http://ergoemacs.org/emacs/emacs_eww_web_browser.html
(defun xah-rename-eww-hook ()
"Rename eww browser's buffer so sites open in new page."
(rename-buffer "eww" t))
(add-hook 'eww-mode-hook #'xah-rename-eww-hook)
;; If the current buffer is an eww buffer, "M-x eww" will always reuse the
;; current buffer to load the new page. Below advice will make "C-u M-x eww"
;; force a new eww buffer even when the current buffer is an eww buffer.
;; The above `xah-rename-eww-hook' fix is still needed in order to create
;; uniquely named eww buffers.
;; http://emacs.stackexchange.com/a/24477/115
(defun modi/force-new-eww-buffer (orig-fun &rest args)
"When prefix argument is used, a new eww buffer will be created.
This is regardless of whether the current buffer is an eww buffer. "
(if current-prefix-arg
(with-temp-buffer
(apply orig-fun args))
(apply orig-fun args)))
(advice-add 'eww :around #'modi/force-new-eww-buffer)
;; Re-write of the `eww-search-words' definition.
(defun modi/eww-search-words ()
"Search the web for the text between BEG and END.
If region is active (and not whitespace), search the web for
the text in that region.
Else if the region is not active, and the point is on a symbol,
search the web for that symbol.
Else prompt the user for a search string.
See the `eww-search-prefix' variable for the search engine used."
(interactive)
(let ((search-string (modi/get-selected-text-or-symbol-at-point)))
(when (and (stringp search-string)
(string-match-p "\\`[[:blank:]]*\\'" search-string))
(setq search-string nil))
(if (stringp search-string)
(eww search-string)
(call-interactively #'eww))))
;; Tue Oct 17 08:00:57 EDT 2017 - kmodi
;; duckduckgo is not included in the below alist because
;; `shr-probe-and-copy-url' does not work on duckduckgo search result URLs.
(defvar modi/eww-search-alist '((modi/eww-google-search-url . "[[:digit:]]+ results[[:blank:]]*$"))
"Alist of search engines and regexp matching the start of results.
The elements are of type (SEARCH-PREFIX . REGEXP) where
SEARCH-PREFIX is a prefix URL as would be used by
`eww-search-prefix', and REGEXP is a regular expression to match
the start of search results.")
(defun modi/eww--go-to-first-search-result (search-term)
"Navigate to the first search result in the *eww* buffer."
;; Keep on burying the current buffer if it turns out to be an eww buffer.
(while (string-match "^\\*?eww" (buffer-name))
(bury-buffer))
(let* ((eww-search-prefix eww-search-prefix) ;Use the global value of `eww-search-prefix' by default
(start-results-re
(let ((re (cdr (assoc eww-search-prefix modi/eww-search-alist))))
(unless re
(message "Using Google search because `modi/eww-search-alist' does not have an entry for %S" eww-search-prefix)
(setq eww-search-prefix modi/eww-google-search-url)
(setq re (cdr (assoc eww-search-prefix modi/eww-search-alist))))
re))
(max-wait 5) ;Seconds
(search-repeat-interval 0.1) ;Seconds
(max-trials (floor max-wait search-repeat-interval))
(start-time (current-time))
(n 1))
(unless start-results-re
;; This condition would be entered only if `modi/eww-search-alist' is
;; messed up badly.
(user-error "`modi/eww-search-alist' does not contain an entry for %S" eww-search-prefix))
(eww search-term) ;Start a new eww search
;; The while loop will keep on repeating every `search-repeat-interval'
;; seconds till the return value of `eww-links-at-point' is non-nil.
(catch 'break
(while (<= n max-trials)
(goto-char (point-min)) ;Go to the top of the buffer
;; Go to the start of results
(re-search-forward start-results-re nil :noerror)
(shr-next-link) ;Go to the first search result
(when (eww-links-at-point)
(throw 'break nil))
;; Wait for a while before trying link check again.
(sleep-for search-repeat-interval)
;; (message "eww search result trial # %d" n)
(setq n (1+ n))))
(message "Search for `%s' finished in %0.2f seconds."
search-term (float-time (time-since start-time)))))
(defun modi/eww-get-link (search-term)
"Copy the link to the first search result."
(interactive "sSearch term: ")
(let ((eww-buffer-name))
(modi/eww--go-to-first-search-result search-term)
(setq eww-buffer-name (rename-buffer "*eww-temp*" t))
(>=e "26.0"
;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=1b4f0a92ff3505ef9a465b9b391756e3a73a6443
(call-interactively #'shr-probe-and-copy-url)
;; Copy the actual link instead of the redirection link by calling
;; `shr-copy-url' twice. This twice-calling is needed only on emacs
;; versions 25.x and older.
(dotimes (i 2)
(shr-copy-url)))
(kill-buffer eww-buffer-name)))
(defun modi/eww-im-feeling-lucky (search-term)
"Navigate to the first search result directly."
(interactive "sSearch term (I'm Feeling Lucky!): ")
(modi/eww--go-to-first-search-result search-term)
(eww-follow-link))
(defun modi/eww-copy-url-dwim (&optional option)
"Copy the URL or image under point to the kill ring.
If OPTION is \\[universal-argument], or if there is no link under
point, but there is an image under point then copy the URL of the
image under point instead.
If OPTION is \\[universal-argument] \\[universal-argument], or if
there is neither a link nor an image, the page URL will be
copied.
\(For emacs 25.x and older) If this function is called twice, try
to fetch the URL and see whether it redirects somewhere else.
\(For emacs 26.x and newer) Automatically use the fetched URL's
redirection destination if it has one."
(interactive "P")
(let (image-url page-url)
(cond
((equal '(4) option) ;C-u
(setq image-url t))
((equal '(16) option) ;C-u C-u
(setq page-url t))
(t ;No prefix
))
(>=e "26.0"
(let* ((pt-on-url (shr-url-at-point nil))
(pt-on-image (shr-url-at-point :image-url)))
(unless (or pt-on-url
pt-on-image)
(setq page-url t)) ;Get page URL if point is neither on URL nor image
(if page-url
(message "Copied page url: %s" (eww-copy-page-url))
(let ((current-prefix-arg image-url))
(call-interactively #'shr-probe-and-copy-url))))
(if page-url
(message "Copied page url: %s" (eww-copy-page-url))
(when (string= (shr-copy-url image-url) "No URL under point") ;No prefix or C-u
;; Copy page url if COMMAND or C-u COMMAND returns
;; "No URL under point".
(message "Copied page url: %s" (eww-copy-page-url)))))))
(defun modi/eww-browse-url-of-file ()
"Browse the current file using `eww'."
(interactive)
(let ((browse-url-browser-function 'eww-browse-url))
(call-interactively #'browse-url-of-file)))
;; eww-lnum
;; https://github.com/m00natic/eww-lnum
(use-package eww-lnum
:bind (:map eww-mode-map
("f" . eww-lnum-follow)
("U" . eww-lnum-universal)))
;; org-eww
;; Copy text from html page for pasting in org mode file/buffer
;; e.g. Copied HTML hyperlinks get converted to [[link][desc]] for org mode.
;; http://emacs.stackexchange.com/a/8191/115
(use-package org-eww
:bind (:map eww-mode-map
("o" . org-eww-copy-for-org-mode)))
;; Auto-refreshing eww buffer whenever the html file it's showing changes
;; http://emacs.stackexchange.com/a/2566/115
(defvar modi/eww--file-notify-descriptors-list ()
"List to store file-notify descriptor for all files that have an
associated auto-reloading eww buffer.")
(defun modi/advice-eww-open-file-to-auto-reload (orig-fun &rest args)
"When `eww-open-file' is called with \\[universal-argument], open
the file in eww and also add `file-notify' watch for it so that the eww
buffer auto-reloads when the HTML file changes."
(prog1
(apply orig-fun args)
(when current-prefix-arg ; C-u M-x eww-open-file
(require 'filenotify)
(let ((file-name (car args)))
(file-notify-add-watch file-name
'(change attribute-change)
#'modi/file-notify-callback-eww-reload)
;; Show the HTML file and its rendered form in eww side-by-side
(find-file-other-window file-name))
;; Redefine the `q' binding in `eww-mode-map'
(bind-key "q" #'modi/eww-quit-and-update-fn-descriptors eww-mode-map))))
(advice-add 'eww-open-file :around #'modi/advice-eww-open-file-to-auto-reload)
(defun modi/file-notify-callback-eww-reload (event)
"On getting triggered, switch to the eww buffer, reload and switch
back to the working buffer. Also save the `file-notify-descriptor' of the
triggering event."
(let* ((working-buffer (buffer-name)))
(switch-to-buffer-other-window "eww")
(eww-reload)
(switch-to-buffer-other-window working-buffer))
;; `(car event)' will return the event descriptor
(add-to-list 'modi/eww--file-notify-descriptors-list (car event)))
(defun modi/eww-quit-and-update-fn-descriptors ()
"When quitting `eww', first remove any saved file-notify descriptors
specific to eww, while also updating `modi/eww--file-notify-descriptors-list'."
(interactive)
(dotimes (index (safe-length modi/eww--file-notify-descriptors-list))
(file-notify-rm-watch (pop modi/eww--file-notify-descriptors-list)))
(quit-window :kill))
(bind-keys
:map eww-mode-map
(":" . eww) ;Go to URL
("h" . eww-list-histories) ;View history
("w" . modi/eww-copy-url-dwim)
("/" . highlight-regexp))
;; Make the binding for `revert-buffer' do `eww-reload' in eww-mode
(define-key eww-mode-map [remap revert-buffer] #'eww-reload)
(bind-keys
:map eww-text-map ;For single line text fields
("<backtab>" . shr-previous-link) ;S-TAB Jump to previous link on the page
("<C-return>" . eww-submit)) ;S-TAB Jump to previous link on the page
(bind-keys
:map eww-textarea-map ;For multi-line text boxes
("<backtab>" . shr-previous-link) ;S-TAB Jump to previous link on the page
("<C-return>" . eww-submit)) ;S-TAB Jump to previous link on the page
(bind-keys
:map eww-checkbox-map
("<down-mouse-1>" . eww-toggle-checkbox))
(bind-keys
:map shr-map
("w" . modi/eww-copy-url-dwim))
(bind-keys
:map eww-link-keymap
("w" . modi/eww-copy-url-dwim))))
(provide 'setup-eww)
;; Default eww key bindings
;; |-----------+---------------------------------------------------------------------|
;; | Key | Function |
;; |-----------+---------------------------------------------------------------------|
;; | & | Browse the current URL with an external browser. |
;; | - | Begin a negative numeric argument for the next command. |
;; | 0 .. 9 | Part of the numeric argument for the next command. |
;; | C | Display a buffer listing the current URL cookies, if there are any. |
;; | H | List the eww-histories. |
;; | F | Toggle font between variable-width and fixed-width. |
;; | G | Go to a URL |
;; | R | Readable mode |
;; | S | List eww buffers |
;; | d | Download URL under point to `eww-download-directory'. |
;; | g | Reload the current page. |
;; | q | Quit WINDOW and bury its buffer. |
;; | v | `eww-view-source' |
;; | w | `eww-copy-page-url' |
;; |-----------+---------------------------------------------------------------------|
;; | b | Add the current page to the bookmarks. |
;; | B | Display the bookmark list. |
;; | M-n | Visit the next bookmark |
;; | M-p | Visit the previous bookmark |
;; |-----------+---------------------------------------------------------------------|
;; | t | Go to the page marked `top'. |
;; | u | Go to the page marked `up'. |
;; |-----------+---------------------------------------------------------------------|
;; | n | Go to the page marked `next'. |
;; | p | Go to the page marked `previous'. |
;; |-----------+---------------------------------------------------------------------|
;; | l | Go to the previously displayed page. |
;; | r | Go to the next displayed page. |
;; |-----------+---------------------------------------------------------------------|
;; | TAB | Move point to next link on the page. |
;; | S-TAB | Move point to previous link on the page. |
;; |-----------+---------------------------------------------------------------------|
;; | SPC | Scroll up |
;; | DEL/Bkspc | Scroll down |
;; | S-SPC | Scroll down |
;; |-----------+---------------------------------------------------------------------|