summary refs log tree commit diff stats
path: root/lisp/+browse-url.el
blob: 12e433c871458ec488b4ac794d76c4077df83495 (plain)
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