diff options
| author | Vincent Belaïche | 2026-03-29 06:17:55 +0200 |
|---|---|---|
| committer | Vincent Belaïche | 2026-04-09 14:48:48 +0200 |
| commit | 92a2d9abbd3d7884b6c6f442d5e57ae9ae06f9bd (patch) | |
| tree | b5d24aee4ededca2f98c4eb81cd24bbf07db9d6c | |
| parent | 04dbd88c34341bc4fb1712f370eefd0d3387aa9d (diff) | |
| download | emacs-scratch/ert-play-keys-pre-master.tar.gz emacs-scratch/ert-play-keys-pre-master.zip | |
ert-play-keys functionscratch/ert-play-keys-pre-master
* lisp/emacs-lisp/ert-x.el (ert-play-keys): new defun.
* test/lisp/simple-tests.el (undo-test-kill-c-a-then-undo)
(undo-test-point-after-forward-kill): Use new function
`ert-play-keys' and `(ert-with-test-buffer (:selected t) ...)'
rather (with-temp-buffer (switch-to-buffer (current-buffer) ...)'.
* test/lisp/erc/erc-scenarios-spelling.el
(erc-scenarios-spelling--auto-correct): Use new function
`ert-play-keys' and `(ert-with-buffer-selected ...)' rather than
`execute-kbd-macro' and `(with-current-buffer
... (set-window-buffer nil (current-buffer) ...)'.
* doc/misc/ert.texi (Helper Functions): Document ert-play-keys,
and differences between ert-simulate-command, ert-simulate-keys
& ert-play-keys.
* test/lisp/emacs-lisp/ert-x-tests.el
(ert-x-tests-play-keys)
(ert-x-tests-simulate-command, ert-x-tests-simulate-keys): New
tests.
| -rw-r--r-- | doc/misc/ert.texi | 90 | ||||
| -rw-r--r-- | lisp/emacs-lisp/ert-x.el | 13 | ||||
| -rw-r--r-- | lisp/emacs-lisp/ert.el | 15 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/ert-x-tests.el | 71 | ||||
| -rw-r--r-- | test/lisp/erc/erc-scenarios-spelling.el | 7 | ||||
| -rw-r--r-- | test/lisp/simple-tests.el | 46 |
6 files changed, 205 insertions, 37 deletions
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi index f3bd60db8e4..8a2128fe851 100644 --- a/doc/misc/ert.texi +++ b/doc/misc/ert.texi | |||
| @@ -1132,6 +1132,12 @@ This has the same effect as combining @code{ert-with-test-buffer} with | |||
| 1132 | (ert-with-test-buffer (:name "global" :selected t) | 1132 | (ert-with-test-buffer (:name "global" :selected t) |
| 1133 | @dots{})) | 1133 | @dots{})) |
| 1134 | @end lisp | 1134 | @end lisp |
| 1135 | |||
| 1136 | @findex ert-play-keys | ||
| 1137 | The @var{select-form} shall be set non-nil when @var{body} contains some | ||
| 1138 | call to @code{ert-play-keys} to generate programmatically user input | ||
| 1139 | events inserting text into the test buffer, or starting commands acting | ||
| 1140 | on the test buffer. | ||
| 1135 | @end defmac | 1141 | @end defmac |
| 1136 | 1142 | ||
| 1137 | @defmac ert-with-buffer-selected (buffer &body body) | 1143 | @defmac ert-with-buffer-selected (buffer &body body) |
| @@ -1154,6 +1160,13 @@ value is the last form in @var{body}. Example: | |||
| 1154 | @end lisp | 1160 | @end lisp |
| 1155 | 1161 | ||
| 1156 | This displays a temporary buffer like @file{ *temp*-739785*}. | 1162 | This displays a temporary buffer like @file{ *temp*-739785*}. |
| 1163 | |||
| 1164 | @findex ert-play-keys | ||
| 1165 | One of the use of @code{ert-with-buffer-selected} is to set the buffer | ||
| 1166 | to which user input events generated programmatically by one or more | ||
| 1167 | calls to @code{ert-play-keys} are targetted, which is needed when those | ||
| 1168 | events are supposed to insert text into this buffer, or start commands | ||
| 1169 | acting on it. | ||
| 1157 | @end defmac | 1170 | @end defmac |
| 1158 | 1171 | ||
| 1159 | @subsection Protecting buffers | 1172 | @subsection Protecting buffers |
| @@ -1348,7 +1361,14 @@ symbol and the rest are arguments to the command. Example: | |||
| 1348 | 1361 | ||
| 1349 | @strong{Note}: Since the command is not called by | 1362 | @strong{Note}: Since the command is not called by |
| 1350 | @code{call-interactively}, a test for @code{(called-interactively-p | 1363 | @code{call-interactively}, a test for @code{(called-interactively-p |
| 1351 | 'interactive)} in the command will fail. | 1364 | @var{kind})} in the command will fail for whatever @var{kind}.@* |
| 1365 | Function @code{ert-play-keys} may be used instead to start a command if | ||
| 1366 | you need the predicate @code{(called-interactively-p @var{kind})} tested | ||
| 1367 | within the command body to return @code{t} for @var{kind} @code{any}, | ||
| 1368 | note however that it will still be @code{nil} too for @var{kind} | ||
| 1369 | @code{interactive} since @code{ert-play-keys} uses keyboard macros under | ||
| 1370 | the hood, and that @code{ert-play-keys} needs selecting the buffer of | ||
| 1371 | interest. | ||
| 1352 | @end defun | 1372 | @end defun |
| 1353 | 1373 | ||
| 1354 | @defmac ert-simulate-keys (keys &rest body) | 1374 | @defmac ert-simulate-keys (keys &rest body) |
| @@ -1362,8 +1382,76 @@ vector. Examples: | |||
| 1362 | (ert-simulate-keys (kbd "#fake C-m C-a C-k C-m") @dots{}) | 1382 | (ert-simulate-keys (kbd "#fake C-m C-a C-k C-m") @dots{}) |
| 1363 | (ert-simulate-keys [?b ?2 return] @dots{}) | 1383 | (ert-simulate-keys [?b ?2 return] @dots{}) |
| 1364 | @end lisp | 1384 | @end lisp |
| 1385 | |||
| 1386 | @c @findex ert-play-keys | ||
| 1387 | To generate input event for inserting some text into a buffer, or | ||
| 1388 | calling some interactive command, see rather function | ||
| 1389 | @code{ert-play-keys}. | ||
| 1365 | @end defmac | 1390 | @end defmac |
| 1366 | 1391 | ||
| 1392 | @defun ert-play-keys (keys) | ||
| 1393 | Generate programmatically user input events. | ||
| 1394 | |||
| 1395 | @c @findex ert-simulate-keys | ||
| 1396 | Contrary to @code{ert-simulate-keys}, these events are not intended to be | ||
| 1397 | consumed by functions reading input, like @code{read-from-minibuffer}, | ||
| 1398 | but are consumed by the command loop which typically will process them | ||
| 1399 | to start interactive commands or insert text into the selected buffer. | ||
| 1400 | |||
| 1401 | So, before calling @code{ert-play-keys} you generally need to select the | ||
| 1402 | buffer to which input events are intended to insert text or call a | ||
| 1403 | command. Do this by passing a non-nil @code{:selected} flag to | ||
| 1404 | @code{ert-with-test-buffer} if the buffer was created this way, or use | ||
| 1405 | the @code{ert-with-buffer-selected} macro. | ||
| 1406 | |||
| 1407 | @c @findex ert-simulate-command | ||
| 1408 | Contrary to @code{ert-simulate-command}, when @code{ert-play-keys} | ||
| 1409 | generates events starting a command you cannot get the command return | ||
| 1410 | value. On the other hand, @code{(called-interactively-p 'any)} tested in | ||
| 1411 | the command body will be @code{t}, but not @code{(called-interactively-p | ||
| 1412 | 'interactive)} as @code{ert-play-keys} does not a true interactive call, | ||
| 1413 | but uses a keyboard macro under the hood. Another difference is that, | ||
| 1414 | contrary to @code{ert-simulate-command}, @code{ert-play-keys} needs to | ||
| 1415 | select the buffer on which the command acts for the input events to | ||
| 1416 | reach it. | ||
| 1417 | |||
| 1418 | In this example a test buffer is created and selected, then | ||
| 1419 | @code{ert-play-keys} sets the mark, inserts text @samp{n'importe quoi} | ||
| 1420 | and kills it, then the test checks that the killed text is in the kill | ||
| 1421 | ring and the test buffer is empty, then a second @code{ert-play-keys} | ||
| 1422 | call yanks again the killed text, and finally the test checks the test | ||
| 1423 | buffer contains @samp{n'importe quoi}: | ||
| 1424 | |||
| 1425 | @lisp | ||
| 1426 | (ert-deftest ert-example-kill&yank () | ||
| 1427 | "Test kill and yank." | ||
| 1428 | (ert-with-test-buffer (:selected t) | ||
| 1429 | (ert-play-keys "C-SPC n'importe SPC quoi C-w") | ||
| 1430 | (should (string= "n'importe quoi" (car kill-ring))) | ||
| 1431 | (should (string= "" (buffer-substring (point-min) (point-max)))) | ||
| 1432 | (ert-play-keys "C-y") | ||
| 1433 | (should (string= "n'importe quoi" | ||
| 1434 | (buffer-substring (point-min) (point-max)))))) | ||
| 1435 | @end lisp | ||
| 1436 | |||
| 1437 | @noindent | ||
| 1438 | Write input events as above with a string in the input format used by | ||
| 1439 | @code{key-parse}, or directly in the internal Emacs representation like | ||
| 1440 | here which is otherwise the same test as above: | ||
| 1441 | |||
| 1442 | @lisp | ||
| 1443 | (ert-deftest ert-example-kill&yank () | ||
| 1444 | "Test kill and yank." | ||
| 1445 | (ert-with-test-buffer (:selected t) | ||
| 1446 | (ert-play-keys (vconcat [ ?\C- ] "n'importe quoi" [ ?\C-w])) | ||
| 1447 | (should (string= "n'importe quoi" (car kill-ring))) | ||
| 1448 | (should (string= "" (buffer-substring (point-min) (point-max)))) | ||
| 1449 | (ert-play-keys [ ?\C-y ]) | ||
| 1450 | (should (string= "n'importe quoi" | ||
| 1451 | (buffer-substring (point-min) (point-max)))))) | ||
| 1452 | @end lisp | ||
| 1453 | @end defun | ||
| 1454 | |||
| 1367 | @defun ert-filter-string (s &rest regexps) | 1455 | @defun ert-filter-string (s &rest regexps) |
| 1368 | This function returns a copy of string @var{s} with all matches of | 1456 | This function returns a copy of string @var{s} with all matches of |
| 1369 | @var{regexps} removed. Elements of @var{regexps} may also be | 1457 | @var{regexps} removed. Elements of @var{regexps} may also be |
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el index be4023c350a..0952033a6cc 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el | |||
| @@ -416,6 +416,19 @@ The same keyword arguments are supported as in | |||
| 416 | (format "/mock::%s" temporary-file-directory)))) | 416 | (format "/mock::%s" temporary-file-directory)))) |
| 417 | "Temporary directory for remote file tests.") | 417 | "Temporary directory for remote file tests.") |
| 418 | 418 | ||
| 419 | (defun ert-play-keys (keys) | ||
| 420 | "Play the key sequence KEYS as if it was user input. | ||
| 421 | |||
| 422 | KEYS shall have the same format as in a call to function `kmacro'. | ||
| 423 | |||
| 424 | This macro should be expanded within the body of | ||
| 425 | `ert-with-buffer-selected' to select a buffer when keys KEYS start | ||
| 426 | commands acting on this buffer, or within the body of | ||
| 427 | `ert-with-test-buffer' used with `:selected' flag set." | ||
| 428 | (funcall | ||
| 429 | (kmacro keys))) | ||
| 430 | |||
| 431 | |||
| 419 | 432 | ||
| 420 | ;;;; Obsolete | 433 | ;;;; Obsolete |
| 421 | 434 | ||
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 1c2df07f137..2f3f517701b 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el | |||
| @@ -3125,14 +3125,13 @@ The return value is the last form in BODY." | |||
| 3125 | 3125 | ||
| 3126 | If BUFFER-OR-NAME is nil, the current buffer is used. | 3126 | If BUFFER-OR-NAME is nil, the current buffer is used. |
| 3127 | 3127 | ||
| 3128 | The buffer is made the current buffer, and the temporary window | 3128 | The buffer is made the current buffer, and the temporary window becomes |
| 3129 | becomes the `selected-window', before BODY is evaluated. The | 3129 | the `selected-window', before BODY is evaluated. The modification hooks |
| 3130 | modification hooks `before-change-functions' and | 3130 | `before-change-functions' and `after-change-functions' are not inhibited |
| 3131 | `after-change-functions' are not inhibited during the evaluation | 3131 | during the evaluation of BODY, which makes it easier to use |
| 3132 | of BODY, which makes it easier to use `execute-kbd-macro' to | 3132 | `ert-play-keys' to simulate user sending input events. The window |
| 3133 | simulate user interaction. The window configuration is restored | 3133 | configuration is restored before returning, even if BODY exits |
| 3134 | before returning, even if BODY exits nonlocally. The return | 3134 | nonlocally. The return value is the last form in BODY." |
| 3135 | value is the last form in BODY." | ||
| 3136 | (declare (debug (form body)) (indent 1)) | 3135 | (declare (debug (form body)) (indent 1)) |
| 3137 | `(save-window-excursion | 3136 | `(save-window-excursion |
| 3138 | (with-current-buffer (or ,buffer-or-name (current-buffer)) | 3137 | (with-current-buffer (or ,buffer-or-name (current-buffer)) |
diff --git a/test/lisp/emacs-lisp/ert-x-tests.el b/test/lisp/emacs-lisp/ert-x-tests.el index c72ab97c557..2823fdba3d7 100644 --- a/test/lisp/emacs-lisp/ert-x-tests.el +++ b/test/lisp/emacs-lisp/ert-x-tests.el | |||
| @@ -293,6 +293,77 @@ desired effect." | |||
| 293 | (should-error | 293 | (should-error |
| 294 | (ert-with-temp-directory dir :text "foo" nil))) | 294 | (ert-with-temp-directory dir :text "foo" nil))) |
| 295 | 295 | ||
| 296 | (ert-deftest ert-x-tests-play-keys () | ||
| 297 | "Test `ert-play-keys'. | ||
| 298 | Send one symbolic event, some inserted text, and some key event to the | ||
| 299 | test buffer, and check all of them are processed." | ||
| 300 | (ert-with-test-buffer (:selected t) | ||
| 301 | (let (verdict-event verdict-key verdict-pre-command-hook verdict-post-command-hook) | ||
| 302 | (let ((pre-command-hook (lambda () (setq verdict-pre-command-hook t))) | ||
| 303 | (post-command-hook (lambda () (setq verdict-post-command-hook t))) | ||
| 304 | (map (let ((map (make-sparse-keymap))) | ||
| 305 | (define-key map [event] | ||
| 306 | (lambda () | ||
| 307 | (interactive) | ||
| 308 | (setq verdict-event | ||
| 309 | (list t | ||
| 310 | (called-interactively-p 'any) | ||
| 311 | (called-interactively-p 'interactive))))) | ||
| 312 | (define-key map [?$] | ||
| 313 | (lambda () | ||
| 314 | (interactive) | ||
| 315 | (setq verdict-key | ||
| 316 | (list t | ||
| 317 | (called-interactively-p 'any) | ||
| 318 | (called-interactively-p 'interactive))))) | ||
| 319 | map))) | ||
| 320 | (let ((minor-mode-map-alist (cons (cons t map) minor-mode-map-alist))) | ||
| 321 | (ert-play-keys (vconcat [event] "n'importe $quoi")))) | ||
| 322 | (should (equal verdict-event '(t t nil))) | ||
| 323 | (should (equal verdict-key '(t t nil))) | ||
| 324 | (should (eq verdict-pre-command-hook t)) | ||
| 325 | (should (eq verdict-post-command-hook t))) | ||
| 326 | (should (string= "n'importe quoi" | ||
| 327 | (buffer-substring (point-min) (point-max)))))) | ||
| 328 | |||
| 329 | (ert-deftest ert-x-tests-simulate-command () | ||
| 330 | "Test `ert-simulate-command'." | ||
| 331 | (ert-with-test-buffer () | ||
| 332 | (let (verdict-interactive verdict-pre-command-hook verdict-post-command-hook) | ||
| 333 | (let ((pre-command-hook (lambda () (setq verdict-pre-command-hook t))) | ||
| 334 | (post-command-hook (lambda () (setq verdict-post-command-hook t)))) | ||
| 335 | (should (eq (ert-simulate-command | ||
| 336 | (list | ||
| 337 | (lambda (x) | ||
| 338 | (interactive (list "un rien")) | ||
| 339 | (insert x) | ||
| 340 | (setq verdict-interactive (list t | ||
| 341 | (called-interactively-p 'any) | ||
| 342 | (called-interactively-p 'interactive))) | ||
| 343 | :ok) | ||
| 344 | "n'importe quoi")) | ||
| 345 | :ok))) | ||
| 346 | (should (equal verdict-interactive '(t nil nil))) | ||
| 347 | (should (eq verdict-pre-command-hook t)) | ||
| 348 | (should (eq verdict-post-command-hook t))) | ||
| 349 | (should (string= "n'importe quoi" | ||
| 350 | (buffer-substring (point-min) (point-max)))))) | ||
| 351 | |||
| 352 | (ert-deftest ert-x-tests-simulate-keys () | ||
| 353 | "Test `ert-simulate-keys'." | ||
| 354 | (ert-with-test-buffer () | ||
| 355 | (let* ((map (let ((map (make-sparse-keymap))) | ||
| 356 | (define-key map [?b] | ||
| 357 | (lambda () | ||
| 358 | (interactive) | ||
| 359 | (insert "r"))) map)) | ||
| 360 | (minor-mode-map-alist (cons (cons t map) minor-mode-map-alist))) | ||
| 361 | (ert-simulate-keys | ||
| 362 | (listify-key-sequence "un bien\nn'importe quoi") | ||
| 363 | (should (string= (read-from-minibuffer "Please enter something: ") "un rien"))) | ||
| 364 | (should (string= "" (buffer-substring (point-min) (point-max))))))) | ||
| 365 | |||
| 366 | |||
| 296 | (provide 'ert-x-tests) | 367 | (provide 'ert-x-tests) |
| 297 | 368 | ||
| 298 | ;;; ert-x-tests.el ends here | 369 | ;;; ert-x-tests.el ends here |
diff --git a/test/lisp/erc/erc-scenarios-spelling.el b/test/lisp/erc/erc-scenarios-spelling.el index 0495a2a1390..74e6dbb9715 100644 --- a/test/lisp/erc/erc-scenarios-spelling.el +++ b/test/lisp/erc/erc-scenarios-spelling.el | |||
| @@ -61,14 +61,13 @@ | |||
| 61 | (should erc-spelling-mode) | 61 | (should erc-spelling-mode) |
| 62 | (should flyspell-mode))) | 62 | (should flyspell-mode))) |
| 63 | 63 | ||
| 64 | (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan")) | 64 | (ert-with-buffer-selected (erc-d-t-wait-for 10 (get-buffer "#chan")) |
| 65 | (should erc-spelling-mode) | 65 | (should erc-spelling-mode) |
| 66 | (should flyspell-mode) | 66 | (should flyspell-mode) |
| 67 | (funcall expect 10 "<alice> tester, welcome!") | 67 | (funcall expect 10 "<alice> tester, welcome!") |
| 68 | 68 | ||
| 69 | ;; Insert a command with one misspelled word. | 69 | ;; Insert a command with one misspelled word. |
| 70 | (set-window-buffer nil (current-buffer)) | 70 | (ert-play-keys (vconcat [?\M->] "/AMSG an/dor /gmsg one fsbot two frob my shoe")) |
| 71 | (execute-kbd-macro "\M->/AMSG an/dor /gmsg one fsbot two frob my shoe") | ||
| 72 | (funcall expect 10 "shoe") | 71 | (funcall expect 10 "shoe") |
| 73 | 72 | ||
| 74 | (let* ((ovs (overlays-in erc-input-marker (point))) | 73 | (let* ((ovs (overlays-in erc-input-marker (point))) |
| @@ -90,7 +89,7 @@ | |||
| 90 | 89 | ||
| 91 | ;; Depending on the machine, this should become something | 90 | ;; Depending on the machine, this should become something |
| 92 | ;; like: "/AMSG an/dor /gmsg one fsbot two Rob my shoe". | 91 | ;; like: "/AMSG an/dor /gmsg one fsbot two Rob my shoe". |
| 93 | (execute-kbd-macro (key-parse "M-TAB")) | 92 | (ert-play-keys "M-TAB") |
| 94 | (should (equal (overlays-in erc-input-marker (point-max)) | 93 | (should (equal (overlays-in erc-input-marker (point-max)) |
| 95 | (list ov1))))) | 94 | (list ov1))))) |
| 96 | 95 | ||
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index 12697b2d68e..464cc51c152 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | ;;; Code: | 22 | ;;; Code: |
| 23 | 23 | ||
| 24 | (require 'ert) | 24 | (require 'ert-x) |
| 25 | (eval-when-compile (require 'cl-lib)) | 25 | (eval-when-compile (require 'cl-lib)) |
| 26 | 26 | ||
| 27 | (defun simple-test--buffer-substrings () | 27 | (defun simple-test--buffer-substrings () |
| @@ -730,36 +730,34 @@ See bug#35036." | |||
| 730 | ;; Test for a regression introduced by undo-auto--boundaries changes. | 730 | ;; Test for a regression introduced by undo-auto--boundaries changes. |
| 731 | ;; https://lists.gnu.org/r/emacs-devel/2015-11/msg01652.html | 731 | ;; https://lists.gnu.org/r/emacs-devel/2015-11/msg01652.html |
| 732 | (defun undo-test-kill-c-a-then-undo () | 732 | (defun undo-test-kill-c-a-then-undo () |
| 733 | (with-temp-buffer | 733 | (ert-with-test-buffer (:selected t) |
| 734 | (switch-to-buffer (current-buffer)) | 734 | (setq buffer-undo-list nil) |
| 735 | (setq buffer-undo-list nil) | 735 | (insert "a\nb\nc\n") |
| 736 | (insert "a\nb\nc\n") | 736 | (goto-char (point-max)) |
| 737 | (goto-char (point-max)) | 737 | ;; We use a keyboard macro because it adds undo events in the same |
| 738 | ;; We use a keyboard macro because it adds undo events in the same | 738 | ;; way as if a user were involved. |
| 739 | ;; way as if a user were involved. | 739 | (ert-play-keys [left |
| 740 | (funcall (kmacro [left | 740 | ;; Delete "c" |
| 741 | ;; Delete "c" | 741 | backspace |
| 742 | backspace | 742 | left left left |
| 743 | left left left | 743 | ;; Delete "a" |
| 744 | ;; Delete "a" | 744 | backspace |
| 745 | backspace | 745 | ;; C-/ or undo |
| 746 | ;; C-/ or undo | 746 | ?\C-/ |
| 747 | ?\C-/ | 747 | ]) |
| 748 | ])) | ||
| 749 | (point))) | 748 | (point))) |
| 750 | 749 | ||
| 751 | (defun undo-test-point-after-forward-kill () | 750 | (defun undo-test-point-after-forward-kill () |
| 752 | (with-temp-buffer | 751 | (ert-with-test-buffer (:selected t) |
| 753 | (switch-to-buffer (current-buffer)) | ||
| 754 | (setq buffer-undo-list nil) | 752 | (setq buffer-undo-list nil) |
| 755 | (insert "kill word forward") | 753 | (insert "kill word forward") |
| 756 | ;; Move to word "word". | 754 | ;; Move to word "word". |
| 757 | (goto-char 6) | 755 | (goto-char 6) |
| 758 | (funcall (kmacro [;; kill-word | 756 | (ert-play-keys [;; kill-word |
| 759 | C-delete | 757 | C-delete |
| 760 | ;; undo | 758 | ;; undo |
| 761 | ?\C-/ | 759 | ?\C-/ |
| 762 | ])) | 760 | ]) |
| 763 | (point))) | 761 | (point))) |
| 764 | 762 | ||
| 765 | (ert-deftest undo-point-in-wrong-place () | 763 | (ert-deftest undo-point-in-wrong-place () |