diff options
| author | Tino Calancha | 2018-06-03 23:28:30 +0900 |
|---|---|---|
| committer | Tino Calancha | 2018-06-03 23:28:30 +0900 |
| commit | 5fa73a7d98040f749f4cd45cfa40cf3c1c8cc2e3 (patch) | |
| tree | 01511805dc80acff47aba83bb967b81daa229f6a /test/lisp/replace-tests.el | |
| parent | 031004e81b1507c4594ae253faaafcda31f253c8 (diff) | |
| download | emacs-5fa73a7d98040f749f4cd45cfa40cf3c1c8cc2e3.tar.gz emacs-5fa73a7d98040f749f4cd45cfa40cf3c1c8cc2e3.zip | |
query-replace undo: Handle when user edits the replacement string
* lisp/replace.el (perform-replace): Update the replacement string
after the user edit it (Fix Bug#31538).
* test/lisp/replace-tests.el (query-replace-undo-bug31538): New test.
Backport: (cherry picked from commits
ea133e04f49afa7928e49a3ac4a85b47f6f13f01
and
7dcfdf5b14325ae7996f272f14c72810d7c84944)
Diffstat (limited to 'test/lisp/replace-tests.el')
| -rw-r--r-- | test/lisp/replace-tests.el | 133 |
1 files changed, 84 insertions, 49 deletions
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el index 40ee838e679..3fcdce6704f 100644 --- a/test/lisp/replace-tests.el +++ b/test/lisp/replace-tests.el | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | ;;; Code: | 23 | ;;; Code: |
| 24 | 24 | ||
| 25 | (require 'ert) | 25 | (require 'ert) |
| 26 | (eval-when-compile (require 'subr-x)) | ||
| 26 | 27 | ||
| 27 | (ert-deftest query-replace--split-string-tests () | 28 | (ert-deftest query-replace--split-string-tests () |
| 28 | (let ((sep (propertize "\0" 'separator t))) | 29 | (let ((sep (propertize "\0" 'separator t))) |
| @@ -358,23 +359,71 @@ Each element has the format: | |||
| 358 | (dotimes (i (length replace-occur-tests)) | 359 | (dotimes (i (length replace-occur-tests)) |
| 359 | (replace-occur-test-create i)) | 360 | (replace-occur-test-create i)) |
| 360 | 361 | ||
| 362 | |||
| 363 | ;;; Tests for `query-replace' undo feature. | ||
| 364 | |||
| 365 | (defvar replace-tests-bind-read-string nil | ||
| 366 | "A string to bind `read-string' and avoid the prompt.") | ||
| 367 | |||
| 368 | (defmacro replace-tests-with-undo (input from to char-nums def-chr &rest body) | ||
| 369 | "Helper to test `query-replace' undo feature. | ||
| 370 | INPUT is a string to insert in a temporary buffer. | ||
| 371 | FROM is the string to match and replace. | ||
| 372 | TO is the replacement string. | ||
| 373 | CHAR-NUMS is a list of elements (CHAR . NUMS), where CHAR is | ||
| 374 | one of the characters `,', `?\\s', `u', `U', `E' or `q' | ||
| 375 | and NUMS a list of integers. | ||
| 376 | DEF-CHAR is the character `?\\s' or `q'. | ||
| 377 | BODY is a list of forms to evaluate. | ||
| 378 | |||
| 379 | Use CHAR-NUMS and DEF-CHAR to temporary bind the function value of | ||
| 380 | `read-event', thus avoiding the prompt. | ||
| 381 | For instance, if CHAR-NUMS is the lists ((?\\s . (1 2 3)) (?u . (4))), | ||
| 382 | then replace 3 matches of FROM with TO, and undo the last replacement. | ||
| 383 | |||
| 384 | Return the last evalled form in BODY." | ||
| 385 | (declare (indent 5) (debug (stringp stringp stringp form characterp body))) | ||
| 386 | (let ((text (gensym "text")) | ||
| 387 | (count (gensym "count"))) | ||
| 388 | `(let* ((,text ,input) | ||
| 389 | (,count 0) | ||
| 390 | (inhibit-message t)) | ||
| 391 | (with-temp-buffer | ||
| 392 | (insert ,text) | ||
| 393 | (goto-char 1) | ||
| 394 | ;; Bind `read-event' to simulate user input. | ||
| 395 | ;; If `replace-tests-bind-read-string' is non-nil, then | ||
| 396 | ;; bind `read-string' as well. | ||
| 397 | (cl-letf (((symbol-function 'read-event) | ||
| 398 | (lambda (&rest args) | ||
| 399 | (cl-incf ,count) | ||
| 400 | (pcase ,count ; Build the clauses from CHAR-NUMS | ||
| 401 | ,@(append | ||
| 402 | (delq nil | ||
| 403 | (mapcar | ||
| 404 | (lambda (chr) | ||
| 405 | (when-let (it (alist-get chr char-nums)) | ||
| 406 | (if (cdr it) | ||
| 407 | `(,(cons 'or it) ,chr) | ||
| 408 | `(,(car it) ,chr)))) | ||
| 409 | '(?, ?\s ?u ?U ?E ?q))) | ||
| 410 | `((_ ,def-chr)))))) | ||
| 411 | ((symbol-function 'read-string) | ||
| 412 | (if replace-tests-bind-read-string | ||
| 413 | (lambda (&rest args) replace-tests-bind-read-string) | ||
| 414 | (symbol-function 'read-string)))) | ||
| 415 | (perform-replace ,from ,to t t nil)) | ||
| 416 | ,@body)))) | ||
| 417 | |||
| 361 | (defun replace-tests--query-replace-undo (&optional comma) | 418 | (defun replace-tests--query-replace-undo (&optional comma) |
| 362 | (with-temp-buffer | 419 | (let ((input "111")) |
| 363 | (insert "111") | 420 | (if comma |
| 364 | (goto-char 1) | 421 | (should |
| 365 | (let ((count 0)) | 422 | (replace-tests-with-undo |
| 366 | ;; Don't wait for user input. | 423 | input "1" "2" ((?, . (2)) (?u . (3)) (?q . (4))) ?\s (buffer-string))) |
| 367 | (cl-letf (((symbol-function 'read-event) | 424 | (should |
| 368 | (lambda (&rest args) | 425 | (replace-tests-with-undo |
| 369 | (cl-incf count) | 426 | input "1" "2" ((?\s . (2)) (?u . (3)) (?q . (4))) ?\s (buffer-string)))))) |
| 370 | (let ((val (pcase count | ||
| 371 | ('2 (if comma ?, ?\s)) ; replace and: ',' no move; '\s' go next | ||
| 372 | ('3 ?u) ; undo | ||
| 373 | ('4 ?q) ; exit | ||
| 374 | (_ ?\s)))) ; replace current and go next | ||
| 375 | val)))) | ||
| 376 | (perform-replace "1" "2" t nil nil))) | ||
| 377 | (buffer-string))) | ||
| 378 | 427 | ||
| 379 | (ert-deftest query-replace--undo () | 428 | (ert-deftest query-replace--undo () |
| 380 | (should (string= "211" (replace-tests--query-replace-undo))) | 429 | (should (string= "211" (replace-tests--query-replace-undo))) |
| @@ -382,42 +431,28 @@ Each element has the format: | |||
| 382 | 431 | ||
| 383 | (ert-deftest query-replace-undo-bug31073 () | 432 | (ert-deftest query-replace-undo-bug31073 () |
| 384 | "Test for https://debbugs.gnu.org/31073 ." | 433 | "Test for https://debbugs.gnu.org/31073 ." |
| 385 | (let ((text "aaa aaa") | 434 | (let ((input "aaa aaa")) |
| 386 | (count 0)) | 435 | (should |
| 387 | (with-temp-buffer | 436 | (replace-tests-with-undo |
| 388 | (insert text) | 437 | input "a" "B" ((?\s . (1 2 3)) (?U . (4))) ?q |
| 389 | (goto-char 1) | 438 | (string= input (buffer-string)))))) |
| 390 | (cl-letf (((symbol-function 'read-event) | ||
| 391 | (lambda (&rest args) | ||
| 392 | (cl-incf count) | ||
| 393 | (let ((val (pcase count | ||
| 394 | ((or 1 2 3) ?\s) ; replace current and go next | ||
| 395 | (4 ?U) ; undo-all | ||
| 396 | (_ ?q)))) ; exit | ||
| 397 | val)))) | ||
| 398 | (perform-replace "a" "B" t nil nil)) | ||
| 399 | ;; After undo text must be the same. | ||
| 400 | (should (string= text (buffer-string)))))) | ||
| 401 | 439 | ||
| 402 | (ert-deftest query-replace-undo-bug31492 () | 440 | (ert-deftest query-replace-undo-bug31492 () |
| 403 | "Test for https://debbugs.gnu.org/31492 ." | 441 | "Test for https://debbugs.gnu.org/31492 ." |
| 404 | (let ((text "a\nb\nc\n") | 442 | (let ((input "a\nb\nc\n")) |
| 405 | (count 0) | 443 | (should |
| 406 | (inhibit-message t)) | 444 | (replace-tests-with-undo |
| 407 | (with-temp-buffer | 445 | input "^\\|\b\\|$" "foo" ((?\s . (1 2)) (?U . (3))) ?q |
| 408 | (insert text) | 446 | (string= input (buffer-string)))))) |
| 409 | (goto-char 1) | 447 | |
| 410 | (cl-letf (((symbol-function 'read-event) | 448 | (ert-deftest query-replace-undo-bug31538 () |
| 411 | (lambda (&rest args) | 449 | "Test for https://debbugs.gnu.org/31538 ." |
| 412 | (cl-incf count) | 450 | (let ((input "aaa aaa") |
| 413 | (let ((val (pcase count | 451 | (replace-tests-bind-read-string "Bfoo")) |
| 414 | ((or 1 2) ?\s) ; replace current and go next | 452 | (should |
| 415 | (3 ?U) ; undo-all | 453 | (replace-tests-with-undo |
| 416 | (_ ?q)))) ; exit | 454 | input "a" "B" ((?\s . (1 2 3)) (?E . (4)) (?U . (5))) ?q |
| 417 | val)))) | 455 | (string= input (buffer-string)))))) |
| 418 | (perform-replace "^\\|\b\\|$" "foo" t t nil)) | ||
| 419 | ;; After undo text must be the same. | ||
| 420 | (should (string= text (buffer-string)))))) | ||
| 421 | 456 | ||
| 422 | 457 | ||
| 423 | ;;; replace-tests.el ends here | 458 | ;;; replace-tests.el ends here |