diff options
| author | Stefan Monnier | 2019-05-02 09:00:53 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2019-05-02 09:00:53 -0400 |
| commit | 0efaae78f2b66de7ebeff7d1c16771ddafdf2d06 (patch) | |
| tree | bd1c649ff6001c334bf5976113952a1da492a730 | |
| parent | cd3a7f35de8b0f39524912529d6fceda26571276 (diff) | |
| download | emacs-0efaae78f2b66de7ebeff7d1c16771ddafdf2d06.tar.gz emacs-0efaae78f2b66de7ebeff7d1c16771ddafdf2d06.zip | |
* lisp/mail/footnote.el: Use dolist and hoist regexps out of loops
(footnote--refresh-footnotes): Use pcase-dolist; compute regexp once
outside of the loops. Use less confusing `literal` arg to `replace-match`
and specify `fixedcase` since footnote--index-to-string already chose
the proper case for us.
(footnote--renumber): Use dolist; compute regexp once
outside of the loops; shortcircuit when number is unchanged.
(footnote--text-under-cursor): Rewrite.
(footnote--make-hole): Use dolist.
(footnote-add-footnote): CSE.
(footnote-delete-footnote): Use dolist; compute regexp once
outside of the loop.
(footnote-delete-footnote): Don't renumber if there's no footnote left.
(footnote-renumber-footnotes): Use dolist.
| -rw-r--r-- | lisp/mail/footnote.el | 183 |
1 files changed, 77 insertions, 106 deletions
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el index ef359b62b40..9a918376e67 100644 --- a/lisp/mail/footnote.el +++ b/lisp/mail/footnote.el | |||
| @@ -164,7 +164,9 @@ left with the first character of footnote text." | |||
| 164 | "List of (FN TEXT . POINTERS). | 164 | "List of (FN TEXT . POINTERS). |
| 165 | Where FN is the footnote number, TEXT is a marker pointing to | 165 | Where FN is the footnote number, TEXT is a marker pointing to |
| 166 | the footnote's text, and POINTERS is a list of markers pointing | 166 | the footnote's text, and POINTERS is a list of markers pointing |
| 167 | to the places from which the footnote is referenced.") | 167 | to the places from which the footnote is referenced. |
| 168 | TEXT points right *before* the [...] and POINTERS point right | ||
| 169 | *after* the [...].") | ||
| 168 | 170 | ||
| 169 | (defvar footnote-mouse-highlight 'highlight | 171 | (defvar footnote-mouse-highlight 'highlight |
| 170 | ;; FIXME: This `highlight' property is not currently used. | 172 | ;; FIXME: This `highlight' property is not currently used. |
| @@ -452,52 +454,41 @@ Conversion is done based upon the current selected style." | |||
| 452 | 454 | ||
| 453 | (defun footnote--refresh-footnotes (&optional index-regexp) | 455 | (defun footnote--refresh-footnotes (&optional index-regexp) |
| 454 | "Redraw all footnotes. | 456 | "Redraw all footnotes. |
| 455 | You must call this or arrange to have this called after changing footnote | 457 | You must call this or arrange to have this called after changing |
| 456 | styles." | 458 | footnote styles." |
| 457 | (unless index-regexp | 459 | (let ((fn-regexp (concat |
| 458 | (setq index-regexp (footnote--current-regexp))) | 460 | (regexp-quote footnote-start-tag) |
| 459 | (save-excursion | 461 | "\\(" (or index-regexp (footnote--current-regexp)) "+\\)" |
| 460 | ;; Take care of the pointers first | 462 | (regexp-quote footnote-end-tag)))) |
| 461 | (let ((i 0) locn alist) | 463 | (save-excursion |
| 462 | (while (setq alist (nth i footnote--markers-alist)) | 464 | (pcase-dolist (`(,fn ,text . ,pointers) footnote--markers-alist) |
| 463 | (setq locn (cddr alist)) | 465 | ;; Take care of the pointers first |
| 464 | (while locn | 466 | (dolist (locn pointers) |
| 465 | (goto-char (car locn)) | 467 | (goto-char locn) |
| 466 | ;; Try to handle the case where `footnote-start-tag' and | 468 | ;; Try to handle the case where `footnote-start-tag' and |
| 467 | ;; `footnote-end-tag' are the same string. | 469 | ;; `footnote-end-tag' are the same string. |
| 468 | (when (looking-back (concat | 470 | (when (looking-back fn-regexp |
| 469 | (regexp-quote footnote-start-tag) | ||
| 470 | "\\(" index-regexp "+\\)" | ||
| 471 | (regexp-quote footnote-end-tag)) | ||
| 472 | (line-beginning-position)) | 471 | (line-beginning-position)) |
| 473 | (replace-match | 472 | (replace-match |
| 474 | (propertize | 473 | (propertize |
| 475 | (concat | 474 | (concat |
| 476 | footnote-start-tag | 475 | footnote-start-tag |
| 477 | (footnote--index-to-string (1+ i)) | 476 | (footnote--index-to-string fn) |
| 478 | footnote-end-tag) | 477 | footnote-end-tag) |
| 479 | 'footnote-number (1+ i) footnote-mouse-highlight t) | 478 | 'footnote-number fn footnote-mouse-highlight t) |
| 480 | nil "\\1")) | 479 | t t))) |
| 481 | (setq locn (cdr locn))) | 480 | |
| 482 | (setq i (1+ i)))) | 481 | ;; Now take care of the text section |
| 483 | 482 | (goto-char text) | |
| 484 | ;; Now take care of the text section | 483 | (when (looking-at fn-regexp) |
| 485 | (let ((i 0) alist) | ||
| 486 | (while (setq alist (nth i footnote--markers-alist)) | ||
| 487 | (goto-char (cadr alist)) | ||
| 488 | (when (looking-at (concat | ||
| 489 | (regexp-quote footnote-start-tag) | ||
| 490 | "\\(" index-regexp "+\\)" | ||
| 491 | (regexp-quote footnote-end-tag))) | ||
| 492 | (replace-match | 484 | (replace-match |
| 493 | (propertize | 485 | (propertize |
| 494 | (concat | 486 | (concat |
| 495 | footnote-start-tag | 487 | footnote-start-tag |
| 496 | (footnote--index-to-string (1+ i)) | 488 | (footnote--index-to-string fn) |
| 497 | footnote-end-tag) | 489 | footnote-end-tag) |
| 498 | 'footnote-number (1+ i)) | 490 | 'footnote-number fn) |
| 499 | nil "\\1")) | 491 | t t)))))) |
| 500 | (setq i (1+ i)))))) | ||
| 501 | 492 | ||
| 502 | (defun footnote-cycle-style () | 493 | (defun footnote-cycle-style () |
| 503 | "Select next defined footnote style." | 494 | "Select next defined footnote style." |
| @@ -532,31 +523,28 @@ styles." | |||
| 532 | 523 | ||
| 533 | (defun footnote--renumber (to alist-elem) | 524 | (defun footnote--renumber (to alist-elem) |
| 534 | "Renumber a single footnote." | 525 | "Renumber a single footnote." |
| 535 | (let* ((posn-list (cddr alist-elem))) | 526 | (unless (equal to (car alist-elem)) ;Nothing to do. |
| 536 | (setcar alist-elem to) | 527 | (let* ((fn-regexp (concat (regexp-quote footnote-start-tag) |
| 537 | (while posn-list | 528 | (footnote--current-regexp) |
| 538 | (goto-char (car posn-list)) | 529 | (regexp-quote footnote-end-tag)))) |
| 539 | (when (looking-back (concat (regexp-quote footnote-start-tag) | 530 | (setcar alist-elem to) |
| 540 | (footnote--current-regexp) | 531 | (dolist (posn (cddr alist-elem)) |
| 541 | (regexp-quote footnote-end-tag)) | 532 | (goto-char posn) |
| 542 | (line-beginning-position)) | 533 | (when (looking-back fn-regexp (line-beginning-position)) |
| 543 | (replace-match | 534 | (replace-match |
| 544 | (propertize | 535 | (propertize |
| 536 | (concat footnote-start-tag | ||
| 537 | (footnote--index-to-string to) | ||
| 538 | footnote-end-tag) | ||
| 539 | 'footnote-number to footnote-mouse-highlight t)))) | ||
| 540 | (goto-char (cadr alist-elem)) | ||
| 541 | (when (looking-at fn-regexp) | ||
| 542 | (replace-match | ||
| 543 | (propertize | ||
| 545 | (concat footnote-start-tag | 544 | (concat footnote-start-tag |
| 546 | (footnote--index-to-string to) | 545 | (footnote--index-to-string to) |
| 547 | footnote-end-tag) | 546 | footnote-end-tag) |
| 548 | 'footnote-number to footnote-mouse-highlight t))) | 547 | 'footnote-number to)))))) |
| 549 | (setq posn-list (cdr posn-list))) | ||
| 550 | (goto-char (cadr alist-elem)) | ||
| 551 | (when (looking-at (concat (regexp-quote footnote-start-tag) | ||
| 552 | (footnote--current-regexp) | ||
| 553 | (regexp-quote footnote-end-tag))) | ||
| 554 | (replace-match | ||
| 555 | (propertize | ||
| 556 | (concat footnote-start-tag | ||
| 557 | (footnote--index-to-string to) | ||
| 558 | footnote-end-tag) | ||
| 559 | 'footnote-number to))))) | ||
| 560 | 548 | ||
| 561 | (defun footnote--narrow-to-footnotes () | 549 | (defun footnote--narrow-to-footnotes () |
| 562 | "Restrict text in buffer to show only text of footnotes." | 550 | "Restrict text in buffer to show only text of footnotes." |
| @@ -652,18 +640,11 @@ Presumes we're within the footnote area already." | |||
| 652 | "Return the number of the current footnote if in footnote text. | 640 | "Return the number of the current footnote if in footnote text. |
| 653 | Return nil if the cursor is not positioned over the text of | 641 | Return nil if the cursor is not positioned over the text of |
| 654 | a footnote." | 642 | a footnote." |
| 655 | (when (and footnote--markers-alist | 643 | (when (<= (point) (footnote--get-area-point-max)) |
| 656 | (<= (footnote--get-area-point-min) | 644 | (let ((result nil)) |
| 657 | (point) | 645 | (pcase-dolist (`(,fn ,text . ,_) footnote--markers-alist) |
| 658 | (footnote--get-area-point-max))) | 646 | (if (<= text (point)) |
| 659 | (let ((i 1) alist-txt result) | 647 | (setq result fn))) |
| 660 | (while (and (setq alist-txt (nth i footnote--markers-alist)) | ||
| 661 | (null result)) | ||
| 662 | (when (< (point) (cadr alist-txt)) | ||
| 663 | (setq result (car (nth (1- i) footnote--markers-alist)))) | ||
| 664 | (setq i (1+ i))) | ||
| 665 | (when (and (null result) (null alist-txt)) | ||
| 666 | (setq result (car (nth (1- i) footnote--markers-alist)))) | ||
| 667 | result))) | 648 | result))) |
| 668 | 649 | ||
| 669 | (defun footnote--under-cursor () | 650 | (defun footnote--under-cursor () |
| @@ -750,11 +731,8 @@ footnote area, returns `point-max'." | |||
| 750 | 731 | ||
| 751 | (defun footnote--make-hole () | 732 | (defun footnote--make-hole () |
| 752 | (save-excursion | 733 | (save-excursion |
| 753 | (let ((i 0) | 734 | (let (rc) |
| 754 | (notes (length footnote--markers-alist)) | 735 | (dolist (alist-elem footnote--markers-alist) |
| 755 | alist-elem rc) | ||
| 756 | (while (< i notes) | ||
| 757 | (setq alist-elem (nth i footnote--markers-alist)) | ||
| 758 | (when (< (point) (- (cl-caddr alist-elem) 3)) | 736 | (when (< (point) (- (cl-caddr alist-elem) 3)) |
| 759 | (unless rc | 737 | (unless rc |
| 760 | (setq rc (car alist-elem))) | 738 | (setq rc (car alist-elem))) |
| @@ -764,8 +742,7 @@ footnote area, returns `point-max'." | |||
| 764 | (footnote--index-to-string | 742 | (footnote--index-to-string |
| 765 | (1+ (car alist-elem)))) | 743 | (1+ (car alist-elem)))) |
| 766 | (footnote--renumber (1+ (car alist-elem)) | 744 | (footnote--renumber (1+ (car alist-elem)) |
| 767 | alist-elem))) | 745 | alist-elem)))) |
| 768 | (setq i (1+ i))) | ||
| 769 | rc))) | 746 | rc))) |
| 770 | 747 | ||
| 771 | (defun footnote-add-footnote () | 748 | (defun footnote-add-footnote () |
| @@ -778,9 +755,10 @@ by using `footnote-back-to-message'." | |||
| 778 | (interactive "*") | 755 | (interactive "*") |
| 779 | (let ((num | 756 | (let ((num |
| 780 | (if footnote--markers-alist | 757 | (if footnote--markers-alist |
| 781 | (if (< (point) (cl-caddar (last footnote--markers-alist))) | 758 | (let ((last (car (last footnote--markers-alist)))) |
| 782 | (footnote--make-hole) | 759 | (if (< (point) (cl-caddr last)) |
| 783 | (1+ (caar (last footnote--markers-alist)))) | 760 | (footnote--make-hole) |
| 761 | (1+ (car last)))) | ||
| 784 | 1))) | 762 | 1))) |
| 785 | (message "Adding footnote %d" num) | 763 | (message "Adding footnote %d" num) |
| 786 | (footnote--insert-footnote num) | 764 | (footnote--insert-footnote num) |
| @@ -807,20 +785,17 @@ delete the footnote with that number." | |||
| 807 | (when (and arg | 785 | (when (and arg |
| 808 | (or (not footnote-prompt-before-deletion) | 786 | (or (not footnote-prompt-before-deletion) |
| 809 | (y-or-n-p (format "Really delete footnote %d?" arg)))) | 787 | (y-or-n-p (format "Really delete footnote %d?" arg)))) |
| 810 | (let (alist-elem locn) | 788 | (let ((alist-elem (or (assq arg footnote--markers-alist) |
| 811 | (setq alist-elem (assq arg footnote--markers-alist)) | 789 | (error "Can't delete footnote %d" arg))) |
| 812 | (unless alist-elem | 790 | (fn-regexp (concat (regexp-quote footnote-start-tag) |
| 813 | (error "Can't delete footnote %d" arg)) | 791 | (footnote--current-regexp) |
| 814 | (setq locn (cddr alist-elem)) | 792 | (regexp-quote footnote-end-tag)))) |
| 815 | (while (car locn) | 793 | (dolist (locn (cddr alist-elem)) |
| 816 | (save-excursion | 794 | (save-excursion |
| 817 | (goto-char (car locn)) | 795 | (goto-char locn) |
| 818 | (when (looking-back (concat (regexp-quote footnote-start-tag) | 796 | (when (looking-back fn-regexp |
| 819 | (footnote--current-regexp) | ||
| 820 | (regexp-quote footnote-end-tag)) | ||
| 821 | (line-beginning-position)) | 797 | (line-beginning-position)) |
| 822 | (delete-region (match-beginning 0) (match-end 0)))) | 798 | (delete-region (match-beginning 0) (match-end 0))))) |
| 823 | (setq locn (cdr locn))) | ||
| 824 | (save-excursion | 799 | (save-excursion |
| 825 | (goto-char (cadr alist-elem)) | 800 | (goto-char (cadr alist-elem)) |
| 826 | (delete-region | 801 | (delete-region |
| @@ -833,8 +808,8 @@ delete the footnote with that number." | |||
| 833 | (point) 'footnote-number nil (footnote--goto-char-point-max)))))) | 808 | (point) 'footnote-number nil (footnote--goto-char-point-max)))))) |
| 834 | (setq footnote--markers-alist | 809 | (setq footnote--markers-alist |
| 835 | (delq alist-elem footnote--markers-alist)) | 810 | (delq alist-elem footnote--markers-alist)) |
| 836 | (footnote-renumber-footnotes) | 811 | (if footnote--markers-alist |
| 837 | (when (null footnote--markers-alist) | 812 | (footnote-renumber-footnotes) |
| 838 | (save-excursion | 813 | (save-excursion |
| 839 | (if (not (string-equal footnote-section-tag "")) | 814 | (if (not (string-equal footnote-section-tag "")) |
| 840 | (let* ((end (footnote--goto-char-point-max)) | 815 | (let* ((end (footnote--goto-char-point-max)) |
| @@ -855,13 +830,9 @@ delete the footnote with that number." | |||
| 855 | "Renumber footnotes, starting from 1." | 830 | "Renumber footnotes, starting from 1." |
| 856 | (interactive "*") | 831 | (interactive "*") |
| 857 | (save-excursion | 832 | (save-excursion |
| 858 | (let ((i 0) | 833 | (let ((i 1)) |
| 859 | (notes (length footnote--markers-alist)) | 834 | (dolist (alist-elem footnote--markers-alist) |
| 860 | alist-elem) | 835 | (footnote--renumber i alist-elem) |
| 861 | (while (< i notes) | ||
| 862 | (setq alist-elem (nth i footnote--markers-alist)) | ||
| 863 | (unless (= (1+ i) (car alist-elem)) | ||
| 864 | (footnote--renumber (1+ i) alist-elem)) | ||
| 865 | (setq i (1+ i)))))) | 836 | (setq i (1+ i)))))) |
| 866 | 837 | ||
| 867 | (defun footnote-goto-footnote (&optional arg) | 838 | (defun footnote-goto-footnote (&optional arg) |
| @@ -900,13 +871,13 @@ being set it is automatically widened." | |||
| 900 | 871 | ||
| 901 | (defvar footnote-mode-map | 872 | (defvar footnote-mode-map |
| 902 | (let ((map (make-sparse-keymap))) | 873 | (let ((map (make-sparse-keymap))) |
| 903 | (define-key map "a" 'footnote-add-footnote) | 874 | (define-key map "a" #'footnote-add-footnote) |
| 904 | (define-key map "b" 'footnote-back-to-message) | 875 | (define-key map "b" #'footnote-back-to-message) |
| 905 | (define-key map "c" 'footnote-cycle-style) | 876 | (define-key map "c" #'footnote-cycle-style) |
| 906 | (define-key map "d" 'footnote-delete-footnote) | 877 | (define-key map "d" #'footnote-delete-footnote) |
| 907 | (define-key map "g" 'footnote-goto-footnote) | 878 | (define-key map "g" #'footnote-goto-footnote) |
| 908 | (define-key map "r" 'footnote-renumber-footnotes) | 879 | (define-key map "r" #'footnote-renumber-footnotes) |
| 909 | (define-key map "s" 'footnote-set-style) | 880 | (define-key map "s" #'footnote-set-style) |
| 910 | map)) | 881 | map)) |
| 911 | 882 | ||
| 912 | (defvar footnote-minor-mode-map | 883 | (defvar footnote-minor-mode-map |