diff options
| author | Basil L. Contovounesios | 2020-05-06 18:02:32 +0100 |
|---|---|---|
| committer | Basil L. Contovounesios | 2020-05-22 16:28:20 +0100 |
| commit | 3a7894ecd11c66337e7aea8ade8f47673d290a24 (patch) | |
| tree | b3be04e3235bce5c8d408e765390df5d46bae692 | |
| parent | 3f082af536c33ba713561e7ad4b691aaad488701 (diff) | |
| download | emacs-3a7894ecd11c66337e7aea8ade8f47673d290a24.tar.gz emacs-3a7894ecd11c66337e7aea8ade8f47673d290a24.zip | |
Improve shr/eww handling of mailto URLs
* lisp/net/eww.el (eww): Use function-put in place of put, as
recommended in "(elisp) Symbol Plists".
(eww-follow-link):
* lisp/net/shr.el (shr-browse-url): Rather than call browse-url-mail
directly, call browse-url which respects the user options
browse-url-handlers and browse-url-mailto-function. (Bug#41133)
(shr--current-link-region): Return nil if there is no link at point.
(shr--blink-link): Adapt accordingly.
(shr-fill-line, shr-indent, shr-table-body): Refactor to avoid some
unnecessary allocations.
* etc/NEWS: Announce that eww-follow-link and shr-browse-url support
custom URL handlers.
| -rw-r--r-- | etc/NEWS | 18 | ||||
| -rw-r--r-- | lisp/net/eww.el | 30 | ||||
| -rw-r--r-- | lisp/net/shr.el | 84 |
3 files changed, 70 insertions, 62 deletions
| @@ -356,6 +356,24 @@ symbol property to the browsing functions. With a new command | |||
| 356 | 'browse-url-with-browser-kind', an URL can explicitly be browsed with | 356 | 'browse-url-with-browser-kind', an URL can explicitly be browsed with |
| 357 | either an internal or external browser. | 357 | either an internal or external browser. |
| 358 | 358 | ||
| 359 | ** SHR | ||
| 360 | |||
| 361 | --- | ||
| 362 | *** The command 'shr-browse-url' now supports custom mailto handlers. | ||
| 363 | Clicking on or otherwise following a 'mailto:' link in a HTML buffer | ||
| 364 | rendered by SHR previously invoked the command 'browse-url-mailto'. | ||
| 365 | This is still the case by default, but if you customize | ||
| 366 | 'browse-url-mailto-function' or 'browse-url-handlers' to call some | ||
| 367 | other function, it will now be called instead of the default. | ||
| 368 | |||
| 369 | ** EWW | ||
| 370 | |||
| 371 | --- | ||
| 372 | *** The command 'eww-follow-link' now supports custom mailto handlers. | ||
| 373 | The function that is invoked when clicking on or otherwise following a | ||
| 374 | 'mailto:' link in an EWW buffer can now be customized. For more | ||
| 375 | information, see the related entry about 'shr-browse-url' above. | ||
| 376 | |||
| 359 | ** Project | 377 | ** Project |
| 360 | 378 | ||
| 361 | *** New user option 'project-vc-merge-submodules'. | 379 | *** New user option 'project-vc-merge-submodules'. |
diff --git a/lisp/net/eww.el b/lisp/net/eww.el index a6c1abdbb19..2a70560ca7b 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el | |||
| @@ -307,10 +307,10 @@ the default EWW buffer." | |||
| 307 | (insert (format "Loading %s..." url)) | 307 | (insert (format "Loading %s..." url)) |
| 308 | (goto-char (point-min))) | 308 | (goto-char (point-min))) |
| 309 | (let ((url-mime-accept-string eww-accept-content-types)) | 309 | (let ((url-mime-accept-string eww-accept-content-types)) |
| 310 | (url-retrieve url 'eww-render | 310 | (url-retrieve url #'eww-render |
| 311 | (list url nil (current-buffer))))) | 311 | (list url nil (current-buffer))))) |
| 312 | 312 | ||
| 313 | (put 'eww 'browse-url-browser-kind 'internal) | 313 | (function-put 'eww 'browse-url-browser-kind 'internal) |
| 314 | 314 | ||
| 315 | (defun eww--dwim-expand-url (url) | 315 | (defun eww--dwim-expand-url (url) |
| 316 | (setq url (string-trim url)) | 316 | (setq url (string-trim url)) |
| @@ -375,8 +375,8 @@ engine used." | |||
| 375 | (let ((region-string (buffer-substring (region-beginning) (region-end)))) | 375 | (let ((region-string (buffer-substring (region-beginning) (region-end)))) |
| 376 | (if (not (string-match-p "\\`[ \n\t\r\v\f]*\\'" region-string)) | 376 | (if (not (string-match-p "\\`[ \n\t\r\v\f]*\\'" region-string)) |
| 377 | (eww region-string) | 377 | (eww region-string) |
| 378 | (call-interactively 'eww))) | 378 | (call-interactively #'eww))) |
| 379 | (call-interactively 'eww))) | 379 | (call-interactively #'eww))) |
| 380 | 380 | ||
| 381 | (defun eww-open-in-new-buffer () | 381 | (defun eww-open-in-new-buffer () |
| 382 | "Fetch link at point in a new EWW buffer." | 382 | "Fetch link at point in a new EWW buffer." |
| @@ -1013,7 +1013,7 @@ just re-display the HTML already fetched." | |||
| 1013 | (eww-display-html 'utf-8 url (plist-get eww-data :dom) | 1013 | (eww-display-html 'utf-8 url (plist-get eww-data :dom) |
| 1014 | (point) (current-buffer))) | 1014 | (point) (current-buffer))) |
| 1015 | (let ((url-mime-accept-string eww-accept-content-types)) | 1015 | (let ((url-mime-accept-string eww-accept-content-types)) |
| 1016 | (url-retrieve url 'eww-render | 1016 | (url-retrieve url #'eww-render |
| 1017 | (list url (point) (current-buffer) encode)))))) | 1017 | (list url (point) (current-buffer) encode)))))) |
| 1018 | 1018 | ||
| 1019 | ;; Form support. | 1019 | ;; Form support. |
| @@ -1576,8 +1576,10 @@ If EXTERNAL is double prefix, browse in new buffer." | |||
| 1576 | (cond | 1576 | (cond |
| 1577 | ((not url) | 1577 | ((not url) |
| 1578 | (message "No link under point")) | 1578 | (message "No link under point")) |
| 1579 | ((string-match "^mailto:" url) | 1579 | ((string-match-p "\\`mailto:" url) |
| 1580 | (browse-url-mail url)) | 1580 | ;; This respects the user options `browse-url-handlers' |
| 1581 | ;; and `browse-url-mailto-function'. | ||
| 1582 | (browse-url url)) | ||
| 1581 | ((and (consp external) (<= (car external) 4)) | 1583 | ((and (consp external) (<= (car external) 4)) |
| 1582 | (funcall browse-url-secondary-browser-function url) | 1584 | (funcall browse-url-secondary-browser-function url) |
| 1583 | (shr--blink-link)) | 1585 | (shr--blink-link)) |
| @@ -1615,7 +1617,7 @@ Use link at point if there is one, else the current page's URL." | |||
| 1615 | (eww-current-url)))) | 1617 | (eww-current-url)))) |
| 1616 | (if (not url) | 1618 | (if (not url) |
| 1617 | (message "No URL under point") | 1619 | (message "No URL under point") |
| 1618 | (url-retrieve url 'eww-download-callback (list url))))) | 1620 | (url-retrieve url #'eww-download-callback (list url))))) |
| 1619 | 1621 | ||
| 1620 | (defun eww-download-callback (status url) | 1622 | (defun eww-download-callback (status url) |
| 1621 | (unless (plist-get status :error) | 1623 | (unless (plist-get status :error) |
| @@ -2128,12 +2130,12 @@ entries (if any) will be removed from the list. | |||
| 2128 | Only the properties listed in `eww-desktop-data-save' are included. | 2130 | Only the properties listed in `eww-desktop-data-save' are included. |
| 2129 | Generally, the list should not include the (usually overly large) | 2131 | Generally, the list should not include the (usually overly large) |
| 2130 | :dom, :source and :text properties." | 2132 | :dom, :source and :text properties." |
| 2131 | (let ((history (mapcar 'eww-desktop-data-1 | 2133 | (let ((history (mapcar #'eww-desktop-data-1 |
| 2132 | (cons eww-data eww-history)))) | 2134 | (cons eww-data eww-history)))) |
| 2133 | (list :history (if eww-desktop-remove-duplicates | 2135 | (list :history (if eww-desktop-remove-duplicates |
| 2134 | (cl-remove-duplicates | 2136 | (cl-remove-duplicates |
| 2135 | history :test 'eww-desktop-history-duplicate) | 2137 | history :test #'eww-desktop-history-duplicate) |
| 2136 | history)))) | 2138 | history)))) |
| 2137 | 2139 | ||
| 2138 | (defun eww-restore-desktop (file-name buffer-name misc-data) | 2140 | (defun eww-restore-desktop (file-name buffer-name misc-data) |
| 2139 | "Restore an eww buffer from its desktop file record. | 2141 | "Restore an eww buffer from its desktop file record. |
diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 1f80ab74db5..03260c9e70a 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el | |||
| @@ -135,7 +135,7 @@ same domain as the main data." | |||
| 135 | This is used for cid: URLs, and the function is called with the | 135 | This is used for cid: URLs, and the function is called with the |
| 136 | cid: URL as the argument.") | 136 | cid: URL as the argument.") |
| 137 | 137 | ||
| 138 | (defvar shr-put-image-function 'shr-put-image | 138 | (defvar shr-put-image-function #'shr-put-image |
| 139 | "Function called to put image and alt string.") | 139 | "Function called to put image and alt string.") |
| 140 | 140 | ||
| 141 | (defface shr-strike-through '((t :strike-through t)) | 141 | (defface shr-strike-through '((t :strike-through t)) |
| @@ -365,25 +365,20 @@ If the URL is already at the front of the kill ring act like | |||
| 365 | (shr-copy-url url))) | 365 | (shr-copy-url url))) |
| 366 | 366 | ||
| 367 | (defun shr--current-link-region () | 367 | (defun shr--current-link-region () |
| 368 | (let ((current (get-text-property (point) 'shr-url)) | 368 | "Return the start and end positions of the URL at point, if any. |
| 369 | start) | 369 | Value is a pair of positions (START . END) if there is a non-nil |
| 370 | (save-excursion | 370 | `shr-url' text property at point; otherwise nil." |
| 371 | ;; Go to the beginning. | 371 | (when (get-text-property (point) 'shr-url) |
| 372 | (while (and (not (bobp)) | 372 | (let* ((end (or (next-single-property-change (point) 'shr-url) |
| 373 | (equal (get-text-property (point) 'shr-url) current)) | 373 | (point-max))) |
| 374 | (forward-char -1)) | 374 | (beg (or (previous-single-property-change end 'shr-url) |
| 375 | (unless (equal (get-text-property (point) 'shr-url) current) | 375 | (point-min)))) |
| 376 | (forward-char 1)) | 376 | (cons beg end)))) |
| 377 | (setq start (point)) | ||
| 378 | ;; Go to the end. | ||
| 379 | (while (and (not (eobp)) | ||
| 380 | (equal (get-text-property (point) 'shr-url) current)) | ||
| 381 | (forward-char 1)) | ||
| 382 | (list start (point))))) | ||
| 383 | 377 | ||
| 384 | (defun shr--blink-link () | 378 | (defun shr--blink-link () |
| 385 | (let* ((region (shr--current-link-region)) | 379 | "Briefly fontify URL at point with the face `shr-selected-link'." |
| 386 | (overlay (make-overlay (car region) (cadr region)))) | 380 | (when-let* ((region (shr--current-link-region)) |
| 381 | (overlay (make-overlay (car region) (cdr region)))) | ||
| 387 | (overlay-put overlay 'face 'shr-selected-link) | 382 | (overlay-put overlay 'face 'shr-selected-link) |
| 388 | (run-at-time 1 nil (lambda () | 383 | (run-at-time 1 nil (lambda () |
| 389 | (delete-overlay overlay))))) | 384 | (delete-overlay overlay))))) |
| @@ -437,7 +432,7 @@ the URL of the image to the kill buffer instead." | |||
| 437 | (if (not url) | 432 | (if (not url) |
| 438 | (message "No image under point") | 433 | (message "No image under point") |
| 439 | (message "Inserting %s..." url) | 434 | (message "Inserting %s..." url) |
| 440 | (url-retrieve url 'shr-image-fetched | 435 | (url-retrieve url #'shr-image-fetched |
| 441 | (list (current-buffer) (1- (point)) (point-marker)) | 436 | (list (current-buffer) (1- (point)) (point-marker)) |
| 442 | t)))) | 437 | t)))) |
| 443 | 438 | ||
| @@ -463,7 +458,7 @@ size, and full-buffer size." | |||
| 463 | (when (> (- (point) start) 2) | 458 | (when (> (- (point) start) 2) |
| 464 | (delete-region start (1- (point))))) | 459 | (delete-region start (1- (point))))) |
| 465 | (message "Inserting %s..." url) | 460 | (message "Inserting %s..." url) |
| 466 | (url-retrieve url 'shr-image-fetched | 461 | (url-retrieve url #'shr-image-fetched |
| 467 | (list (current-buffer) (1- (point)) (point-marker) | 462 | (list (current-buffer) (1- (point)) (point-marker) |
| 468 | (list (cons 'size | 463 | (list (cons 'size |
| 469 | (cond ((or (eq size 'default) | 464 | (cond ((or (eq size 'default) |
| @@ -493,7 +488,7 @@ size, and full-buffer size." | |||
| 493 | ((fboundp function) | 488 | ((fboundp function) |
| 494 | (apply function dom args)) | 489 | (apply function dom args)) |
| 495 | (t | 490 | (t |
| 496 | (apply 'shr-generic dom args))))) | 491 | (apply #'shr-generic dom args))))) |
| 497 | 492 | ||
| 498 | (defun shr-descend (dom) | 493 | (defun shr-descend (dom) |
| 499 | (let ((function | 494 | (let ((function |
| @@ -730,9 +725,10 @@ size, and full-buffer size." | |||
| 730 | (let ((gap-start (point)) | 725 | (let ((gap-start (point)) |
| 731 | (face (get-text-property (point) 'face))) | 726 | (face (get-text-property (point) 'face))) |
| 732 | ;; Extend the background to the end of the line. | 727 | ;; Extend the background to the end of the line. |
| 733 | (if face | 728 | (insert ?\n) |
| 734 | (insert (propertize "\n" 'face (shr-face-background face))) | 729 | (when face |
| 735 | (insert "\n")) | 730 | (put-text-property (1- (point)) (point) |
| 731 | 'face (shr-face-background face))) | ||
| 736 | (shr-indent) | 732 | (shr-indent) |
| 737 | (when (and (> (1- gap-start) (point-min)) | 733 | (when (and (> (1- gap-start) (point-min)) |
| 738 | (get-text-property (point) 'shr-url) | 734 | (get-text-property (point) 'shr-url) |
| @@ -935,12 +931,11 @@ size, and full-buffer size." | |||
| 935 | 931 | ||
| 936 | (defun shr-indent () | 932 | (defun shr-indent () |
| 937 | (when (> shr-indentation 0) | 933 | (when (> shr-indentation 0) |
| 938 | (insert | 934 | (if (not shr-use-fonts) |
| 939 | (if (not shr-use-fonts) | 935 | (insert-char ?\s shr-indentation) |
| 940 | (make-string shr-indentation ?\s) | 936 | (insert ?\s) |
| 941 | (propertize " " | 937 | (put-text-property (1- (point)) (point) |
| 942 | 'display | 938 | 'display `(space :width (,shr-indentation)))))) |
| 943 | `(space :width (,shr-indentation))))))) | ||
| 944 | 939 | ||
| 945 | (defun shr-fontize-dom (dom &rest types) | 940 | (defun shr-fontize-dom (dom &rest types) |
| 946 | (let ((start (point))) | 941 | (let ((start (point))) |
| @@ -987,16 +982,11 @@ the mouse click event." | |||
| 987 | (cond | 982 | (cond |
| 988 | ((not url) | 983 | ((not url) |
| 989 | (message "No link under point")) | 984 | (message "No link under point")) |
| 990 | ((string-match "^mailto:" url) | 985 | (external |
| 991 | (browse-url-mail url)) | 986 | (funcall browse-url-secondary-browser-function url) |
| 987 | (shr--blink-link)) | ||
| 992 | (t | 988 | (t |
| 993 | (if external | 989 | (browse-url url (xor new-window browse-url-new-window-flag)))))) |
| 994 | (progn | ||
| 995 | (funcall browse-url-secondary-browser-function url) | ||
| 996 | (shr--blink-link)) | ||
| 997 | (browse-url url (if new-window | ||
| 998 | (not browse-url-new-window-flag) | ||
| 999 | browse-url-new-window-flag))))))) | ||
| 1000 | 990 | ||
| 1001 | (defun shr-save-contents (directory) | 991 | (defun shr-save-contents (directory) |
| 1002 | "Save the contents from URL in a file." | 992 | "Save the contents from URL in a file." |
| @@ -1005,7 +995,7 @@ the mouse click event." | |||
| 1005 | (if (not url) | 995 | (if (not url) |
| 1006 | (message "No link under point") | 996 | (message "No link under point") |
| 1007 | (url-retrieve (shr-encode-url url) | 997 | (url-retrieve (shr-encode-url url) |
| 1008 | 'shr-store-contents (list url directory))))) | 998 | #'shr-store-contents (list url directory))))) |
| 1009 | 999 | ||
| 1010 | (defun shr-store-contents (status url directory) | 1000 | (defun shr-store-contents (status url directory) |
| 1011 | (unless (plist-get status :error) | 1001 | (unless (plist-get status :error) |
| @@ -1156,7 +1146,6 @@ width/height instead." | |||
| 1156 | 1146 | ||
| 1157 | ;; url-cache-extract autoloads url-cache. | 1147 | ;; url-cache-extract autoloads url-cache. |
| 1158 | (declare-function url-cache-create-filename "url-cache" (url)) | 1148 | (declare-function url-cache-create-filename "url-cache" (url)) |
| 1159 | (autoload 'browse-url-mail "browse-url") | ||
| 1160 | 1149 | ||
| 1161 | (defun shr-get-image-data (url) | 1150 | (defun shr-get-image-data (url) |
| 1162 | "Get image data for URL. | 1151 | "Get image data for URL. |
| @@ -1230,7 +1219,7 @@ START, and END. Note that START and END should be markers." | |||
| 1230 | (funcall shr-put-image-function | 1219 | (funcall shr-put-image-function |
| 1231 | image (buffer-substring start end)) | 1220 | image (buffer-substring start end)) |
| 1232 | (delete-region (point) end)))) | 1221 | (delete-region (point) end)))) |
| 1233 | (url-retrieve url 'shr-image-fetched | 1222 | (url-retrieve url #'shr-image-fetched |
| 1234 | (list (current-buffer) start end) | 1223 | (list (current-buffer) start end) |
| 1235 | t t))))) | 1224 | t t))))) |
| 1236 | 1225 | ||
| @@ -1679,7 +1668,7 @@ The preference is a float determined from `shr-prefer-media-type'." | |||
| 1679 | (or alt ""))) | 1668 | (or alt ""))) |
| 1680 | (insert " ") | 1669 | (insert " ") |
| 1681 | (url-queue-retrieve | 1670 | (url-queue-retrieve |
| 1682 | (shr-encode-url url) 'shr-image-fetched | 1671 | (shr-encode-url url) #'shr-image-fetched |
| 1683 | (list (current-buffer) start (set-marker (make-marker) (point)) | 1672 | (list (current-buffer) start (set-marker (make-marker) (point)) |
| 1684 | (list :width width :height height)) | 1673 | (list :width width :height height)) |
| 1685 | t | 1674 | t |
| @@ -2006,12 +1995,11 @@ BASE is the URL of the HTML being rendered." | |||
| 2006 | (cond | 1995 | (cond |
| 2007 | ((null tbodies) | 1996 | ((null tbodies) |
| 2008 | dom) | 1997 | dom) |
| 2009 | ((= (length tbodies) 1) | 1998 | ((null (cdr tbodies)) |
| 2010 | (car tbodies)) | 1999 | (car tbodies)) |
| 2011 | (t | 2000 | (t |
| 2012 | ;; Table with multiple tbodies. Convert into a single tbody. | 2001 | ;; Table with multiple tbodies. Convert into a single tbody. |
| 2013 | `(tbody nil ,@(cl-reduce 'append | 2002 | `(tbody nil ,@(mapcan #'dom-non-text-children tbodies)))))) |
| 2014 | (mapcar 'dom-non-text-children tbodies))))))) | ||
| 2015 | 2003 | ||
| 2016 | (defun shr--fix-tbody (tbody) | 2004 | (defun shr--fix-tbody (tbody) |
| 2017 | (nconc (list 'tbody (dom-attributes tbody)) | 2005 | (nconc (list 'tbody (dom-attributes tbody)) |
| @@ -2311,8 +2299,8 @@ flags that control whether to collect or render objects." | |||
| 2311 | (dolist (column row) | 2299 | (dolist (column row) |
| 2312 | (aset natural-widths i (max (aref natural-widths i) column)) | 2300 | (aset natural-widths i (max (aref natural-widths i) column)) |
| 2313 | (setq i (1+ i))))) | 2301 | (setq i (1+ i))))) |
| 2314 | (let ((extra (- (apply '+ (append suggested-widths nil)) | 2302 | (let ((extra (- (apply #'+ (append suggested-widths nil)) |
| 2315 | (apply '+ (append widths nil)) | 2303 | (apply #'+ (append widths nil)) |
| 2316 | (* shr-table-separator-pixel-width (1+ (length widths))))) | 2304 | (* shr-table-separator-pixel-width (1+ (length widths))))) |
| 2317 | (expanded-columns 0)) | 2305 | (expanded-columns 0)) |
| 2318 | ;; We have extra, unused space, so divide this space amongst the | 2306 | ;; We have extra, unused space, so divide this space amongst the |