summary refs log tree commit diff stats
path: root/lisp/+browse-url.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/+browse-url.el')
-rw-r--r--lisp/+browse-url.el189
1 files changed, 0 insertions, 189 deletions
diff --git a/lisp/+browse-url.el b/lisp/+browse-url.el deleted file mode 100644 index b65b6f9..0000000 --- a/lisp/+browse-url.el +++ /dev/null
@@ -1,189 +0,0 @@
1;;; +browse-url.el -*- lexical-binding: t; -*-
2
3(require 'browse-url)
4(require 'cl-lib)
5(require 'seq)
6(require 'url-util)
7
8(defgroup +browse-url nil
9 "My `browse-url' extras."
10 :group 'browse-url)
11
12;;; External URL handlers
13
14(cl-defmacro +browse-url-make-external-viewer-handler
15 (viewer
16 &key
17 args
18 (prompt "URL: ")
19 (program (executable-find (format "%s" viewer)))
20 (name (intern (format "+browse-url-with-%s" viewer)))
21 doc
22 (var (intern (format "%s-args" name)))
23 vardoc
24 (custom-group '+browse-url)
25 (fallback '(function browse-url-generic)))
26 "Create a `browse-url' handler function calling PROGRAM on the URL.
27This macro also creates a `customize' setting in CUSTOM-GROUP for
28PROGRAM's command-line arguments. ARGS specifies the
29default arguments for this user option.
30
31PROGRAM defaults to the result of calling `executable-find' on VIEWER.
32
33PROMPT is shown to the user in the function's `interactive' spec, as an argument
34to `browse-url-interactive-arg'.
35
36The resulting function is named NAME, which defaults to
37`+browse-url-with-VIEWER'. The custom variable is named VAR, which defaults
38to `NAME-args'. If DOC or VARDOC are provided, they'll be the documentation of
39the function and variable respectively; otherwise a basic default doc-string is
40used.
41
42If FALLBACK is non-nil (the default is `browse-url-generic'), the
43generated function will call FALLBACK if unable to start PROGRAM
44for some reason."
45 (declare (indent 1))
46 `(progn
47 (defcustom ,var ,args
48 ,(or vardoc (format "Arguments to pass to %s in `%s'."
49 viewer name))
50 :type '(repeat :tag "Command-line argument" string)
51 :group ',custom-group)
52 (defun ,name (url &optional new-window)
53 ,(or doc (format "Open URL in %s." viewer))
54 (interactive (browse-url-interactive-arg ,prompt))
55 (let* ((url (browse-url-encode-url url))
56 (process-environment (browse-url-process-environment)))
57 (message ,(format "Opening %%s in %s..." viewer) url)
58 (unless (ignore-errors (apply #'start-process
59 (format "%s %s" ',viewer url)
60 nil
61 ,program
62 (append ,var (list url))))
63 ,@(cond
64 (fallback `((funcall ,fallback url new-window)))
65 (:else `((message "Can't find viewer: %s" ,viewer)
66 nil))))))))
67
68;; Some default handlers
69
70(+browse-url-make-external-viewer-handler mpv
71 :args '("--cache-pause-wait=15"
72 "--cache-pause-initial=yes")
73 :prompt "Video URL: ")
74
75(+browse-url-make-external-viewer-handler mpv-image
76 :program (executable-find "mpv")
77 :args '("--image-display-duration=inf")
78 :prompt "Image URL: ")
79
80;;; Downloading
81
82(defcustom +browse-url-download-open t
83 "Whether to open downloaded files after downloading."
84 :type 'boolean)
85
86(defun +browse-url-download (url &rest _)
87 "Download URL to `eww-download-directory'."
88 (interactive "sDownload URL: ")
89 (let ((dir eww-download-directory))
90 (when (functionp dir) (setq dir (funcall dir)))
91 (make-directory dir :parents)
92 (url-retrieve url
93 (lambda (s u d)
94 (let ((file (+browse-url-download-callback s u d)))
95 (when +browse-url-download-open
96 (browse-url-xdg-open file))))
97 (list url dir))))
98
99(defun +browse-url-download-callback (status url dir)
100 ;; A slight change to `eww-download-callback' that returns the downloaded
101 ;; filename.
102 (unless (plist-get status :error)
103 (let* ((obj (url-generic-parse-url url))
104 (path (directory-file-name (car (url-path-and-query obj))))
105 (file (eww-make-unique-file-name
106 (eww-decode-url-file-name (file-name-nondirectory path))
107 dir)))
108 (goto-char (point-min))
109 (re-search-forward "\r?\n\r?\n")
110 (let ((coding-system-for-write 'no-conversion))
111 (write-region (point) (point-max) file))
112 (message "Saved %s" file)
113 file)))
114
115;;; URL matcher generators
116
117(defun +browse-url-matches (&rest regexps)
118 "Return a lambda that will determine if a url matches REGEXPS.
119Each regexp will be tested in turn. The first one that matches
120is returned by the lambda.
121
122This is a good function to use in key positions in `browse-url-handlers'."
123 `(lambda (url &optional new-window)
124 (cl-loop for regexp in ',regexps
125 if (string-match-p regexp url)
126 return regexp)))
127
128;;; External domains
129;; Some domains just don't open well in `eww'. The following function and user
130;; option define an easy way to automatically open those.
131
132(defcustom +browse-url-external-domains nil
133 "Domains to open in `browse-url-secondary-browser-function'.
134This is just a list of strings. They'll be regexp-escaped and
135passed to `+browse-url-external-url-p', which is a good function
136to put in `browse-url-handlers'.
137
138If an item in this list is a list itself, it should contain one string, a valid
139regexp that will not be regexp-quoted when matching against a url."
140 :type '(repeat (choice
141 (list :tag "Regexp" regexp)
142 (string :tag "Literal string"))))
143
144(defun +browse-url-external-url-p (url)
145 "Return t if URL is a member of `+browse-url-external-domains'.
146This function only tests URL's domain."
147 (let ((host (url-host (url-generic-parse-url url))))
148 (cl-loop for domain in +browse-url-external-domains
149 if (string-match-p (if (stringp domain)
150 (regexp-quote domain)
151 (car domain))
152 host)
153 return t)))
154
155;;; Switch to an external browser from an Emacs browser
156
157(defmacro +browse-url-switch-external-browser (mode url-fetcher-form)
158 "Create a function for MODE to open an external browser.
159URL-FETCHER-FORM will be used to get the URL of the current visited page."
160 (declare (indent 1))
161 `(defun ,(intern (format "+browse-url-external-from-%s" mode))
162 (&optional url)
163 "Browse URL with `browse-url-secondary-browser-function'.
164This will close the current buffer."
165 (interactive nil ,mode)
166 (condition-case e
167 (funcall browse-url-secondary-browser-function
168 (or url ,url-fetcher-form))
169 (:success (when (null url) (quit-window))) ; Interactive use
170 (t (signal (car e) (cdr e))))))
171
172;;; Mark `browse-url-browser-function' as safe
173
174(defcustom +browse-url-other-safe-browser-functions nil
175 "Other safe browser functions."
176 :type '(repeat function))
177
178(defun +browse-url-browser-function-safe-p (f)
179 "Return t if F is a safe browser function."
180 (memq f (append +browse-url-other-safe-browser-functions
181 (mapcar (lambda (i)
182 (plist-get (cdr i) :value))
183 (seq-filter (lambda (i)
184 (eq (car i) 'function-item))
185 (cdr (get 'browse-url-browser-function
186 'custom-type)))))))
187
188(provide '+browse-url)
189;;; +browse-url.el ends here