From 1d07a6d7e34677be1653b1d4d464ff00cabfa102 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 28 Mar 2025 01:01:17 -0400 Subject: [PATCH] Use `replace-region-contents` to replace insert+delete * lisp/minibuffer.el (completion--replace): * lisp/emacs-lisp/cl-lib.el (cl--set-buffer-substring): * lisp/subr.el (replace-string-in-region): Use `replace-region-contents` instead of insert+delete. * lisp/help-fns.el (help-fns--signature): Use `replace-region-contents` instead of `cl--set-buffer-substring`. * lisp/language/japan-util.el (japanese-replace-region): Rewrite using `replace-region-contents` and mark obsolete. (japanese-katakana-region, japanese-hankaku-region): Use `replace-region-contents` instead. * lisp/progmodes/flymake-proc.el (flymake-proc--replace-region): Rewrite using `replace-region-contents` and mark obsolete. (flymake-proc--check-patch-master-file-buffer): Use `replace-region-contents` instead. --- lisp/emacs-lisp/cl-lib.el | 8 +++---- lisp/emacs-lisp/gv.el | 2 ++ lisp/help-fns.el | 2 +- lisp/language/japan-util.el | 43 ++++++++++++++++++++-------------- lisp/minibuffer.el | 33 +++----------------------- lisp/progmodes/flymake-proc.el | 14 +++++------ lisp/subr.el | 4 ++-- 7 files changed, 42 insertions(+), 64 deletions(-) diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 4208160bd12..4645b4dffb1 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -154,12 +154,10 @@ to an element already in the list stored in PLACE. `(setq ,place (cl-adjoin ,x ,place ,@keys))) `(cl-callf2 cl-adjoin ,x ,place ,@keys))) -(defun cl--set-buffer-substring (start end val) +(defun cl--set-buffer-substring (start end val &optional inherit) "Delete region from START to END and insert VAL." - (save-excursion (delete-region start end) - (goto-char start) - (insert val) - val)) + (replace-region-contents start end val 0 nil inherit) + val) (defun cl--set-substring (str start end val) (if end (if (< end 0) (incf end (length str))) diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index b44f7dc87f3..6c949f1016b 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -684,6 +684,8 @@ REF must have been previously obtained with `gv-ref'." `(insert (prog1 ,store (erase-buffer)))) (make-obsolete-generalized-variable 'buffer-string nil "29.1") +;; FIXME: Can't use `replace-region-contents' because it's not +;; expected to be costly, so we need to pass MAX-SECS==0. (gv-define-simple-setter buffer-substring cl--set-buffer-substring) (make-obsolete-generalized-variable 'buffer-substring nil "29.1") diff --git a/lisp/help-fns.el b/lisp/help-fns.el index cd5a0a6883f..dacf1ecbbd4 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -777,7 +777,7 @@ the C sources, too." (save-excursion (forward-char -1) (<= (current-column) (- fill-column 12))) - (cl--set-buffer-substring (- beg 3) beg " "))))) + (replace-region-contents (- beg 3) beg " " 0))))) high-doc))))) (defun help-fns--parent-mode (function) diff --git a/lisp/language/japan-util.el b/lisp/language/japan-util.el index 718c469d562..6fbb52b627e 100644 --- a/lisp/language/japan-util.el +++ b/lisp/language/japan-util.el @@ -217,9 +217,9 @@ The argument object is not altered--the value is a copy." (defun japanese-replace-region (from to string) "Replace the region specified by FROM and TO to STRING." - (goto-char from) - (insert string) - (delete-char (- to from))) + (declare (obsolete replace-region-contents "31.1")) + (goto-char to) + (replace-region-contents from to string 0)) ;;;###autoload (defun japanese-katakana-region (from to &optional hankaku) @@ -238,13 +238,15 @@ of which charset is `japanese-jisx0201-kana'." (get-char-code-property kana 'kana-composition))) slot) ;; next (if (and composition (setq slot (assq (following-char) composition))) - (japanese-replace-region (match-beginning 0) (1+ (point)) - (cdr slot)) + (progn + (goto-char (1+ (point))) + (replace-region-contents (match-beginning 0) (point) + (cdr slot) 0)) (let ((kata (get-char-code-property kana (if hankaku 'jisx0201 'katakana)))) (if kata - (japanese-replace-region (match-beginning 0) (point) - kata))))))))) + (replace-region-contents (match-beginning 0) (point) + kata 0))))))))) ;;;###autoload @@ -260,13 +262,16 @@ of which charset is `japanese-jisx0201-kana'." (composition (get-char-code-property kata 'kana-composition)) slot) ;; next (if (and composition (setq slot (assq (following-char) composition))) - (japanese-replace-region (match-beginning 0) (1+ (point)) - (get-char-code-property - (cdr slot) 'hiragana)) + (progn + (goto-char (1+ (point))) + (replace-region-contents (match-beginning 0) (point) + (get-char-code-property + (cdr slot) 'hiragana) + 0)) (let ((hira (get-char-code-property kata 'hiragana))) (if hira - (japanese-replace-region (match-beginning 0) (point) - hira))))))))) + (replace-region-contents (match-beginning 0) (point) + hira 0))))))))) ;;;###autoload (defun japanese-hankaku-region (from to &optional ascii-only) @@ -285,8 +290,8 @@ Optional argument ASCII-ONLY non-nil means to convert only to ASCII char." (get-char-code-property zenkaku 'jisx0201)) (get-char-code-property zenkaku 'ascii)))) (if hankaku - (japanese-replace-region (match-beginning 0) (match-end 0) - hankaku))))))) + (replace-region-contents (match-beginning 0) (match-end 0) + hankaku 0))))))) ;;;###autoload (defun japanese-zenkaku-region (from to &optional katakana-only) @@ -307,12 +312,14 @@ Optional argument KATAKANA-ONLY non-nil means to convert only KATAKANA char." (composition (get-char-code-property hankaku 'kana-composition)) slot) ;; next (if (and composition (setq slot (assq (following-char) composition))) - (japanese-replace-region (match-beginning 0) (1+ (point)) - (cdr slot)) + (progn + (goto-char (1+ (point))) + (replace-region-contents (match-beginning 0) (point) + (cdr slot) 0)) (let ((zenkaku (japanese-zenkaku hankaku))) (if zenkaku - (japanese-replace-region (match-beginning 0) (match-end 0) - zenkaku))))))))) + (replace-region-contents (match-beginning 0) (match-end 0) + zenkaku 0))))))))) ;;;###autoload (defun read-hiragana-string (prompt &optional initial-input) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index becb2a7faba..e9c064b89e8 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1398,35 +1398,8 @@ Moves point to the end of the new text." newtext) ;; Remove all text properties. (set-text-properties 0 (length newtext) nil newtext)) - ;; Maybe this should be in subr.el. - ;; You'd think this is trivial to do, but details matter if you want - ;; to keep markers "at the right place" and be robust in the face of - ;; after-change-functions that may themselves modify the buffer. - (let ((prefix-len 0)) - ;; Don't touch markers in the shared prefix (if any). - (while (and (< prefix-len (length newtext)) - (< (+ beg prefix-len) end) - (eq (char-after (+ beg prefix-len)) - (aref newtext prefix-len))) - (setq prefix-len (1+ prefix-len))) - (unless (zerop prefix-len) - (setq beg (+ beg prefix-len)) - (setq newtext (substring newtext prefix-len)))) - (let ((suffix-len 0)) - ;; Don't touch markers in the shared suffix (if any). - (while (and (< suffix-len (length newtext)) - (< beg (- end suffix-len)) - (eq (char-before (- end suffix-len)) - (aref newtext (- (length newtext) suffix-len 1)))) - (setq suffix-len (1+ suffix-len))) - (unless (zerop suffix-len) - (setq end (- end suffix-len)) - (setq newtext (substring newtext 0 (- suffix-len)))) - (goto-char beg) - (let ((length (- end beg))) ;Read `end' before we insert the text. - (insert-and-inherit newtext) - (delete-region (point) (+ (point) length))) - (forward-char suffix-len))) + (replace-region-contents beg end newtext 0.1 nil 'inherit) + (goto-char (+ beg (length newtext)))) (defcustom completion-cycle-threshold nil "Number of completion candidates below which cycling is used. @@ -2951,7 +2924,7 @@ This calls the function that `completion-in-region-function' specifies \(passing the same four arguments that it received) to do the work, and returns whatever it does. The return value should be nil if there was no valid completion, else t." - (cl-assert (<= start (point)) (<= (point) end)) + (cl-assert (<= start (point) end) t) (funcall completion-in-region-function start end collection predicate)) (defcustom read-file-name-completion-ignore-case diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el index df6571311e4..0418d9fd07c 100644 --- a/lisp/progmodes/flymake-proc.el +++ b/lisp/progmodes/flymake-proc.el @@ -331,7 +331,7 @@ max-level parent dirs. File contents are not checked." (setq dirs (cdr dirs))) (when files (let ((flymake-proc--included-file-name (file-name-nondirectory file-name))) - (setq files (sort files 'flymake-proc--master-file-compare)))) + (setq files (sort files #'flymake-proc--master-file-compare)))) (flymake-log 3 "found %d possible master file(s)" (length files)) files)) @@ -407,9 +407,10 @@ instead of reading master file from disk." ;; replace-match is not used here as it fails in ;; XEmacs with 'last match not a buffer' error as ;; check-includes calls replace-in-string - (flymake-proc--replace-region + (replace-region-contents match-beg match-end - (file-name-nondirectory patched-source-file-name)))) + (file-name-nondirectory patched-source-file-name) + 0))) (forward-line 1))) (when found (flymake-proc--save-buffer-in-file patched-master-file-name))) @@ -424,11 +425,8 @@ instead of reading master file from disk." ;;; XXX: remove (defun flymake-proc--replace-region (beg end rep) "Replace text in BUFFER in region (BEG END) with REP." - (save-excursion - (goto-char end) - ;; Insert before deleting, so as to better preserve markers's positions. - (insert rep) - (delete-region beg end))) + (declare (obsolete replace-region-contents "31")) + (replace-region-contents beg end rep 0)) (defun flymake-proc--read-file-to-temp-buffer (file-name) "Insert contents of FILE-NAME into newly created temp buffer." diff --git a/lisp/subr.el b/lisp/subr.el index 66b73cbf6cc..017ab3e16bb 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4798,8 +4798,8 @@ Comparisons and replacements are done with fixed case." (let ((matches 0) (case-fold-search nil)) (while (search-forward string nil t) - (delete-region (match-beginning 0) (match-end 0)) - (insert replacement) + (replace-region-contents (match-beginning 0) (match-end 0) + replacement 0) (setq matches (1+ matches))) (and (not (zerop matches)) matches)))))