diff options
| author | Lars Magne Ingebrigtsen | 2013-06-17 09:19:50 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2013-06-17 09:19:50 +0000 |
| commit | 7304e4dd67bb88abadf198f47e75cea971aaa5cc (patch) | |
| tree | 183bd9a84da52497ce1a012ab3ee0b6bdf3ccfb2 | |
| parent | d363bffbedce7027288fbe7f05040e4ff71ff4bc (diff) | |
| download | emacs-7304e4dd67bb88abadf198f47e75cea971aaa5cc.tar.gz emacs-7304e4dd67bb88abadf198f47e75cea971aaa5cc.zip | |
Convert shr.el from using overlays into using text properties
* eww.el (eww-mode-map): Use `shr-next-link' (etc) instead of the
widget commands, since we're no longer using widgets for links.
* mm-decode.el (mm-convert-shr-links): New function to convert
new-style shr URL links into widgets.
(mm-shr): Use it.
* shr.el (shr-next-link): New command.
(shr-previous-link): New command.
(shr-urlify): Don't use `widget-convert', because that's slow.
(shr-put-color-1): Use `add-face-text-property' instead of overlays,
because collecting the overlays and reapplying them when generating
tables is slow.
(shr-insert-table): Ditto.
| -rw-r--r-- | lisp/gnus/ChangeLog | 17 | ||||
| -rw-r--r-- | lisp/gnus/eww.el | 4 | ||||
| -rw-r--r-- | lisp/gnus/mm-decode.el | 15 | ||||
| -rw-r--r-- | lisp/gnus/shr.el | 130 |
4 files changed, 105 insertions, 61 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 8b0741bec6e..9552078ddb8 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,20 @@ | |||
| 1 | 2013-06-17 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 2 | |||
| 3 | * mm-decode.el (mm-convert-shr-links): New function to convert | ||
| 4 | new-style shr URL links into widgets. | ||
| 5 | (mm-shr): Use it. | ||
| 6 | |||
| 7 | * eww.el (eww-mode-map): Use `shr-next-link' (etc) instead of the | ||
| 8 | widget commands, since we're no longer using widgets for links. | ||
| 9 | |||
| 10 | * shr.el (shr-next-link): New command. | ||
| 11 | (shr-previous-link): New command. | ||
| 12 | (shr-urlify): Don't use `widget-convert', because that's slow. | ||
| 13 | (shr-put-color-1): Use `add-face-text-property' instead of overlays, | ||
| 14 | because collecting the overlays and reapplying them when generating | ||
| 15 | tables is slow. | ||
| 16 | (shr-insert-table): Ditto. | ||
| 17 | |||
| 1 | 2013-06-17 Stefan Monnier <monnier@iro.umontreal.ca> | 18 | 2013-06-17 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 19 | ||
| 3 | * sieve.el (sieve-edit-script): Avoid beginning-of-buffer. | 20 | * sieve.el (sieve-edit-script): Avoid beginning-of-buffer. |
diff --git a/lisp/gnus/eww.el b/lisp/gnus/eww.el index a79738a283f..6460ee79604 100644 --- a/lisp/gnus/eww.el +++ b/lisp/gnus/eww.el | |||
| @@ -206,8 +206,8 @@ | |||
| 206 | (suppress-keymap map) | 206 | (suppress-keymap map) |
| 207 | (define-key map "q" 'eww-quit) | 207 | (define-key map "q" 'eww-quit) |
| 208 | (define-key map "g" 'eww-reload) | 208 | (define-key map "g" 'eww-reload) |
| 209 | (define-key map [tab] 'widget-forward) | 209 | (define-key map [tab] 'shr-next-link) |
| 210 | (define-key map [backtab] 'widget-backward) | 210 | (define-key map [backtab] 'shr-previous-link) |
| 211 | (define-key map [delete] 'scroll-down-command) | 211 | (define-key map [delete] 'scroll-down-command) |
| 212 | (define-key map "\177" 'scroll-down-command) | 212 | (define-key map "\177" 'scroll-down-command) |
| 213 | (define-key map " " 'scroll-up-command) | 213 | (define-key map " " 'scroll-up-command) |
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el index b025f7cc601..948b2a2fd1c 100644 --- a/lisp/gnus/mm-decode.el +++ b/lisp/gnus/mm-decode.el | |||
| @@ -1809,6 +1809,7 @@ If RECURSIVE, search recursively." | |||
| 1809 | (libxml-parse-html-region (point-min) (point-max)))) | 1809 | (libxml-parse-html-region (point-min) (point-max)))) |
| 1810 | (unless (bobp) | 1810 | (unless (bobp) |
| 1811 | (insert "\n")) | 1811 | (insert "\n")) |
| 1812 | (mm-convert-shr-links) | ||
| 1812 | (mm-handle-set-undisplayer | 1813 | (mm-handle-set-undisplayer |
| 1813 | handle | 1814 | handle |
| 1814 | `(lambda () | 1815 | `(lambda () |
| @@ -1816,6 +1817,20 @@ If RECURSIVE, search recursively." | |||
| 1816 | (delete-region ,(point-min-marker) | 1817 | (delete-region ,(point-min-marker) |
| 1817 | ,(point-max-marker)))))))) | 1818 | ,(point-max-marker)))))))) |
| 1818 | 1819 | ||
| 1820 | (defun mm-convert-shr-links () | ||
| 1821 | (let ((start (point-min)) | ||
| 1822 | end) | ||
| 1823 | (while (and start | ||
| 1824 | (< start (point-max))) | ||
| 1825 | (when (setq start (text-property-not-all start (point-max) 'shr-url nil)) | ||
| 1826 | (setq end (next-single-property-change start 'shr-url nil (point-max))) | ||
| 1827 | (widget-convert-button | ||
| 1828 | 'url-link start end | ||
| 1829 | :help-echo (get-text-property start 'help-echo) | ||
| 1830 | :keymap shr-map | ||
| 1831 | (get-text-property start 'shr-url)) | ||
| 1832 | (setq start end))))) | ||
| 1833 | |||
| 1819 | (defun mm-handle-filename (handle) | 1834 | (defun mm-handle-filename (handle) |
| 1820 | "Return filename of HANDLE if any." | 1835 | "Return filename of HANDLE if any." |
| 1821 | (or (mail-content-type-get (mm-handle-type handle) | 1836 | (or (mail-content-type-get (mm-handle-type handle) |
diff --git a/lisp/gnus/shr.el b/lisp/gnus/shr.el index be8ffb02581..b394607dbff 100644 --- a/lisp/gnus/shr.el +++ b/lisp/gnus/shr.el | |||
| @@ -131,6 +131,8 @@ cid: URL as the argument.") | |||
| 131 | (define-key map "a" 'shr-show-alt-text) | 131 | (define-key map "a" 'shr-show-alt-text) |
| 132 | (define-key map "i" 'shr-browse-image) | 132 | (define-key map "i" 'shr-browse-image) |
| 133 | (define-key map "z" 'shr-zoom-image) | 133 | (define-key map "z" 'shr-zoom-image) |
| 134 | (define-key map [tab] 'shr-next-link) | ||
| 135 | (define-key map [backtab] 'shr-previous-link) | ||
| 134 | (define-key map "I" 'shr-insert-image) | 136 | (define-key map "I" 'shr-insert-image) |
| 135 | (define-key map "u" 'shr-copy-url) | 137 | (define-key map "u" 'shr-copy-url) |
| 136 | (define-key map "v" 'shr-browse-url) | 138 | (define-key map "v" 'shr-browse-url) |
| @@ -217,6 +219,40 @@ redirects somewhere else." | |||
| 217 | (copy-region-as-kill (point-min) (point-max)) | 219 | (copy-region-as-kill (point-min) (point-max)) |
| 218 | (message "Copied %s" url)))))) | 220 | (message "Copied %s" url)))))) |
| 219 | 221 | ||
| 222 | (defun shr-next-link () | ||
| 223 | "Skip to the next link." | ||
| 224 | (interactive) | ||
| 225 | (let ((skip (text-property-any (point) (point-max) 'shr-url nil))) | ||
| 226 | (if (not (setq skip (text-property-not-all skip (point-max) | ||
| 227 | 'shr-url nil))) | ||
| 228 | (message "No next link") | ||
| 229 | (goto-char skip) | ||
| 230 | (message "%s" (get-text-property (point) 'help-echo))))) | ||
| 231 | |||
| 232 | (defun shr-previous-link () | ||
| 233 | "Skip to the previous link." | ||
| 234 | (interactive) | ||
| 235 | (let ((start (point)) | ||
| 236 | (found nil)) | ||
| 237 | ;; Skip past the current link. | ||
| 238 | (while (and (not (bobp)) | ||
| 239 | (get-text-property (point) 'shr-url)) | ||
| 240 | (forward-char -1)) | ||
| 241 | ;; Find the previous link. | ||
| 242 | (while (and (not (bobp)) | ||
| 243 | (not (setq found (get-text-property (point) 'shr-url)))) | ||
| 244 | (forward-char -1)) | ||
| 245 | (if (not found) | ||
| 246 | (progn | ||
| 247 | (message "No previous link") | ||
| 248 | (goto-char start)) | ||
| 249 | ;; Put point at the start of the link. | ||
| 250 | (while (and (not (bobp)) | ||
| 251 | (get-text-property (point) 'shr-url)) | ||
| 252 | (forward-char -1)) | ||
| 253 | (forward-char 1) | ||
| 254 | (message "%s" (get-text-property (point) 'help-echo))))) | ||
| 255 | |||
| 220 | (defun shr-show-alt-text () | 256 | (defun shr-show-alt-text () |
| 221 | "Show the ALT text of the image under point." | 257 | "Show the ALT text of the image under point." |
| 222 | (interactive) | 258 | (interactive) |
| @@ -578,17 +614,16 @@ size, and full-buffer size." | |||
| 578 | (overlay-put overlay 'evaporate t) | 614 | (overlay-put overlay 'evaporate t) |
| 579 | overlay)) | 615 | overlay)) |
| 580 | 616 | ||
| 581 | ;; Add an overlay in the region, but avoid putting the font properties | 617 | ;; Add face to the region, but avoid putting the font properties on |
| 582 | ;; on blank text at the start of the line, and the newline at the end, | 618 | ;; blank text at the start of the line, and the newline at the end, to |
| 583 | ;; to avoid ugliness. | 619 | ;; avoid ugliness. |
| 584 | (defun shr-add-font (start end type) | 620 | (defun shr-add-font (start end type) |
| 585 | (save-excursion | 621 | (save-excursion |
| 586 | (goto-char start) | 622 | (goto-char start) |
| 587 | (while (< (point) end) | 623 | (while (< (point) end) |
| 588 | (when (bolp) | 624 | (when (bolp) |
| 589 | (skip-chars-forward " ")) | 625 | (skip-chars-forward " ")) |
| 590 | (let ((overlay (shr-make-overlay (point) (min (line-end-position) end)))) | 626 | (add-face-text-property (point) (min (line-end-position) end) type) |
| 591 | (overlay-put overlay 'face type)) | ||
| 592 | (if (< (line-end-position) end) | 627 | (if (< (line-end-position) end) |
| 593 | (forward-line 1) | 628 | (forward-line 1) |
| 594 | (goto-char end))))) | 629 | (goto-char end))))) |
| @@ -678,10 +713,7 @@ size, and full-buffer size." | |||
| 678 | (> (car (image-size image t)) 400)) | 713 | (> (car (image-size image t)) 400)) |
| 679 | (insert "\n")) | 714 | (insert "\n")) |
| 680 | (if (eq size 'original) | 715 | (if (eq size 'original) |
| 681 | (let ((overlays (overlays-at (point)))) | 716 | (insert-sliced-image image (or alt "*") nil 20 1) |
| 682 | (insert-sliced-image image (or alt "*") nil 20 1) | ||
| 683 | (dolist (overlay overlays) | ||
| 684 | (overlay-put overlay 'face 'default))) | ||
| 685 | (insert-image image (or alt "*"))) | 717 | (insert-image image (or alt "*"))) |
| 686 | (put-text-property start (point) 'image-size size) | 718 | (put-text-property start (point) 'image-size size) |
| 687 | (when (cond ((fboundp 'image-multi-frame-p) | 719 | (when (cond ((fboundp 'image-multi-frame-p) |
| @@ -769,16 +801,13 @@ START, and END. Note that START and END should be markers." | |||
| 769 | (apply #'shr-fontize-cont cont types) | 801 | (apply #'shr-fontize-cont cont types) |
| 770 | (shr-ensure-paragraph)) | 802 | (shr-ensure-paragraph)) |
| 771 | 803 | ||
| 772 | (autoload 'widget-convert-button "wid-edit") | ||
| 773 | |||
| 774 | (defun shr-urlify (start url &optional title) | 804 | (defun shr-urlify (start url &optional title) |
| 775 | (widget-convert-button | ||
| 776 | 'url-link start (point) | ||
| 777 | :help-echo (if title (format "%s (%s)" url title) url) | ||
| 778 | :keymap shr-map | ||
| 779 | url) | ||
| 780 | (shr-add-font start (point) 'shr-link) | 805 | (shr-add-font start (point) 'shr-link) |
| 781 | (put-text-property start (point) 'shr-url url)) | 806 | (add-text-properties |
| 807 | start (point) | ||
| 808 | (list 'shr-url url | ||
| 809 | 'local-map shr-map | ||
| 810 | 'help-echo (if title (format "%s (%s)" url title) url)))) | ||
| 782 | 811 | ||
| 783 | (defun shr-encode-url (url) | 812 | (defun shr-encode-url (url) |
| 784 | "Encode URL." | 813 | "Encode URL." |
| @@ -860,7 +889,7 @@ ones, in case fg and bg are nil." | |||
| 860 | (when (and (< (setq column (current-column)) width) | 889 | (when (and (< (setq column (current-column)) width) |
| 861 | (< (setq column (shr-previous-newline-padding-width column)) | 890 | (< (setq column (shr-previous-newline-padding-width column)) |
| 862 | width)) | 891 | width)) |
| 863 | (let ((overlay (shr-make-overlay (point) (1+ (point))))) | 892 | (let ((overlay (make-overlay (point) (1+ (point))))) |
| 864 | (overlay-put overlay 'before-string | 893 | (overlay-put overlay 'before-string |
| 865 | (concat | 894 | (concat |
| 866 | (mapconcat | 895 | (mapconcat |
| @@ -898,8 +927,7 @@ ones, in case fg and bg are nil." | |||
| 898 | (while (< start end) | 927 | (while (< start end) |
| 899 | (setq change (next-single-property-change start 'face nil end)) | 928 | (setq change (next-single-property-change start 'face nil end)) |
| 900 | (when do-put | 929 | (when do-put |
| 901 | (put-text-property start change 'face | 930 | (add-face-text-property start change (list type color))) |
| 902 | (nconc (list type color) old-props))) | ||
| 903 | (setq old-props (get-text-property change 'face)) | 931 | (setq old-props (get-text-property change 'face)) |
| 904 | (setq do-put (and (listp old-props) | 932 | (setq do-put (and (listp old-props) |
| 905 | (not (memq type old-props)))) | 933 | (not (memq type old-props)))) |
| @@ -1172,10 +1200,9 @@ ones, in case fg and bg are nil." | |||
| 1172 | (defun shr-tag-span (cont) | 1200 | (defun shr-tag-span (cont) |
| 1173 | (let ((title (cdr (assq :title cont)))) | 1201 | (let ((title (cdr (assq :title cont)))) |
| 1174 | (shr-generic cont) | 1202 | (shr-generic cont) |
| 1175 | (when title | 1203 | (when (and title |
| 1176 | (when shr-start | 1204 | shr-start) |
| 1177 | (let ((overlay (shr-make-overlay shr-start (point)))) | 1205 | (put-text-property shr-start (point) 'help-echo title)))) |
| 1178 | (overlay-put overlay 'help-echo title)))))) | ||
| 1179 | 1206 | ||
| 1180 | (defun shr-tag-h1 (cont) | 1207 | (defun shr-tag-h1 (cont) |
| 1181 | (shr-heading cont 'bold 'underline)) | 1208 | (shr-heading cont 'bold 'underline)) |
| @@ -1341,19 +1368,10 @@ ones, in case fg and bg are nil." | |||
| 1341 | (insert shr-table-vertical-line "\n")) | 1368 | (insert shr-table-vertical-line "\n")) |
| 1342 | (dolist (column row) | 1369 | (dolist (column row) |
| 1343 | (goto-char start) | 1370 | (goto-char start) |
| 1344 | (let ((lines (nth 2 column)) | 1371 | (let ((lines (nth 2 column))) |
| 1345 | (overlay-lines (nth 3 column)) | ||
| 1346 | overlay overlay-line) | ||
| 1347 | (dolist (line lines) | 1372 | (dolist (line lines) |
| 1348 | (setq overlay-line (pop overlay-lines)) | ||
| 1349 | (end-of-line) | 1373 | (end-of-line) |
| 1350 | (insert line shr-table-vertical-line) | 1374 | (insert line shr-table-vertical-line) |
| 1351 | (dolist (overlay overlay-line) | ||
| 1352 | (let ((o (shr-make-overlay (- (point) (nth 0 overlay) 1) | ||
| 1353 | (- (point) (nth 1 overlay) 1))) | ||
| 1354 | (properties (nth 2 overlay))) | ||
| 1355 | (while properties | ||
| 1356 | (overlay-put o (pop properties) (pop properties))))) | ||
| 1357 | (forward-line 1)) | 1375 | (forward-line 1)) |
| 1358 | ;; Add blank lines at padding at the bottom of the TD, | 1376 | ;; Add blank lines at padding at the bottom of the TD, |
| 1359 | ;; possibly. | 1377 | ;; possibly. |
| @@ -1441,7 +1459,7 @@ ones, in case fg and bg are nil." | |||
| 1441 | (fgcolor (cdr (assq :fgcolor cont))) | 1459 | (fgcolor (cdr (assq :fgcolor cont))) |
| 1442 | (style (cdr (assq :style cont))) | 1460 | (style (cdr (assq :style cont))) |
| 1443 | (shr-stylesheet shr-stylesheet) | 1461 | (shr-stylesheet shr-stylesheet) |
| 1444 | overlays actual-colors) | 1462 | actual-colors) |
| 1445 | (when style | 1463 | (when style |
| 1446 | (setq style (and (string-match "color" style) | 1464 | (setq style (and (string-match "color" style) |
| 1447 | (shr-parse-style style)))) | 1465 | (shr-parse-style style)))) |
| @@ -1489,7 +1507,7 @@ ones, in case fg and bg are nil." | |||
| 1489 | (list max | 1507 | (list max |
| 1490 | (count-lines (point-min) (point-max)) | 1508 | (count-lines (point-min) (point-max)) |
| 1491 | (split-string (buffer-string) "\n") | 1509 | (split-string (buffer-string) "\n") |
| 1492 | (shr-collect-overlays) | 1510 | nil |
| 1493 | (car actual-colors)) | 1511 | (car actual-colors)) |
| 1494 | max))))) | 1512 | max))))) |
| 1495 | 1513 | ||
| @@ -1502,29 +1520,6 @@ ones, in case fg and bg are nil." | |||
| 1502 | (forward-line 1)) | 1520 | (forward-line 1)) |
| 1503 | max)) | 1521 | max)) |
| 1504 | 1522 | ||
| 1505 | (defun shr-collect-overlays () | ||
| 1506 | (save-excursion | ||
| 1507 | (goto-char (point-min)) | ||
| 1508 | (let ((overlays nil)) | ||
| 1509 | (while (not (eobp)) | ||
| 1510 | (push (shr-overlays-in-region (point) (line-end-position)) | ||
| 1511 | overlays) | ||
| 1512 | (forward-line 1)) | ||
| 1513 | (nreverse overlays)))) | ||
| 1514 | |||
| 1515 | (defun shr-overlays-in-region (start end) | ||
| 1516 | (let (result) | ||
| 1517 | (dolist (overlay (overlays-in start end)) | ||
| 1518 | (push (list (if (> start (overlay-start overlay)) | ||
| 1519 | (- end start) | ||
| 1520 | (- end (overlay-start overlay))) | ||
| 1521 | (if (< end (overlay-end overlay)) | ||
| 1522 | 0 | ||
| 1523 | (- end (overlay-end overlay))) | ||
| 1524 | (overlay-properties overlay)) | ||
| 1525 | result)) | ||
| 1526 | (nreverse result))) | ||
| 1527 | |||
| 1528 | (defun shr-pro-rate-columns (columns) | 1523 | (defun shr-pro-rate-columns (columns) |
| 1529 | (let ((total-percentage 0) | 1524 | (let ((total-percentage 0) |
| 1530 | (widths (make-vector (length columns) 0))) | 1525 | (widths (make-vector (length columns) 0))) |
| @@ -1570,6 +1565,23 @@ ones, in case fg and bg are nil." | |||
| 1570 | (shr-count (cdr row) 'th)))))) | 1565 | (shr-count (cdr row) 'th)))))) |
| 1571 | max)) | 1566 | max)) |
| 1572 | 1567 | ||
| 1568 | ;; Emacs less than 24.3 | ||
| 1569 | (unless (fboundp 'add-face-text-property) | ||
| 1570 | (defun add-face-text-property (beg end face) | ||
| 1571 | "Combine FACE BEG and END." | ||
| 1572 | (let ((b beg)) | ||
| 1573 | (while (< b end) | ||
| 1574 | (let ((oldval (get-text-property b 'face))) | ||
| 1575 | (put-text-property | ||
| 1576 | b (setq b (next-single-property-change b 'face nil end)) | ||
| 1577 | 'face (cond ((null oldval) | ||
| 1578 | face) | ||
| 1579 | ((and (consp oldval) | ||
| 1580 | (not (keywordp (car oldval)))) | ||
| 1581 | (cons face oldval)) | ||
| 1582 | (t | ||
| 1583 | (list face oldval))))))))) | ||
| 1584 | |||
| 1573 | (provide 'shr) | 1585 | (provide 'shr) |
| 1574 | 1586 | ||
| 1575 | ;; Local Variables: | 1587 | ;; Local Variables: |