diff options
| author | Tassilo Horn | 2020-05-04 11:24:08 +0200 |
|---|---|---|
| committer | Tassilo Horn | 2020-05-06 10:14:58 +0200 |
| commit | c4adfbae24d920f0ce62cb88b988219348d1ec73 (patch) | |
| tree | b60ac0e763bc09d50c56795e833fe1a44070f28a | |
| parent | 58c234aa8cb6e76d377f07cbf0b59f2552eb296b (diff) | |
| download | emacs-c4adfbae24d920f0ce62cb88b988219348d1ec73.tar.gz emacs-c4adfbae24d920f0ce62cb88b988219348d1ec73.zip | |
Allow for custom URL handlers in browse-url.
* lisp/net/browse-url.el (browse-url-handlers): New defcustom.
(browse-url-default-handlers): New defvar.
(browse-url): Use them. Adapt docstring. Issue a warning pointing to
browse-url-handlers when browse-url-browser-function is an alist.
(browse-url--mailto, browse-url--man): New functions.
(browse-url--browser-defcustom-type): Add :doc that the alist usage is
deprecated.
(browse-url-browser-function): Remove documentation referring to the
alist usage and mention browse-url-handlers.
* doc/emacs/misc.texi: Document browse-url-handlers in Browse-URL
node.
* etc/NEWS: Mention browse-url-default-handlers and
browse-url-handlers.
| -rw-r--r-- | doc/emacs/misc.texi | 13 | ||||
| -rw-r--r-- | etc/NEWS | 16 | ||||
| -rw-r--r-- | lisp/net/browse-url.el | 114 |
3 files changed, 104 insertions, 39 deletions
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 47f195d0b20..d1854f31ff3 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi | |||
| @@ -2920,9 +2920,16 @@ you might like to bind to keys, such as @code{browse-url-at-point} and | |||
| 2920 | You can customize Browse-URL's behavior via various options in the | 2920 | You can customize Browse-URL's behavior via various options in the |
| 2921 | @code{browse-url} Customize group. In particular, the option | 2921 | @code{browse-url} Customize group. In particular, the option |
| 2922 | @code{browse-url-mailto-function} lets you define how to follow | 2922 | @code{browse-url-mailto-function} lets you define how to follow |
| 2923 | @samp{mailto:} URLs, while @code{browse-url-browser-function} lets you | 2923 | @samp{mailto:} URLs, while @code{browse-url-browser-function} |
| 2924 | define how to follow other types of URLs. For more information, view | 2924 | specifies your default browser. |
| 2925 | the package commentary by typing @kbd{C-h P browse-url @key{RET}}. | 2925 | |
| 2926 | @vindex browse-url-handlers | ||
| 2927 | You can define that certain URLs are browsed with other functions by | ||
| 2928 | customizing @code{browse-url-handlers}, an alist of regular | ||
| 2929 | expressions paired with functions to browse matching URLs. | ||
| 2930 | |||
| 2931 | For more information, view the package commentary by typing @kbd{C-h P | ||
| 2932 | browse-url @key{RET}}. | ||
| 2926 | 2933 | ||
| 2927 | @node Goto Address mode | 2934 | @node Goto Address mode |
| 2928 | @subsection Activating URLs | 2935 | @subsection Activating URLs |
| @@ -304,6 +304,22 @@ use ‘doxygen’ by default one might evaluate: | |||
| 304 | (c++-mode . doxygen))) | 304 | (c++-mode . doxygen))) |
| 305 | 305 | ||
| 306 | or use it in a custom ‘c-style’. | 306 | or use it in a custom ‘c-style’. |
| 307 | |||
| 308 | ** browse-url | ||
| 309 | |||
| 310 | *** Added support for custom URL handlers | ||
| 311 | |||
| 312 | There is a new defvar 'browse-url-default-handlers' and a defcustom | ||
| 313 | 'browse-url-handlers' being alists with (REGEXP . FUNCTION) entries | ||
| 314 | allowing to define different browsing FUNCTIONs depending on the URL | ||
| 315 | to be browsed. The defvar is for default handlers provided by Emacs | ||
| 316 | itself or external packages, the defcustom is for the user (and allows | ||
| 317 | for overriding the default handlers). | ||
| 318 | |||
| 319 | Formerly, one could do the same by setting | ||
| 320 | 'browse-url-browser-function' to such an alist. This usage is still | ||
| 321 | supported but deprecated. | ||
| 322 | |||
| 307 | 323 | ||
| 308 | * New Modes and Packages in Emacs 28.1 | 324 | * New Modes and Packages in Emacs 28.1 |
| 309 | 325 | ||
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 7aad44b2876..1275c15578f 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el | |||
| @@ -114,9 +114,10 @@ | |||
| 114 | ;; To always save modified buffers before displaying the file in a browser: | 114 | ;; To always save modified buffers before displaying the file in a browser: |
| 115 | ;; (setq browse-url-save-file t) | 115 | ;; (setq browse-url-save-file t) |
| 116 | 116 | ||
| 117 | ;; To invoke different browsers for different URLs: | 117 | ;; To invoke different browsers/tools for different URLs, customize |
| 118 | ;; (setq browse-url-browser-function '(("^mailto:" . browse-url-mail) | 118 | ;; `browse-url-handlers'. In earlier versions of Emacs, the same |
| 119 | ;; ("." . browse-url-firefox))) | 119 | ;; could be done by setting `browse-url-browser-function' to an alist |
| 120 | ;; but this usage is deprecated now. | ||
| 120 | 121 | ||
| 121 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 122 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 122 | ;;; Code: | 123 | ;;; Code: |
| @@ -157,7 +158,9 @@ | |||
| 157 | :value browse-url-default-browser) | 158 | :value browse-url-default-browser) |
| 158 | (function :tag "Your own function") | 159 | (function :tag "Your own function") |
| 159 | (alist :tag "Regexp/function association list" | 160 | (alist :tag "Regexp/function association list" |
| 160 | :key-type regexp :value-type function))) | 161 | :key-type regexp :value-type function |
| 162 | :format "%{%t%}\n%d%v\n" | ||
| 163 | :doc "Deprecated. Use `browse-url-handlers' instead."))) | ||
| 161 | 164 | ||
| 162 | ;;;###autoload | 165 | ;;;###autoload |
| 163 | (defcustom browse-url-browser-function 'browse-url-default-browser | 166 | (defcustom browse-url-browser-function 'browse-url-default-browser |
| @@ -165,13 +168,8 @@ | |||
| 165 | This is used by the `browse-url-at-point', `browse-url-at-mouse', and | 168 | This is used by the `browse-url-at-point', `browse-url-at-mouse', and |
| 166 | `browse-url-of-file' commands. | 169 | `browse-url-of-file' commands. |
| 167 | 170 | ||
| 168 | If the value is not a function it should be a list of pairs | 171 | Also see `browse-url-secondary-browser-function' and |
| 169 | \(REGEXP . FUNCTION). In this case the function called will be the one | 172 | `browse-url-handlers'." |
| 170 | associated with the first REGEXP which matches the current URL. The | ||
| 171 | function is passed the URL and any other args of `browse-url'. The last | ||
| 172 | regexp should probably be \".\" to specify a default browser. | ||
| 173 | |||
| 174 | Also see `browse-url-secondary-browser-function'." | ||
| 175 | :type browse-url--browser-defcustom-type | 173 | :type browse-url--browser-defcustom-type |
| 176 | :version "24.1") | 174 | :version "24.1") |
| 177 | 175 | ||
| @@ -595,6 +593,41 @@ down (this *won't* always work)." | |||
| 595 | "Wrapper command prepended to the Elinks command-line." | 593 | "Wrapper command prepended to the Elinks command-line." |
| 596 | :type '(repeat (string :tag "Wrapper"))) | 594 | :type '(repeat (string :tag "Wrapper"))) |
| 597 | 595 | ||
| 596 | (defun browse-url--mailto (url &rest args) | ||
| 597 | "Calls `browse-url-mailto-function' with URL and ARGS." | ||
| 598 | (funcall browse-url-mailto-function url args)) | ||
| 599 | |||
| 600 | (defun browse-url--man (url &rest args) | ||
| 601 | "Calls `browse-url-man-function' with URL and ARGS." | ||
| 602 | (funcall browse-url-man-function url args)) | ||
| 603 | |||
| 604 | ;;;###autoload | ||
| 605 | (defvar browse-url-default-handlers | ||
| 606 | '(("\\`mailto:" . browse-url--mailto) | ||
| 607 | ("\\`man:" . browse-url--man) | ||
| 608 | ("\\`file://" . browse-url-emacs)) | ||
| 609 | "Like `browse-url-handlers' but populated by Emacs and packages. | ||
| 610 | |||
| 611 | Emacs and external packages capable of browsing certain URLs | ||
| 612 | should place their entries in this alist rather than | ||
| 613 | `browse-url-handlers' which is reserved for the user.") | ||
| 614 | |||
| 615 | (defcustom browse-url-handlers nil | ||
| 616 | "An alist with elements of the form (REGEXP HANDLER). | ||
| 617 | Each REGEXP is matched against the URL to be opened in turn and | ||
| 618 | the first match's HANDLER is invoked with the URL. | ||
| 619 | |||
| 620 | A HANDLER must be a function with the same arguments as | ||
| 621 | `browse-url'. | ||
| 622 | |||
| 623 | If no REGEXP matches, the same procedure is performed with the | ||
| 624 | value of `browse-url-default-handlers'. If there is also no | ||
| 625 | match, the URL is opened using the value of | ||
| 626 | `browse-url-browser-function'." | ||
| 627 | :type '(alist :key-type (regexp :tag "Regexp") | ||
| 628 | :value-type (function :tag "Handler")) | ||
| 629 | :version "28.1") | ||
| 630 | |||
| 598 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 631 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 599 | ;; URL encoding | 632 | ;; URL encoding |
| 600 | 633 | ||
| @@ -768,16 +801,18 @@ narrowed." | |||
| 768 | "Ask a WWW browser to load URL. | 801 | "Ask a WWW browser to load URL. |
| 769 | Prompt for a URL, defaulting to the URL at or before point. | 802 | Prompt for a URL, defaulting to the URL at or before point. |
| 770 | Invokes a suitable browser function which does the actual job. | 803 | Invokes a suitable browser function which does the actual job. |
| 771 | The variable `browse-url-browser-function' says which browser function to | 804 | |
| 772 | use. If the URL is a mailto: URL, consult `browse-url-mailto-function' | 805 | The variables `browse-url-browser-function', |
| 773 | first, if that exists. | 806 | `browse-url-handlers', and `browse-url-default-handlers' |
| 774 | 807 | determine which browser function to use. | |
| 775 | The additional ARGS are passed to the browser function. See the doc | 808 | |
| 776 | strings of the actual functions, starting with `browse-url-browser-function', | 809 | The additional ARGS are passed to the browser function. See the |
| 777 | for information about the significance of ARGS (most of the functions | 810 | doc strings of the actual functions, starting with |
| 778 | ignore it). | 811 | `browse-url-browser-function', for information about the |
| 779 | If ARGS are omitted, the default is to pass `browse-url-new-window-flag' | 812 | significance of ARGS (most of the functions ignore it). |
| 780 | as ARGS." | 813 | |
| 814 | If ARGS are omitted, the default is to pass | ||
| 815 | `browse-url-new-window-flag' as ARGS." | ||
| 781 | (interactive (browse-url-interactive-arg "URL: ")) | 816 | (interactive (browse-url-interactive-arg "URL: ")) |
| 782 | (unless (called-interactively-p 'interactive) | 817 | (unless (called-interactively-p 'interactive) |
| 783 | (setq args (or args (list browse-url-new-window-flag)))) | 818 | (setq args (or args (list browse-url-new-window-flag)))) |
| @@ -786,12 +821,15 @@ as ARGS." | |||
| 786 | (not (string-match "\\`[a-z]+:" url))) | 821 | (not (string-match "\\`[a-z]+:" url))) |
| 787 | (setq url (expand-file-name url))) | 822 | (setq url (expand-file-name url))) |
| 788 | (let ((process-environment (copy-sequence process-environment)) | 823 | (let ((process-environment (copy-sequence process-environment)) |
| 789 | (function (or (and (string-match "\\`mailto:" url) | 824 | (function |
| 790 | browse-url-mailto-function) | 825 | (catch 'custom-url-handler |
| 791 | (and (string-match "\\`man:" url) | 826 | (dolist (regex-handler (append browse-url-handlers |
| 792 | browse-url-man-function) | 827 | browse-url-default-handlers)) |
| 793 | browse-url-browser-function)) | 828 | (when (string-match-p (car regex-handler) url) |
| 794 | ;; Ensure that `default-directory' exists and is readable (b#6077). | 829 | (throw 'custom-url-handler (cdr regex-handler)))) |
| 830 | ;; No special handler found. | ||
| 831 | browse-url-browser-function)) | ||
| 832 | ;; Ensure that `default-directory' exists and is readable (bug#6077). | ||
| 795 | (default-directory (or (unhandled-file-name-directory default-directory) | 833 | (default-directory (or (unhandled-file-name-directory default-directory) |
| 796 | (expand-file-name "~/")))) | 834 | (expand-file-name "~/")))) |
| 797 | ;; When connected to various displays, be careful to use the display of | 835 | ;; When connected to various displays, be careful to use the display of |
| @@ -801,15 +839,19 @@ as ARGS." | |||
| 801 | (setenv "DISPLAY" (frame-parameter nil 'display))) | 839 | (setenv "DISPLAY" (frame-parameter nil 'display))) |
| 802 | (if (and (consp function) | 840 | (if (and (consp function) |
| 803 | (not (functionp function))) | 841 | (not (functionp function))) |
| 804 | ;; The `function' can be an alist; look down it for first match | 842 | ;; The `function' can be an alist; look down it for first |
| 805 | ;; and apply the function (which might be a lambda). | 843 | ;; match and apply the function (which might be a lambda). |
| 806 | (catch 'done | 844 | ;; However, this usage is deprecated as of Emacs 28.1. |
| 807 | (dolist (bf function) | 845 | (progn |
| 808 | (when (string-match (car bf) url) | 846 | (warn "Having `browse-url-browser-function' set to an |
| 809 | (apply (cdr bf) url args) | 847 | alist is deprecated. Use `browse-url-handlers' instead.") |
| 810 | (throw 'done t))) | 848 | (catch 'done |
| 811 | (error "No browse-url-browser-function matching URL %s" | 849 | (dolist (bf function) |
| 812 | url)) | 850 | (when (string-match (car bf) url) |
| 851 | (apply (cdr bf) url args) | ||
| 852 | (throw 'done t))) | ||
| 853 | (error "No browse-url-browser-function matching URL %s" | ||
| 854 | url))) | ||
| 813 | ;; Unbound symbols go down this leg, since void-function from | 855 | ;; Unbound symbols go down this leg, since void-function from |
| 814 | ;; apply is clearer than wrong-type-argument from dolist. | 856 | ;; apply is clearer than wrong-type-argument from dolist. |
| 815 | (apply function url args)))) | 857 | (apply function url args)))) |