diff options
| author | Stefan Monnier | 2020-10-31 09:07:53 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2020-10-31 09:07:53 -0400 |
| commit | 7103192cd2b0434c7acf712d0b7cf5a2f7b19e75 (patch) | |
| tree | 14333414af14ff4035a27ec26f67ab177394ae01 | |
| parent | c3a20804a81826ec091a4a096c1987a61e412580 (diff) | |
| download | emacs-7103192cd2b0434c7acf712d0b7cf5a2f7b19e75.tar.gz emacs-7103192cd2b0434c7acf712d0b7cf5a2f7b19e75.zip | |
* src/xdisp.c (syms_of_xdisp) <"scroll-minibuffer-conservatively">: New var
Fix bug#44070, which causes the minibuffer display to jump upon minor edit
(redisplay_window): Obey it.
* lisp/simple.el (end-of-buffer): Obey it.
* test/src/xdisp-tests.el (xdisp-tests--in-minibuffer): New macro,
extracted from `xdisp-tests--minibuffer-resizing`.
(xdisp-tests--minibuffer-resizing): Use it.
(xdisp-tests--minibuffer-scroll): New test.
| -rw-r--r-- | doc/emacs/display.texi | 4 | ||||
| -rw-r--r-- | etc/NEWS | 3 | ||||
| -rw-r--r-- | lisp/simple.el | 6 | ||||
| -rw-r--r-- | src/xdisp.c | 17 | ||||
| -rw-r--r-- | test/src/xdisp-tests.el | 71 |
5 files changed, 72 insertions, 29 deletions
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 02859d522e3..7dadb0966f2 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi | |||
| @@ -244,6 +244,7 @@ point vertically in the window, but there are several ways to alter | |||
| 244 | this behavior. | 244 | this behavior. |
| 245 | 245 | ||
| 246 | @vindex scroll-conservatively | 246 | @vindex scroll-conservatively |
| 247 | @vindex scroll-minibuffer-conservatively | ||
| 247 | If you set @code{scroll-conservatively} to a small number @var{n}, | 248 | If you set @code{scroll-conservatively} to a small number @var{n}, |
| 248 | then moving point just a little off the screen (no more than @var{n} | 249 | then moving point just a little off the screen (no more than @var{n} |
| 249 | lines) causes Emacs to scroll just enough to bring point back on | 250 | lines) causes Emacs to scroll just enough to bring point back on |
| @@ -255,6 +256,9 @@ moves; Emacs always scrolls text just enough to bring point into view, | |||
| 255 | either at the top or bottom of the window depending on the scroll | 256 | either at the top or bottom of the window depending on the scroll |
| 256 | direction. By default, @code{scroll-conservatively} is@tie{}0, which | 257 | direction. By default, @code{scroll-conservatively} is@tie{}0, which |
| 257 | means to always center point in the window. | 258 | means to always center point in the window. |
| 259 | This said, in minibuffer windows, scrolling is always conservative by | ||
| 260 | default because @code{scroll-minibuffer-conservatively} is non-nil, | ||
| 261 | which takes precedence over @code{scroll-conservatively}. | ||
| 258 | 262 | ||
| 259 | @vindex scroll-step | 263 | @vindex scroll-step |
| 260 | Another way to control automatic scrolling is to customize the | 264 | Another way to control automatic scrolling is to customize the |
| @@ -85,6 +85,9 @@ useful on systems such as FreeBSD which ships only with "etc/termcap". | |||
| 85 | 85 | ||
| 86 | * Changes in Emacs 28.1 | 86 | * Changes in Emacs 28.1 |
| 87 | 87 | ||
| 88 | ** Minibuffer scrolling is now conservative by default. | ||
| 89 | This is controlled by the new variable 'scroll-minibuffer-conservatively'. | ||
| 90 | |||
| 88 | +++ | 91 | +++ |
| 89 | ** New system for displaying documentation for groups of function. | 92 | ** New system for displaying documentation for groups of function. |
| 90 | This can either be used by saying 'M-x shortdoc-display-group' and | 93 | This can either be used by saying 'M-x shortdoc-display-group' and |
diff --git a/lisp/simple.el b/lisp/simple.el index a9d79d031e8..d871be104cf 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -1134,7 +1134,11 @@ is supplied, or Transient Mark mode is enabled and the mark is active." | |||
| 1134 | ;; If the end of the buffer is not already on the screen, | 1134 | ;; If the end of the buffer is not already on the screen, |
| 1135 | ;; then scroll specially to put it near, but not at, the bottom. | 1135 | ;; then scroll specially to put it near, but not at, the bottom. |
| 1136 | (overlay-recenter (point)) | 1136 | (overlay-recenter (point)) |
| 1137 | (recenter -3)))) | 1137 | ;; FIXME: Arguably if `scroll-conservatively' is set, then |
| 1138 | ;; we should pass -1 to `recenter'. | ||
| 1139 | (recenter (if (and scroll-minibuffer-conservatively | ||
| 1140 | (window-minibuffer-p)) | ||
| 1141 | -1 -3))))) | ||
| 1138 | 1142 | ||
| 1139 | (defcustom delete-active-region t | 1143 | (defcustom delete-active-region t |
| 1140 | "Whether single-char deletion commands delete an active region. | 1144 | "Whether single-char deletion commands delete an active region. |
diff --git a/src/xdisp.c b/src/xdisp.c index 0e5dffbe007..cc499f33261 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -18820,6 +18820,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 18820 | 18820 | ||
| 18821 | /* Try to scroll by specified few lines. */ | 18821 | /* Try to scroll by specified few lines. */ |
| 18822 | if ((0 < scroll_conservatively | 18822 | if ((0 < scroll_conservatively |
| 18823 | || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w)) | ||
| 18823 | || 0 < emacs_scroll_step | 18824 | || 0 < emacs_scroll_step |
| 18824 | || temp_scroll_step | 18825 | || temp_scroll_step |
| 18825 | || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)) | 18826 | || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)) |
| @@ -18830,7 +18831,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) | |||
| 18830 | /* The function returns -1 if new fonts were loaded, 1 if | 18831 | /* The function returns -1 if new fonts were loaded, 1 if |
| 18831 | successful, 0 if not successful. */ | 18832 | successful, 0 if not successful. */ |
| 18832 | int ss = try_scrolling (window, just_this_one_p, | 18833 | int ss = try_scrolling (window, just_this_one_p, |
| 18833 | scroll_conservatively, | 18834 | ((scroll_minibuffer_conservatively |
| 18835 | && MINI_WINDOW_P (w)) | ||
| 18836 | ? SCROLL_LIMIT + 1 | ||
| 18837 | : scroll_conservatively), | ||
| 18834 | emacs_scroll_step, | 18838 | emacs_scroll_step, |
| 18835 | temp_scroll_step, last_line_misfit); | 18839 | temp_scroll_step, last_line_misfit); |
| 18836 | switch (ss) | 18840 | switch (ss) |
| @@ -34538,7 +34542,14 @@ syms_of_xdisp (void) | |||
| 34538 | 34542 | ||
| 34539 | DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)"); | 34543 | DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)"); |
| 34540 | 34544 | ||
| 34541 | DEFVAR_BOOL("inhibit-message", inhibit_message, | 34545 | DEFVAR_BOOL ("scroll-minibuffer-conservatively", |
| 34546 | scroll_minibuffer_conservatively, | ||
| 34547 | doc: /* Non-nil means scroll conservatively in minibuffer windows. | ||
| 34548 | When the value is nil, scrolling in minibuffer windows obeys the | ||
| 34549 | settings of `scroll-conservatively'. */); | ||
| 34550 | scroll_minibuffer_conservatively = true; /* bug#44070 */ | ||
| 34551 | |||
| 34552 | DEFVAR_BOOL ("inhibit-message", inhibit_message, | ||
| 34542 | doc: /* Non-nil means calls to `message' are not displayed. | 34553 | doc: /* Non-nil means calls to `message' are not displayed. |
| 34543 | They are still logged to the *Messages* buffer. | 34554 | They are still logged to the *Messages* buffer. |
| 34544 | 34555 | ||
| @@ -34546,7 +34557,7 @@ Do NOT set this globally to a non-nil value, as doing that will | |||
| 34546 | disable messages everywhere, including in I-search and other | 34557 | disable messages everywhere, including in I-search and other |
| 34547 | places where they are necessary. This variable is intended to | 34558 | places where they are necessary. This variable is intended to |
| 34548 | be let-bound around code that needs to disable messages temporarily. */); | 34559 | be let-bound around code that needs to disable messages temporarily. */); |
| 34549 | inhibit_message = 0; | 34560 | inhibit_message = false; |
| 34550 | 34561 | ||
| 34551 | message_dolog_marker1 = Fmake_marker (); | 34562 | message_dolog_marker1 = Fmake_marker (); |
| 34552 | staticpro (&message_dolog_marker1); | 34563 | staticpro (&message_dolog_marker1); |
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el index 95c39dacc3e..fad90fad531 100644 --- a/test/src/xdisp-tests.el +++ b/test/src/xdisp-tests.el | |||
| @@ -21,34 +21,55 @@ | |||
| 21 | 21 | ||
| 22 | (require 'ert) | 22 | (require 'ert) |
| 23 | 23 | ||
| 24 | (defmacro xdisp-tests--in-minibuffer (&rest body) | ||
| 25 | (declare (debug t) (indent 0)) | ||
| 26 | `(catch 'result | ||
| 27 | (minibuffer-with-setup-hook | ||
| 28 | (lambda () | ||
| 29 | (let ((redisplay-skip-initial-frame nil) | ||
| 30 | (executing-kbd-macro nil)) ;Don't skip redisplay | ||
| 31 | (throw 'result (progn . ,body)))) | ||
| 32 | (let ((executing-kbd-macro t)) ;Force real minibuffer in `read-string'. | ||
| 33 | (read-string "toto: "))))) | ||
| 34 | |||
| 24 | (ert-deftest xdisp-tests--minibuffer-resizing () ;; bug#43519 | 35 | (ert-deftest xdisp-tests--minibuffer-resizing () ;; bug#43519 |
| 25 | ;; FIXME: This test returns success when run in batch but | ||
| 26 | ;; it's only a lucky accident: it also returned success | ||
| 27 | ;; when bug#43519 was not fixed. | ||
| 28 | (should | 36 | (should |
| 29 | (equal | 37 | (equal |
| 30 | t | 38 | t |
| 31 | (catch 'result | 39 | (xdisp-tests--in-minibuffer |
| 32 | (minibuffer-with-setup-hook | 40 | (insert "hello") |
| 33 | (lambda () | 41 | (let ((ol (make-overlay (point) (point))) |
| 34 | (insert "hello") | 42 | (max-mini-window-height 1) |
| 35 | (let ((ol (make-overlay (point) (point))) | 43 | (text "askdjfhaklsjdfhlkasjdfhklasdhflkasdhflkajsdhflkashdfkljahsdlfkjahsdlfkjhasldkfhalskdjfhalskdfhlaksdhfklasdhflkasdhflkasdhflkajsdhklajsdgh")) |
| 36 | (redisplay-skip-initial-frame nil) | 44 | ;; (save-excursion (insert text)) |
| 37 | (max-mini-window-height 1) | 45 | ;; (sit-for 2) |
| 38 | (text "askdjfhaklsjdfhlkasjdfhklasdhflkasdhflkajsdhflkashdfkljahsdlfkjahsdlfkjhasldkfhalskdjfhalskdfhlaksdhfklasdhflkasdhflkasdhflkajsdhklajsdgh")) | 46 | ;; (delete-region (point) (point-max)) |
| 39 | ;; (save-excursion (insert text)) | 47 | (put-text-property 0 1 'cursor t text) |
| 40 | ;; (sit-for 2) | 48 | (overlay-put ol 'after-string text) |
| 41 | ;; (delete-region (point) (point-max)) | 49 | (redisplay 'force) |
| 42 | (put-text-property 0 1 'cursor t text) | 50 | ;; Make sure we do the see "hello" text. |
| 43 | (overlay-put ol 'after-string text) | 51 | (prog1 (equal (window-start) (point-min)) |
| 44 | (let ((executing-kbd-macro nil)) ;Don't skip redisplay | 52 | ;; (list (window-start) (window-end) (window-width)) |
| 45 | (redisplay 'force)) | 53 | (delete-overlay ol))))))) |
| 46 | (throw 'result | 54 | |
| 47 | ;; Make sure we do the see "hello" text. | 55 | (ert-deftest xdisp-tests--minibuffer-scroll () ;; bug#44070 |
| 48 | (prog1 (equal (window-start) (point-min)) | 56 | (let ((posns |
| 49 | ;; (list (window-start) (window-end) (window-width)) | 57 | (xdisp-tests--in-minibuffer |
| 50 | (delete-overlay ol))))) | 58 | (let ((max-mini-window-height 4)) |
| 51 | (let ((executing-kbd-macro t)) ;Force real minibuffer in `read-string'. | 59 | (dotimes (_ 80) (insert "\nhello")) |
| 52 | (read-string "toto: "))))))) | 60 | (beginning-of-buffer) |
| 61 | (redisplay 'force) | ||
| 62 | (end-of-buffer) | ||
| 63 | ;; A simple edit like removing the last `o' shouldn't cause | ||
| 64 | ;; the rest of the minibuffer's text to move. | ||
| 65 | (list | ||
| 66 | (progn (redisplay 'force) (window-start)) | ||
| 67 | (progn (delete-char -1) | ||
| 68 | (redisplay 'force) (window-start)) | ||
| 69 | (progn (goto-char (point-min)) (redisplay 'force) | ||
| 70 | (goto-char (point-max)) (redisplay 'force) | ||
| 71 | (window-start))))))) | ||
| 72 | (should (equal (nth 0 posns) (nth 1 posns))) | ||
| 73 | (should (equal (nth 1 posns) (nth 2 posns))))) | ||
| 53 | 74 | ||
| 54 | ;;; xdisp-tests.el ends here | 75 | ;;; xdisp-tests.el ends here |