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
|
;;; +browse-url.el -*- lexical-binding: t -*-
(require 'browse-url)
(cl-defmacro +browse-url-make-external-viewer-handler
(viewer default-args
&optional (prompt "URL: ")
&key
(custom-group 'browse-url)
(name (intern (format "+browse-url-with-%s" viewer)))
doc vardoc
(varname (intern (format "%s-args" name)))
(fallback t))
"Create a `browse-url' handler function calling VIEWER on the url.
This macro also creates a `customize' setting in CUSTOM-GROUP for
VIEWER's command-line arguments. DEFAULT-ARGS specifies the
default arguments for that setting.
PROMPT is shown to the user in the function's `interactive' spec,
as an argument to `browse-url-interactive-arg'.
The resulting function is named NAME, which defaults to
`+browse-url-wth-VIEWER'. The custom variable is named VARNAME,
which defaults to `NAME-args'. If DOC or VARDOC are provided,
they'll be the documentation of the function and variable
respectively; otherwise, basic docstrings are used.
Finally, if FALLBACK is non-nil (by default, it's
`browse-url-generic'), the function will call that if unable to
start VIEWER."
(declare (indent 1))
`(progn
(defcustom ,varname ,default-args
,(or doc (format "Arguments to pass to %s in `%s'." viewer name))
:type '(repeat :tag "Command-line argument" string)
:group ',custom-group)
(defun ,name (url &optional new-window)
,(or vardoc (format "Open URL in %s." viewer))
(interactive (browse-url-interactive-arg ,prompt))
(let* ((url (browse-url-encode-url url))
(process-environment (browse-url-process-environment)))
(message ,(format "Opening %%s in %s..." viewer) url)
(unless (ignore-errors (apply #'start-process
(format "%s %s" ,viewer url) nil
,viewer
(append ,varname (list url))))
,@(cond
((eq fallback t) '((browse-url-generic url new-window)))
(fallback `((funcall ,fallback url new-window)))
(:else `((message "Can't find viewer: `%s'" ,viewer)
nil))))))))
(defcustom +browse-url-download-open t
"Whether to open downloaded files afterward."
:group 'browse-url
:type 'boolean)
(defun +browse-url-download-callback (status url dir)
;; A slight change to `eww-download-callback' that returns the downloaded
;; filename.
(unless (plist-get status :error)
(let* ((obj (url-generic-parse-url url))
(path (directory-file-name (car (url-path-and-query obj))))
(file (eww-make-unique-file-name
(eww-decode-url-file-name (file-name-nondirectory path))
dir)))
(goto-char (point-min))
(re-search-forward "\r?\n\r?\n")
(let ((coding-system-for-write 'no-conversion))
(write-region (point) (point-max) file))
(message "Saved %s" file)
file)))
(defun +browse-url-download (url &rest _)
"Download URL to `eww-download-directory'."
(interactive "sDownload URL: ")
(let ((dir eww-download-directory))
(when (functionp dir) (setq dir (funcall dir)))
(make-directory dir :parents)
(url-retrieve url
(lambda (s u d)
(let ((file (+browse-url-download-callback s u d)))
(when +browse-url-download-open
(browse-url-xdg-open file))))
(list url dir))))
(provide '+browse-url)
;;; +browse-url.el ends here
|