diff options
| author | Mauro Aranda | 2025-02-06 08:01:08 -0300 |
|---|---|---|
| committer | Eli Zaretskii | 2025-02-22 11:19:17 +0200 |
| commit | 3e269371507ea4cd7e933e39320d258a3b98de44 (patch) | |
| tree | 57fcaa623db864e159bfc75587093dd08b4e0912 | |
| parent | 79ab873b9b679ec0aedb03ce246035d8e5d4b09c (diff) | |
| download | emacs-3e269371507ea4cd7e933e39320d258a3b98de44.tar.gz emacs-3e269371507ea4cd7e933e39320d258a3b98de44.zip | |
Speed up widget creation (Bug#53606)
* lisp/wid-edit.el (widget-default-create, widget-checklist-add-item)
(widget-radio-add-item, widget-editable-list-entry-create): Don't
insert format escapes into the buffer, only to delete them after.
This avoids calls to delete-char and makes widget creation about 3
times faster.
| -rw-r--r-- | lisp/wid-edit.el | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index a1d4c4850ae..2d6075c10a8 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el | |||
| @@ -1776,18 +1776,20 @@ to a given widget." | |||
| 1776 | (defun widget-default-create (widget) | 1776 | (defun widget-default-create (widget) |
| 1777 | "Create WIDGET at point in the current buffer." | 1777 | "Create WIDGET at point in the current buffer." |
| 1778 | (widget-specify-insert | 1778 | (widget-specify-insert |
| 1779 | (let ((from (point)) | 1779 | (let ((str (widget-get widget :format)) |
| 1780 | (onext 0) (next 0) | ||
| 1780 | button-begin button-end | 1781 | button-begin button-end |
| 1781 | sample-begin sample-end | 1782 | sample-begin sample-end |
| 1782 | doc-begin doc-end | 1783 | doc-begin doc-end |
| 1783 | value-pos | 1784 | value-pos |
| 1784 | (markers (widget--prepare-markers-for-inside-insertion widget))) | 1785 | (markers (widget--prepare-markers-for-inside-insertion widget))) |
| 1785 | (insert (widget-get widget :format)) | ||
| 1786 | (goto-char from) | ||
| 1787 | ;; Parse escapes in format. | 1786 | ;; Parse escapes in format. |
| 1788 | (while (re-search-forward "%\\(.\\)" nil t) | 1787 | (while (string-match "%\\(.\\)" str next) |
| 1789 | (let ((escape (char-after (match-beginning 1)))) | 1788 | (setq next (match-end 1)) |
| 1790 | (delete-char -2) | 1789 | ;; If we skipped some literal text, insert it. |
| 1790 | (when (/= (- next onext) 2) | ||
| 1791 | (insert (substring str onext (- next 2)))) | ||
| 1792 | (let ((escape (string-to-char (match-string 1 str)))) | ||
| 1791 | (cond ((eq escape ?%) | 1793 | (cond ((eq escape ?%) |
| 1792 | (insert ?%)) | 1794 | (insert ?%)) |
| 1793 | ((eq escape ?\[) | 1795 | ((eq escape ?\[) |
| @@ -1831,7 +1833,11 @@ to a given widget." | |||
| 1831 | (widget-apply widget :value-create) | 1833 | (widget-apply widget :value-create) |
| 1832 | (setq value-pos (point)))) | 1834 | (setq value-pos (point)))) |
| 1833 | (t | 1835 | (t |
| 1834 | (widget-apply widget :format-handler escape))))) | 1836 | (widget-apply widget :format-handler escape)))) |
| 1837 | (setq onext next)) | ||
| 1838 | ;; Insert remaining literal text, if any. | ||
| 1839 | (when (> (length str) next) | ||
| 1840 | (insert (substring str next))) | ||
| 1835 | ;; Specify button, sample, and doc, and insert value. | 1841 | ;; Specify button, sample, and doc, and insert value. |
| 1836 | (and button-begin button-end | 1842 | (and button-begin button-end |
| 1837 | (widget-specify-button widget button-begin button-end)) | 1843 | (widget-specify-button widget button-begin button-end)) |
| @@ -2578,14 +2584,15 @@ If the item is checked, CHOSEN is a cons whose cdr is the value." | |||
| 2578 | (buttons (widget-get widget :buttons)) | 2584 | (buttons (widget-get widget :buttons)) |
| 2579 | (button-args (or (widget-get type :sibling-args) | 2585 | (button-args (or (widget-get type :sibling-args) |
| 2580 | (widget-get widget :button-args))) | 2586 | (widget-get widget :button-args))) |
| 2581 | (from (point)) | 2587 | (str (widget-get widget :entry-format)) |
| 2588 | (onext 0) (next 0) | ||
| 2582 | child button) | 2589 | child button) |
| 2583 | (insert (widget-get widget :entry-format)) | ||
| 2584 | (goto-char from) | ||
| 2585 | ;; Parse % escapes in format. | 2590 | ;; Parse % escapes in format. |
| 2586 | (while (re-search-forward "%\\([bv%]\\)" nil t) | 2591 | (while (string-match "%\\([bv%]\\)" str next) |
| 2587 | (let ((escape (char-after (match-beginning 1)))) | 2592 | (setq next (match-end 1)) |
| 2588 | (delete-char -2) | 2593 | (when (/= (- next onext) 2) |
| 2594 | (insert (substring str onext (- next 2)))) | ||
| 2595 | (let ((escape (string-to-char (match-string 1 str)))) | ||
| 2589 | (cond ((eq escape ?%) | 2596 | (cond ((eq escape ?%) |
| 2590 | (insert ?%)) | 2597 | (insert ?%)) |
| 2591 | ((eq escape ?b) | 2598 | ((eq escape ?b) |
| @@ -2609,7 +2616,10 @@ If the item is checked, CHOSEN is a cons whose cdr is the value." | |||
| 2609 | (widget-create-child-value | 2616 | (widget-create-child-value |
| 2610 | widget type (car (cdr chosen))))))) | 2617 | widget type (car (cdr chosen))))))) |
| 2611 | (t | 2618 | (t |
| 2612 | (error "Unknown escape `%c'" escape))))) | 2619 | (error "Unknown escape `%c'" escape)))) |
| 2620 | (setq onext next)) | ||
| 2621 | (when (> (length str) next) | ||
| 2622 | (insert (substring str next))) | ||
| 2613 | ;; Update properties. | 2623 | ;; Update properties. |
| 2614 | (and button child (widget-put child :button button)) | 2624 | (and button child (widget-put child :button button)) |
| 2615 | (and button (widget-put widget :buttons (cons button buttons))) | 2625 | (and button (widget-put widget :buttons (cons button buttons))) |
| @@ -2756,16 +2766,17 @@ Return an alist of (TYPE MATCH)." | |||
| 2756 | (buttons (widget-get widget :buttons)) | 2766 | (buttons (widget-get widget :buttons)) |
| 2757 | (button-args (or (widget-get type :sibling-args) | 2767 | (button-args (or (widget-get type :sibling-args) |
| 2758 | (widget-get widget :button-args))) | 2768 | (widget-get widget :button-args))) |
| 2759 | (from (point)) | 2769 | (str (widget-get widget :entry-format)) |
| 2770 | (onext 0) (next 0) | ||
| 2760 | (chosen (and (null (widget-get widget :choice)) | 2771 | (chosen (and (null (widget-get widget :choice)) |
| 2761 | (widget-apply type :match value))) | 2772 | (widget-apply type :match value))) |
| 2762 | child button) | 2773 | child button) |
| 2763 | (insert (widget-get widget :entry-format)) | ||
| 2764 | (goto-char from) | ||
| 2765 | ;; Parse % escapes in format. | 2774 | ;; Parse % escapes in format. |
| 2766 | (while (re-search-forward "%\\([bv%]\\)" nil t) | 2775 | (while (string-match "%\\([bv%]\\)" str next) |
| 2767 | (let ((escape (char-after (match-beginning 1)))) | 2776 | (setq next (match-end 1)) |
| 2768 | (delete-char -2) | 2777 | (when (/= (- next onext) 2) |
| 2778 | (insert (substring str onext (- next 2)))) | ||
| 2779 | (let ((escape (string-to-char (match-string 1 str)))) | ||
| 2769 | (cond ((eq escape ?%) | 2780 | (cond ((eq escape ?%) |
| 2770 | (insert ?%)) | 2781 | (insert ?%)) |
| 2771 | ((eq escape ?b) | 2782 | ((eq escape ?b) |
| @@ -2784,7 +2795,10 @@ Return an alist of (TYPE MATCH)." | |||
| 2784 | (to (widget-get child :to))) | 2795 | (to (widget-get child :to))) |
| 2785 | (widget-specify-unselected child from to)))) | 2796 | (widget-specify-unselected child from to)))) |
| 2786 | (t | 2797 | (t |
| 2787 | (error "Unknown escape `%c'" escape))))) | 2798 | (error "Unknown escape `%c'" escape)))) |
| 2799 | (setq onext next)) | ||
| 2800 | (when (> (length str) next) | ||
| 2801 | (insert (substring str next))) | ||
| 2788 | ;; Update properties. | 2802 | ;; Update properties. |
| 2789 | (when chosen | 2803 | (when chosen |
| 2790 | (widget-put widget :choice type)) | 2804 | (widget-put widget :choice type)) |
| @@ -3053,17 +3067,20 @@ Save CHILD into the :last-deleted list, so it can be inserted later." | |||
| 3053 | ;; Create a new entry to the list. | 3067 | ;; Create a new entry to the list. |
| 3054 | (let ((type (nth 0 (widget-get widget :args))) | 3068 | (let ((type (nth 0 (widget-get widget :args))) |
| 3055 | ;; (widget-push-button-gui widget-editable-list-gui) | 3069 | ;; (widget-push-button-gui widget-editable-list-gui) |
| 3070 | (str (widget-get widget :entry-format)) | ||
| 3071 | (onext 0) (next 0) | ||
| 3056 | child delete insert) | 3072 | child delete insert) |
| 3057 | (widget-specify-insert | 3073 | (widget-specify-insert |
| 3058 | (save-excursion | 3074 | (save-excursion |
| 3059 | (and (widget--should-indent-p) | 3075 | (and (widget--should-indent-p) |
| 3060 | (widget-get widget :indent) | 3076 | (widget-get widget :indent) |
| 3061 | (insert-char ?\s (widget-get widget :indent))) | 3077 | (insert-char ?\s (widget-get widget :indent)))) |
| 3062 | (insert (widget-get widget :entry-format))) | ||
| 3063 | ;; Parse % escapes in format. | 3078 | ;; Parse % escapes in format. |
| 3064 | (while (re-search-forward "%\\(.\\)" nil t) | 3079 | (while (string-match "%\\(.\\)" str next) |
| 3065 | (let ((escape (char-after (match-beginning 1)))) | 3080 | (setq next (match-end 1)) |
| 3066 | (delete-char -2) | 3081 | (when (/= (- next onext) 2) |
| 3082 | (insert (substring str onext (- next 2)))) | ||
| 3083 | (let ((escape (string-to-char (match-string 1 str)))) | ||
| 3067 | (cond ((eq escape ?%) | 3084 | (cond ((eq escape ?%) |
| 3068 | (insert ?%)) | 3085 | (insert ?%)) |
| 3069 | ((eq escape ?i) | 3086 | ((eq escape ?i) |
| @@ -3079,7 +3096,10 @@ Save CHILD into the :last-deleted list, so it can be inserted later." | |||
| 3079 | widget type | 3096 | widget type |
| 3080 | (if conv value (widget-default-get type))))) | 3097 | (if conv value (widget-default-get type))))) |
| 3081 | (t | 3098 | (t |
| 3082 | (error "Unknown escape `%c'" escape))))) | 3099 | (error "Unknown escape `%c'" escape)))) |
| 3100 | (setq onext next)) | ||
| 3101 | (when (> (length str) next) | ||
| 3102 | (insert (substring str next))) | ||
| 3083 | (let ((buttons (widget-get widget :buttons))) | 3103 | (let ((buttons (widget-get widget :buttons))) |
| 3084 | (if insert (push insert buttons)) | 3104 | (if insert (push insert buttons)) |
| 3085 | (if delete (push delete buttons)) | 3105 | (if delete (push delete buttons)) |