diff options
| author | Stephen Berman | 2024-10-31 10:46:27 +0100 |
|---|---|---|
| committer | Stephen Berman | 2024-10-31 12:12:25 +0100 |
| commit | 8113b5c562b88d4981231b0e332ced9fc20dc0b9 (patch) | |
| tree | 0ddd8d410f09818d52c5dd9830d3f1a6db75f51d | |
| parent | 3101c5031e6eae31ac64392f312091ffa9bbd777 (diff) | |
| download | emacs-8113b5c562b88d4981231b0e332ced9fc20dc0b9.tar.gz emacs-8113b5c562b88d4981231b0e332ced9fc20dc0b9.zip | |
Fix bugs in dabbrev-expand (bug#74090)
* lisp/dabbrev.el (dabbrev-expand): Use the buffer where the
expansion was found when setting the internal variables used to
determine the next expansion or a replacement expansion.
* test/lisp/dabbrev-tests.el (ert-x): Require for
'ert-with-temp-directory', 'ert-resource-directory' and
'ert-resource-file'.
(with-dabbrev-test): New macro.
(dabbrev-expand-test-same-buffer-{1,2,3,4})
(dabbrev-expand-test-other-buffer-{1,2,3,4})
(dabbrev-expand-test-minibuffer-{1,2,3,4}): New tests.
* test/lisp/dabbrev-resources/dabbrev-expand.el:
* test/lisp/dabbrev-resources/INSTALL_BEGIN: New test resources.
(cherry picked from commit f6c359cb66a0e9b851e3467b1ba9cab7efa8f744)
| -rw-r--r-- | lisp/dabbrev.el | 65 | ||||
| -rw-r--r-- | test/lisp/dabbrev-resources/INSTALL_BEGIN | 153 | ||||
| -rw-r--r-- | test/lisp/dabbrev-resources/dabbrev-expand.el | 132 | ||||
| -rw-r--r-- | test/lisp/dabbrev-tests.el | 207 |
4 files changed, 542 insertions, 15 deletions
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 7b6cbb78cef..bbe6a64b626 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el | |||
| @@ -464,8 +464,21 @@ direction of search to backward if set non-nil. | |||
| 464 | 464 | ||
| 465 | See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." | 465 | See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." |
| 466 | (interactive "*P") | 466 | (interactive "*P") |
| 467 | (let (abbrev record-case-pattern | 467 | ;; There are three possible sources of the expansion, which we need to |
| 468 | expansion old direction (orig-point (point))) | 468 | ;; check in a specific order: |
| 469 | (let ((buf (cond ((window-minibuffer-p) | ||
| 470 | ;; If we invoked dabbrev-expand in the minibuffer, | ||
| 471 | ;; this is the buffer from which we entered the | ||
| 472 | ;; minibuffer. | ||
| 473 | (window-buffer (get-mru-window))) | ||
| 474 | ;; Otherwise, if we found the expansion in another | ||
| 475 | ;; buffer, use that buffer for further expansions. | ||
| 476 | (dabbrev--last-buffer-found dabbrev--last-buffer-found) | ||
| 477 | ;; Otherwise, use the buffer where we invoked | ||
| 478 | ;; dabbrev-expand. | ||
| 479 | (t (current-buffer)))) | ||
| 480 | abbrev record-case-pattern expansion old direction | ||
| 481 | (orig-point (point))) | ||
| 469 | ;; abbrev -- the abbrev to expand | 482 | ;; abbrev -- the abbrev to expand |
| 470 | ;; expansion -- the expansion found (eventually) or nil until then | 483 | ;; expansion -- the expansion found (eventually) or nil until then |
| 471 | ;; old -- the text currently in the buffer | 484 | ;; old -- the text currently in the buffer |
| @@ -480,6 +493,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." | |||
| 480 | (point))))) | 493 | (point))))) |
| 481 | ;; Find a different expansion for the same abbrev as last time. | 494 | ;; Find a different expansion for the same abbrev as last time. |
| 482 | (progn | 495 | (progn |
| 496 | (setq dabbrev--last-buffer-found nil) | ||
| 483 | (setq abbrev dabbrev--last-abbreviation) | 497 | (setq abbrev dabbrev--last-abbreviation) |
| 484 | (setq old dabbrev--last-expansion) | 498 | (setq old dabbrev--last-expansion) |
| 485 | (setq direction dabbrev--last-direction)) | 499 | (setq direction dabbrev--last-direction)) |
| @@ -488,7 +502,14 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." | |||
| 488 | (if (and (eq (preceding-char) ?\s) | 502 | (if (and (eq (preceding-char) ?\s) |
| 489 | (markerp dabbrev--last-abbrev-location) | 503 | (markerp dabbrev--last-abbrev-location) |
| 490 | (marker-position dabbrev--last-abbrev-location) | 504 | (marker-position dabbrev--last-abbrev-location) |
| 491 | (= (point) (1+ dabbrev--last-abbrev-location))) | 505 | ;; Comparing with point only makes sense in the buffer |
| 506 | ;; where we called dabbrev-expand, but if that differs | ||
| 507 | ;; from the buffer containing the expansion, we want to | ||
| 508 | ;; get the next word in the latter buffer, so we skip | ||
| 509 | ;; the comparison. | ||
| 510 | (if (eq buf (current-buffer)) | ||
| 511 | (= (point) (1+ dabbrev--last-abbrev-location)) | ||
| 512 | t)) | ||
| 492 | (progn | 513 | (progn |
| 493 | ;; The "abbrev" to expand is just the space. | 514 | ;; The "abbrev" to expand is just the space. |
| 494 | (setq abbrev " ") | 515 | (setq abbrev " ") |
| @@ -549,29 +570,43 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." | |||
| 549 | (if old " further" "") abbrev)) | 570 | (if old " further" "") abbrev)) |
| 550 | (t | 571 | (t |
| 551 | (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found) | 572 | (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found) |
| 552 | (minibuffer-window-active-p (selected-window)))) | 573 | ;; If we are in the minibuffer and an expansion has |
| 574 | ;; been found but dabbrev--last-buffer-found is not | ||
| 575 | ;; yet set, we need to set it now. | ||
| 576 | (and dabbrev--last-buffer-found | ||
| 577 | (minibuffer-window-active-p (selected-window))))) | ||
| 553 | (progn | 578 | (progn |
| 554 | (when (buffer-name dabbrev--last-buffer) | 579 | (when (buffer-name dabbrev--last-buffer) |
| 555 | (message "Expansion found in `%s'" | 580 | (message "Expansion found in `%s'" |
| 556 | (buffer-name dabbrev--last-buffer))) | 581 | (buffer-name dabbrev--last-buffer))) |
| 557 | (setq dabbrev--last-buffer-found dabbrev--last-buffer)) | 582 | (setq dabbrev--last-buffer-found dabbrev--last-buffer)) |
| 558 | (message nil)) | 583 | (message nil)) |
| 559 | (if (and (or (eq (current-buffer) dabbrev--last-buffer) | 584 | ;; To get correct further expansions we have to be sure to use the |
| 560 | (null dabbrev--last-buffer) | 585 | ;; buffer containing the already found expansions. |
| 561 | (buffer-live-p dabbrev--last-buffer)) | 586 | (when dabbrev--last-buffer-found |
| 562 | (numberp dabbrev--last-expansion-location) | 587 | (setq buf dabbrev--last-buffer-found)) |
| 563 | (and (> dabbrev--last-expansion-location (point)))) | 588 | ;; If the buffer where we called dabbrev-expand differs from the |
| 564 | (setq dabbrev--last-expansion-location | 589 | ;; buffer containing the expansion, make sure copy-marker is |
| 565 | (copy-marker dabbrev--last-expansion-location))) | 590 | ;; called in the latter buffer. |
| 591 | (with-current-buffer buf | ||
| 592 | (if (and (or (eq (current-buffer) dabbrev--last-buffer) | ||
| 593 | (null dabbrev--last-buffer) | ||
| 594 | (buffer-live-p dabbrev--last-buffer)) | ||
| 595 | (numberp dabbrev--last-expansion-location) | ||
| 596 | (and (> dabbrev--last-expansion-location (point)))) | ||
| 597 | (setq dabbrev--last-expansion-location | ||
| 598 | (copy-marker dabbrev--last-expansion-location)))) | ||
| 566 | ;; Success: stick it in and return. | 599 | ;; Success: stick it in and return. |
| 567 | (setq buffer-undo-list (cons orig-point buffer-undo-list)) | 600 | (setq buffer-undo-list (cons orig-point buffer-undo-list)) |
| 568 | (setq expansion (dabbrev--substitute-expansion old abbrev expansion | 601 | (setq expansion (dabbrev--substitute-expansion old abbrev expansion |
| 569 | record-case-pattern)) | 602 | record-case-pattern)) |
| 570 | 603 | ||
| 571 | ;; Save state for re-expand. | 604 | ;; Save state for re-expand (making sure it's the state of the |
| 572 | (setq dabbrev--last-expansion expansion) | 605 | ;; buffer containing the already found expansions). |
| 573 | (setq dabbrev--last-abbreviation abbrev) | 606 | (with-current-buffer buf |
| 574 | (setq dabbrev--last-abbrev-location (point-marker)))))) | 607 | (setq dabbrev--last-expansion expansion) |
| 608 | (setq dabbrev--last-abbreviation abbrev) | ||
| 609 | (setq dabbrev--last-abbrev-location (point-marker))))))) | ||
| 575 | 610 | ||
| 576 | ;;---------------------------------------------------------------- | 611 | ;;---------------------------------------------------------------- |
| 577 | ;; Local functions | 612 | ;; Local functions |
diff --git a/test/lisp/dabbrev-resources/INSTALL_BEGIN b/test/lisp/dabbrev-resources/INSTALL_BEGIN new file mode 100644 index 00000000000..6309419dccf --- /dev/null +++ b/test/lisp/dabbrev-resources/INSTALL_BEGIN | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | GNU Emacs Installation Guide | ||
| 2 | Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation, | ||
| 3 | Inc. | ||
| 4 | See the end of the file for license conditions. | ||
| 5 | |||
| 6 | |||
| 7 | This file contains general information on building GNU Emacs. If you | ||
| 8 | are building an Emacs release tarball on a Unix or a GNU system, the | ||
| 9 | instructions in this file should be sufficient. For other | ||
| 10 | configurations, we have additional specialized files: | ||
| 11 | |||
| 12 | . INSTALL.REPO if you build from a Git checkout | ||
| 13 | . nt/INSTALL if you build for MS-Windows | ||
| 14 | . nextstep/INSTALL if you build for GNUstep/macOS | ||
| 15 | . java/INSTALL if you build for Android | ||
| 16 | . msdos/INSTALL if you build for MS-DOS | ||
| 17 | |||
| 18 | |||
| 19 | BASIC INSTALLATION | ||
| 20 | |||
| 21 | On most Unix systems, you build Emacs by first running the 'configure' | ||
| 22 | shell script. This attempts to deduce the correct values for | ||
| 23 | various system-dependent variables and features, and find the | ||
| 24 | directories where certain system headers and libraries are kept. | ||
| 25 | In a few cases, you may need to explicitly tell configure where to | ||
| 26 | find some things, or what options to use. | ||
| 27 | |||
| 28 | 'configure' creates a 'Makefile' in several subdirectories, and a | ||
| 29 | 'src/config.h' file containing system-dependent definitions. | ||
| 30 | Running the 'make' utility then builds the package for your system. | ||
| 31 | |||
| 32 | Building Emacs requires GNU make, <https://www.gnu.org/software/make/>. | ||
| 33 | On most systems that Emacs supports, this is the default 'make' program. | ||
| 34 | |||
| 35 | Here's the procedure to build Emacs using 'configure' on systems which | ||
| 36 | are supported by it. In some cases, if the simplified procedure fails, | ||
| 37 | you might need to use various non-default options, and maybe perform | ||
| 38 | some of the steps manually. The more detailed description in the other | ||
| 39 | sections of this guide will help you do that, so please refer to those | ||
| 40 | sections if you need to. | ||
| 41 | |||
| 42 | 1. Obtain and unpack the Emacs release, with commands like this: | ||
| 43 | |||
| 44 | wget https://ftp.gnu.org/gnu/emacs/emacs-VERSION.tar.xz | ||
| 45 | tar -xf emacs-VERSION.tar.xz | ||
| 46 | |||
| 47 | where VERSION is the Emacs version number. | ||
| 48 | |||
| 49 | 2a. 'cd' to the directory where you unpacked Emacs and invoke the | ||
| 50 | 'configure' script: | ||
| 51 | |||
| 52 | ./configure | ||
| 53 | |||
| 54 | 2b. Alternatively, create a separate directory, outside the source | ||
| 55 | directory, where you want to build Emacs, and invoke 'configure' | ||
| 56 | from there: | ||
| 57 | |||
| 58 | SOURCE-DIR/configure | ||
| 59 | |||
| 60 | where SOURCE-DIR is the top-level Emacs source directory. | ||
| 61 | |||
| 62 | 2c. If you don't have write access to the default directory where | ||
| 63 | Emacs and its data files will be installed, specify an alternative | ||
| 64 | installation directory: | ||
| 65 | |||
| 66 | ./configure --prefix=/SOME/OTHER/DIRECTORY | ||
| 67 | |||
| 68 | where /SOME/OTHER/DIRECTORY is a directory writable by your user, | ||
| 69 | for example, a subdirectory of your home directory. | ||
| 70 | |||
| 71 | 3. When 'configure' finishes, it prints several lines of details | ||
| 72 | about the system configuration. Read those details carefully | ||
| 73 | looking for anything suspicious, such as wrong CPU and operating | ||
| 74 | system names, wrong places for headers or libraries, missing | ||
| 75 | libraries that you know are installed on your system, etc. | ||
| 76 | |||
| 77 | If you find anything wrong, you may have to pass to 'configure' | ||
| 78 | one or more options specifying the explicit machine configuration | ||
| 79 | name, where to find various headers and libraries, etc. | ||
| 80 | Refer to the section DETAILED BUILDING AND INSTALLATION below. | ||
| 81 | |||
| 82 | If 'configure' didn't find some image support libraries, such as | ||
| 83 | Xpm and jpeg, refer to "Image support libraries" below. | ||
| 84 | |||
| 85 | If the details printed by 'configure' don't make any sense to | ||
| 86 | you, but there are no obvious errors, assume that 'configure' did | ||
| 87 | its job and proceed. | ||
| 88 | |||
| 89 | 4. Invoke the 'make' program: | ||
| 90 | |||
| 91 | make | ||
| 92 | |||
| 93 | 5. If 'make' succeeds, it will build an executable program 'emacs' | ||
| 94 | in the 'src' directory. You can try this program, to make sure | ||
| 95 | it works: | ||
| 96 | |||
| 97 | src/emacs -Q | ||
| 98 | |||
| 99 | To test Emacs further (intended mostly to help developers): | ||
| 100 | |||
| 101 | make check | ||
| 102 | |||
| 103 | 6. Assuming that the program 'src/emacs' starts and displays its | ||
| 104 | opening screen, you can install the program and its auxiliary | ||
| 105 | files into their installation directories: | ||
| 106 | |||
| 107 | make install | ||
| 108 | |||
| 109 | You are now ready to use Emacs. If you wish to conserve space, | ||
| 110 | you may remove the program binaries and object files from the | ||
| 111 | directory where you built Emacs: | ||
| 112 | |||
| 113 | make clean | ||
| 114 | |||
| 115 | You can delete the entire build directory if you do not plan to | ||
| 116 | build Emacs again, but it can be useful to keep for debugging. | ||
| 117 | If you want to build Emacs again with different configure options, | ||
| 118 | first clean the source directories: | ||
| 119 | |||
| 120 | make distclean | ||
| 121 | |||
| 122 | Note that the install automatically saves space by compressing | ||
| 123 | (provided you have the 'gzip' program) those installed Lisp source (.el) | ||
| 124 | files that have corresponding .elc versions, as well as the Info files. | ||
| 125 | |||
| 126 | You can read a brief summary about common make targets: | ||
| 127 | |||
| 128 | make help | ||
| 129 | |||
| 130 | |||
| 131 | ADDITIONAL DISTRIBUTION FILES | ||
| 132 | |||
| 133 | * Complex Text Layout support libraries | ||
| 134 | |||
| 135 | On GNU and Unix systems, Emacs needs optional libraries to correctly | ||
| 136 | display such complex scripts as Indic and Khmer, and also for scripts | ||
| 137 | that require Arabic shaping support (Arabic and Farsi). If the | ||
| 138 | HarfBuzz library is installed, Emacs will build with it and use it for | ||
| 139 | this purpose. HarfBuzz is the preferred shaping engine, both on Posix | ||
| 140 | hosts and on MS-Windows, so we recommend installing it before building | ||
| 141 | Emacs. The alternative for GNU/Linux and Posix systems is to use the | ||
| 142 | "m17n-db", "libm17n-flt", and "libotf" libraries. (On some systems, | ||
| 143 | particularly GNU/Linux, these libraries may be already present or | ||
| 144 | available as additional packages.) Note that if there is a separate | ||
| 145 | 'dev' or 'devel' package, for use at compilation time rather than run | ||
| 146 | time, you will need that as well as the corresponding run time | ||
| 147 | package; typically the dev package will contain header files and a | ||
| 148 | library archive. On MS-Windows, if HarfBuzz is not available, Emacs | ||
| 149 | will use the Uniscribe shaping engine that is part of the OS. | ||
| 150 | |||
| 151 | Note that Emacs cannot support complex scripts on a TTY, unless the | ||
| 152 | terminal includes such a support. However, most modern terminal | ||
| 153 | emulators, such as xterm, do support such scripts. | ||
diff --git a/test/lisp/dabbrev-resources/dabbrev-expand.el b/test/lisp/dabbrev-resources/dabbrev-expand.el new file mode 100644 index 00000000000..c986b0ed633 --- /dev/null +++ b/test/lisp/dabbrev-resources/dabbrev-expand.el | |||
| @@ -0,0 +1,132 @@ | |||
| 1 | (defun dabbrev-expand (arg) | ||
| 2 | "Expand previous word \"dynamically\". | ||
| 3 | |||
| 4 | Expands to the most recent, preceding word for which this is a prefix. | ||
| 5 | If no suitable preceding word is found, words following point are | ||
| 6 | considered. If still no suitable word is found, then look in the | ||
| 7 | buffers accepted by the function pointed out by variable | ||
| 8 | `dabbrev-friend-buffer-function', if `dabbrev-check-other-buffers' | ||
| 9 | says so. Then, if `dabbrev-check-all-buffers' is non-nil, look in | ||
| 10 | all the other buffers, subject to constraints specified | ||
| 11 | by `dabbrev-ignored-buffer-names' and `dabbrev-ignored-buffer-regexps'. | ||
| 12 | |||
| 13 | A positive prefix argument, N, says to take the Nth backward *distinct* | ||
| 14 | possibility. A negative argument says search forward. | ||
| 15 | |||
| 16 | If the cursor has not moved from the end of the previous expansion and | ||
| 17 | no argument is given, replace the previously-made expansion | ||
| 18 | with the next possible expansion not yet tried. | ||
| 19 | |||
| 20 | The variable `dabbrev-backward-only' may be used to limit the | ||
| 21 | direction of search to backward if set non-nil. | ||
| 22 | |||
| 23 | See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." | ||
| 24 | (interactive "*P") | ||
| 25 | (let (abbrev record-case-pattern | ||
| 26 | expansion old direction (orig-point (point))) | ||
| 27 | ;; abbrev -- the abbrev to expand | ||
| 28 | ;; expansion -- the expansion found (eventually) or nil until then | ||
| 29 | ;; old -- the text currently in the buffer | ||
| 30 | ;; (the abbrev, or the previously-made expansion) | ||
| 31 | (save-excursion | ||
| 32 | (if (and (null arg) | ||
| 33 | (markerp dabbrev--last-abbrev-location) | ||
| 34 | (marker-position dabbrev--last-abbrev-location) | ||
| 35 | (or (eq last-command this-command) | ||
| 36 | (and (window-minibuffer-p) | ||
| 37 | (= dabbrev--last-abbrev-location | ||
| 38 | (point))))) | ||
| 39 | ;; Find a different expansion for the same abbrev as last time. | ||
| 40 | (progn | ||
| 41 | (setq abbrev dabbrev--last-abbreviation) | ||
| 42 | (setq old dabbrev--last-expansion) | ||
| 43 | (setq direction dabbrev--last-direction)) | ||
| 44 | ;; If the user inserts a space after expanding | ||
| 45 | ;; and then asks to expand again, always fetch the next word. | ||
| 46 | (if (and (eq (preceding-char) ?\s) | ||
| 47 | (markerp dabbrev--last-abbrev-location) | ||
| 48 | (marker-position dabbrev--last-abbrev-location) | ||
| 49 | (= (point) (1+ dabbrev--last-abbrev-location))) | ||
| 50 | (progn | ||
| 51 | ;; The "abbrev" to expand is just the space. | ||
| 52 | (setq abbrev " ") | ||
| 53 | (save-excursion | ||
| 54 | (save-restriction | ||
| 55 | (widen) | ||
| 56 | (if (buffer-live-p dabbrev--last-buffer) | ||
| 57 | (set-buffer dabbrev--last-buffer)) | ||
| 58 | ;; Find the end of the last "expansion" word. | ||
| 59 | (if (or (eq dabbrev--last-direction 1) | ||
| 60 | (and (eq dabbrev--last-direction 0) | ||
| 61 | (< dabbrev--last-expansion-location (point)))) | ||
| 62 | (setq dabbrev--last-expansion-location | ||
| 63 | (+ dabbrev--last-expansion-location | ||
| 64 | (length dabbrev--last-expansion)))) | ||
| 65 | (goto-char dabbrev--last-expansion-location) | ||
| 66 | ;; Take the following word, with intermediate separators, | ||
| 67 | ;; as our expansion this time. | ||
| 68 | (re-search-forward | ||
| 69 | (concat "\\(?:" dabbrev--abbrev-char-regexp "\\)+")) | ||
| 70 | (setq expansion (buffer-substring-no-properties | ||
| 71 | dabbrev--last-expansion-location (point))) | ||
| 72 | |||
| 73 | ;; Record the end of this expansion, in case we repeat this. | ||
| 74 | (setq dabbrev--last-expansion-location (point)))) | ||
| 75 | ;; Indicate that dabbrev--last-expansion-location is | ||
| 76 | ;; at the end of the expansion. | ||
| 77 | (setq dabbrev--last-direction -1)) | ||
| 78 | |||
| 79 | ;; We have a different abbrev to expand. | ||
| 80 | (dabbrev--reset-global-variables) | ||
| 81 | (setq direction (if (null arg) | ||
| 82 | (if dabbrev-backward-only 1 0) | ||
| 83 | (prefix-numeric-value arg))) | ||
| 84 | (setq abbrev (dabbrev--abbrev-at-point)) | ||
| 85 | (setq record-case-pattern t) | ||
| 86 | (setq old nil))) | ||
| 87 | |||
| 88 | ;;-------------------------------- | ||
| 89 | ;; Find the expansion | ||
| 90 | ;;-------------------------------- | ||
| 91 | (or expansion | ||
| 92 | (setq expansion | ||
| 93 | (dabbrev--find-expansion | ||
| 94 | abbrev direction | ||
| 95 | (dabbrev--ignore-case-p abbrev))))) | ||
| 96 | (cond | ||
| 97 | ((not expansion) | ||
| 98 | (dabbrev--reset-global-variables) | ||
| 99 | (if old | ||
| 100 | (save-excursion | ||
| 101 | (setq buffer-undo-list (cons orig-point buffer-undo-list)) | ||
| 102 | ;; Put back the original abbrev with its original case pattern. | ||
| 103 | (search-backward old) | ||
| 104 | (insert abbrev) | ||
| 105 | (delete-region (point) (+ (point) (length old))))) | ||
| 106 | (user-error "No%s dynamic expansion for `%s' found" | ||
| 107 | (if old " further" "") abbrev)) | ||
| 108 | (t | ||
| 109 | (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found) | ||
| 110 | (minibuffer-window-active-p (selected-window)))) | ||
| 111 | (progn | ||
| 112 | (when (buffer-name dabbrev--last-buffer) | ||
| 113 | (message "Expansion found in `%s'" | ||
| 114 | (buffer-name dabbrev--last-buffer))) | ||
| 115 | (setq dabbrev--last-buffer-found dabbrev--last-buffer)) | ||
| 116 | (message nil)) | ||
| 117 | (if (and (or (eq (current-buffer) dabbrev--last-buffer) | ||
| 118 | (null dabbrev--last-buffer) | ||
| 119 | (buffer-live-p dabbrev--last-buffer)) | ||
| 120 | (numberp dabbrev--last-expansion-location) | ||
| 121 | (and (> dabbrev--last-expansion-location (point)))) | ||
| 122 | (setq dabbrev--last-expansion-location | ||
| 123 | (copy-marker dabbrev--last-expansion-location))) | ||
| 124 | ;; Success: stick it in and return. | ||
| 125 | (setq buffer-undo-list (cons orig-point buffer-undo-list)) | ||
| 126 | (setq expansion (dabbrev--substitute-expansion old abbrev expansion | ||
| 127 | record-case-pattern)) | ||
| 128 | |||
| 129 | ;; Save state for re-expand. | ||
| 130 | (setq dabbrev--last-expansion expansion) | ||
| 131 | (setq dabbrev--last-abbreviation abbrev) | ||
| 132 | (setq dabbrev--last-abbrev-location (point-marker)))))) | ||
diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el index c7574403949..987106aa5af 100644 --- a/test/lisp/dabbrev-tests.el +++ b/test/lisp/dabbrev-tests.el | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | ;;; Code: | 25 | ;;; Code: |
| 26 | 26 | ||
| 27 | (require 'ert) | 27 | (require 'ert) |
| 28 | (require 'ert-x) | ||
| 28 | (require 'dabbrev) | 29 | (require 'dabbrev) |
| 29 | 30 | ||
| 30 | (ert-deftest dabbrev-expand-test () | 31 | (ert-deftest dabbrev-expand-test () |
| @@ -68,4 +69,210 @@ multiple expansions." | |||
| 68 | (execute-kbd-macro (kbd "C-u C-u C-M-/"))) | 69 | (execute-kbd-macro (kbd "C-u C-u C-M-/"))) |
| 69 | (should (string= (buffer-string) "abc\na"))))) | 70 | (should (string= (buffer-string) "abc\na"))))) |
| 70 | 71 | ||
| 72 | (defmacro with-dabbrev-test (&rest body) | ||
| 73 | "Set up an isolated `dabbrev' test environment." | ||
| 74 | (declare (debug (body))) | ||
| 75 | `(ert-with-temp-directory dabbrev-test-home | ||
| 76 | (let* (;; Since we change HOME, clear this to avoid a conflict | ||
| 77 | ;; e.g. if Emacs runs within the user's home directory. | ||
| 78 | (abbreviated-home-dir nil) | ||
| 79 | (process-environment (cons (format "HOME=%s" dabbrev-test-home) | ||
| 80 | process-environment)) | ||
| 81 | (dabbrev-directory (ert-resource-directory))) | ||
| 82 | (unwind-protect | ||
| 83 | (progn ,@body) | ||
| 84 | ;; Restore pre-test-run state of test files. | ||
| 85 | (dolist (f (directory-files dabbrev-directory)) | ||
| 86 | (let ((buf (get-file-buffer f))) | ||
| 87 | (when buf | ||
| 88 | (with-current-buffer buf | ||
| 89 | (restore-buffer-modified-p nil) | ||
| 90 | (kill-buffer))))) | ||
| 91 | (dabbrev--reset-global-variables))))) | ||
| 92 | |||
| 93 | (ert-deftest dabbrev-expand-test-same-buffer-1 () | ||
| 94 | "Test expanding a string twice within a single buffer. | ||
| 95 | The first expansion should expand the input (a prefix-string) to a | ||
| 96 | string in the buffer containing no whitespace character, the second | ||
| 97 | expansion, after adding a space to the first expansion, should extend | ||
| 98 | the string with the following string in the buffer up to the next | ||
| 99 | whitespace character." | ||
| 100 | (with-dabbrev-test | ||
| 101 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 102 | (goto-char (point-max)) | ||
| 103 | (terpri) | ||
| 104 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 105 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) | ||
| 106 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 107 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")))) | ||
| 108 | |||
| 109 | (ert-deftest dabbrev-expand-test-same-buffer-2 () | ||
| 110 | "Test expanding a string plus space twice within a single buffer. | ||
| 111 | Each expansion should extend the string with the following string in the | ||
| 112 | buffer up to the next whitespace character." | ||
| 113 | (with-dabbrev-test | ||
| 114 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 115 | (goto-char (point-max)) | ||
| 116 | (terpri) | ||
| 117 | (execute-kbd-macro (kbd "Indic SPC M-/")) | ||
| 118 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")) | ||
| 119 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 120 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and Khmer")))) | ||
| 121 | |||
| 122 | (ert-deftest dabbrev-expand-test-same-buffer-3 () | ||
| 123 | "Test replacing an expansion within a single buffer." | ||
| 124 | (with-dabbrev-test | ||
| 125 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 126 | (goto-char (point-max)) | ||
| 127 | (terpri) | ||
| 128 | (insert-file-contents (ert-resource-file "dabbrev-expand.el")) | ||
| 129 | (goto-char (point-max)) | ||
| 130 | (terpri) | ||
| 131 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 132 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indicate")) | ||
| 133 | (kill-whole-line) | ||
| 134 | (execute-kbd-macro (kbd "Ind M-/ M-/")) | ||
| 135 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) | ||
| 136 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 137 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")))) | ||
| 138 | |||
| 139 | (ert-deftest dabbrev-expand-test-same-buffer-4 () | ||
| 140 | "Test expanding a string in a narrowed-region." | ||
| 141 | (with-dabbrev-test | ||
| 142 | (let (disabled-command-function) ; Enable narrow-to-region. | ||
| 143 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 144 | (goto-char (point-min)) | ||
| 145 | (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n")) | ||
| 146 | (goto-char (point-max)) | ||
| 147 | (terpri) | ||
| 148 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 149 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) | ||
| 150 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 151 | (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and"))))) | ||
| 152 | |||
| 153 | (ert-deftest dabbrev-expand-test-other-buffer-1 () | ||
| 154 | "Test expanding a prefix string to a string from another buffer." | ||
| 155 | (with-dabbrev-test | ||
| 156 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 157 | (switch-to-buffer (get-buffer-create "a" t)) | ||
| 158 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 159 | (should (string= (buffer-string) "Indic")) | ||
| 160 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 161 | (should (string= (buffer-string) "Indic and")) | ||
| 162 | (kill-buffer "a"))) | ||
| 163 | |||
| 164 | (ert-deftest dabbrev-expand-test-other-buffer-2 () | ||
| 165 | "Test expanding a string + space to a string from another buffer." | ||
| 166 | (with-dabbrev-test | ||
| 167 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 168 | (switch-to-buffer (get-buffer-create "a" t)) | ||
| 169 | (execute-kbd-macro (kbd "Indic SPC M-/")) | ||
| 170 | (should (string= (buffer-string) "Indic and")) | ||
| 171 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 172 | (should (string= (buffer-string) "Indic and Khmer")) | ||
| 173 | (kill-buffer "a"))) | ||
| 174 | |||
| 175 | (ert-deftest dabbrev-expand-test-other-buffer-3 () | ||
| 176 | "Test replacing an expansion with three different buffers. | ||
| 177 | A prefix string in a buffer should find the first expansion in a | ||
| 178 | different buffer and then find a replacement expansion is yet another | ||
| 179 | buffer." | ||
| 180 | (with-dabbrev-test | ||
| 181 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 182 | (find-file (ert-resource-file "dabbrev-expand.el")) | ||
| 183 | (switch-to-buffer (get-buffer-create "a" t)) | ||
| 184 | (emacs-lisp-mode) | ||
| 185 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 186 | (should (string= (buffer-string) "Indicate")) | ||
| 187 | (erase-buffer) | ||
| 188 | (execute-kbd-macro (kbd "Ind M-/ M-/")) | ||
| 189 | (should (string= (buffer-string) "Indic")) | ||
| 190 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 191 | (should (string= (buffer-string) "Indic and")) | ||
| 192 | (kill-buffer "a"))) | ||
| 193 | |||
| 194 | (ert-deftest dabbrev-expand-test-other-buffer-4 () | ||
| 195 | "Test expanding a string using another narrowed buffer." | ||
| 196 | (with-dabbrev-test | ||
| 197 | (let (disabled-command-function) ; Enable narrow-to-region. | ||
| 198 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 199 | (goto-char (point-min)) | ||
| 200 | (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n")) | ||
| 201 | (switch-to-buffer (get-buffer-create "a" t)) | ||
| 202 | (execute-kbd-macro (kbd "Ind M-/")) | ||
| 203 | (should (string= (buffer-string) "Indic")) | ||
| 204 | (execute-kbd-macro (kbd "SPC M-/")) | ||
| 205 | (should (string= (buffer-string) "Indic and")) | ||
| 206 | (kill-buffer "a")))) | ||
| 207 | |||
| 208 | (ert-deftest dabbrev-expand-test-minibuffer-1 () | ||
| 209 | "Test expanding a prefix string twice in the minibuffer. | ||
| 210 | Both expansions should come from the buffer from which the minibuffer | ||
| 211 | was entered." | ||
| 212 | (with-dabbrev-test | ||
| 213 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 214 | (with-selected-window (minibuffer-window) | ||
| 215 | (insert "Ind") | ||
| 216 | (dabbrev-expand nil) | ||
| 217 | (should (string= (minibuffer-contents) "Indic")) | ||
| 218 | (insert " ") | ||
| 219 | (dabbrev-expand nil) | ||
| 220 | (should (string= (minibuffer-contents) "Indic and")) | ||
| 221 | (delete-minibuffer-contents)))) | ||
| 222 | |||
| 223 | (ert-deftest dabbrev-expand-test-minibuffer-2 () | ||
| 224 | "Test expanding a string + space in the minibuffer. | ||
| 225 | The expansions should come from the buffer from which the minibuffer was | ||
| 226 | entered." | ||
| 227 | (with-dabbrev-test | ||
| 228 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 229 | (with-selected-window (minibuffer-window) | ||
| 230 | (insert "Indic ") | ||
| 231 | (dabbrev-expand nil) | ||
| 232 | (should (string= (minibuffer-contents) "Indic and")) | ||
| 233 | (insert " ") | ||
| 234 | (dabbrev-expand nil) | ||
| 235 | (should (string= (buffer-string) "Indic and Khmer")) | ||
| 236 | (delete-minibuffer-contents)))) | ||
| 237 | |||
| 238 | ;; FIXME: Why is dabbrev--reset-global-variables needed here? | ||
| 239 | (ert-deftest dabbrev-expand-test-minibuffer-3 () | ||
| 240 | "Test replacing an expansion in the minibuffer using two buffers. | ||
| 241 | The first expansion should befound in the buffer from which the | ||
| 242 | minibuffer was entered, the replacement should found in another buffer." | ||
| 243 | (with-dabbrev-test | ||
| 244 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 245 | (find-file (ert-resource-file "dabbrev-expand.el")) | ||
| 246 | (with-selected-window (minibuffer-window) | ||
| 247 | (insert "Ind") | ||
| 248 | (dabbrev-expand nil) | ||
| 249 | (should (string= (minibuffer-contents) "Indicate")) | ||
| 250 | (kill-whole-line) | ||
| 251 | (dabbrev--reset-global-variables) | ||
| 252 | (insert "Ind") | ||
| 253 | (dabbrev-expand nil) | ||
| 254 | (dabbrev-expand nil) | ||
| 255 | (should (string= (minibuffer-contents) "Indic")) | ||
| 256 | (dabbrev--reset-global-variables) | ||
| 257 | (insert " ") | ||
| 258 | (dabbrev-expand nil) | ||
| 259 | (should (string= (minibuffer-contents) "Indic and")) | ||
| 260 | (delete-minibuffer-contents)))) | ||
| 261 | |||
| 262 | (ert-deftest dabbrev-expand-test-minibuffer-4 () | ||
| 263 | "Test expansion in the minibuffer using another narrowed buffer." | ||
| 264 | (with-dabbrev-test | ||
| 265 | (let (disabled-command-function) ; Enable narrow-to-region. | ||
| 266 | (find-file (ert-resource-file "INSTALL_BEGIN")) | ||
| 267 | (goto-char (point-min)) | ||
| 268 | (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n"))) | ||
| 269 | (with-selected-window (minibuffer-window) | ||
| 270 | (insert "Ind") | ||
| 271 | (dabbrev-expand nil) | ||
| 272 | (should (string= (minibuffer-contents) "Indic")) | ||
| 273 | (insert " ") | ||
| 274 | (dabbrev-expand nil) | ||
| 275 | (should (string= (minibuffer-contents) "Indic and")) | ||
| 276 | (delete-minibuffer-contents)))) | ||
| 277 | |||
| 71 | ;;; dabbrev-tests.el ends here | 278 | ;;; dabbrev-tests.el ends here |