From: Stefan Monnier Date: Sun, 6 Jul 2025 23:15:51 +0000 (-0400) Subject: (Ftranspose_regions): Fix bug#76124 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=f766b8377487558499841f694684482b8694b490;p=emacs.git (Ftranspose_regions): Fix bug#76124 * src/editfns.c (Ftranspose_regions): Be careful that ELisp code could move the gap from under our feet. * test/src/editfns-tests.el (editfns-tests--bug76124): New test. (cherry picked from commit b93d49a3787085407a9dd57d678d0fc552878fcc) --- diff --git a/src/editfns.c b/src/editfns.c index 714ed422b38..af53923f92c 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -4588,6 +4588,9 @@ ring. */) BUF_TS_LINECOL_POINT (current_buffer)); #endif + /* Run the before-change-functions *before* we move the gap. */ + modify_text (start1, end2); + /* Make sure the gap won't interfere, by moving it out of the text we will operate on. */ if (start1 < gap && gap < end2) @@ -4632,7 +4635,6 @@ ring. */) enough to use as the temporary storage? That would avoid an allocation... interesting. Later, don't fool with it now. */ - modify_text (start1, end2); tmp_interval1 = copy_intervals (cur_intv, start1, len1); tmp_interval2 = copy_intervals (cur_intv, start2, len2); USE_SAFE_ALLOCA; diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 9a27c420f1e..2fce2315edb 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -630,4 +630,29 @@ (should (string= (format "%S" (format "%S %S" [1] (symbol-function '+))) str)))) +(ert-deftest editfns-tests--bug76124 () + (with-temp-buffer + (insert "Emacs forever!foo\n") + (insert "toto\n") + (goto-char (point-min)) + ;; Remove the trailing "foo", so as to move the gap between the + ;; two lines. + (delete-region (- (pos-eol) 3) (pos-eol)) + (add-hook 'before-change-functions + (lambda (beg end) + ;; Eglot uses `encode-coding-region' which can also move + ;; the gap, but let's do it more forcefully here. + (save-excursion + (goto-char beg) + (end-of-line) + (unless (> (point) end) + (with-silent-modifications + (insert "foo") + (delete-char -3))))) + nil t) + (goto-char (point-min)) + (transpose-regions (pos-bol) (pos-eol) + (pos-bol 2) (pos-eol 2)) + (should (equal (buffer-string) "toto\nEmacs forever!\n")))) + ;;; editfns-tests.el ends here