From 011474aa5af24faeceac60348315552313774b10 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Sun, 9 Sep 2012 14:43:47 +0800 Subject: [PATCH] Allow scrolling in y-or-n-p. * lisp/replace.el (query-replace-map): Bind four new symbols for requesting window scrolling. * lisp/subr.el (y-or-n-p): Handle the window-scrolling bindings in query-replace-map. * lisp/custom.el (custom-theme-load-confirm): Use y-or-n-p. * lisp/window.el (scroll-other-window-down): Make the arg optional. * lisp/emacs-lisp/map-ynp.el (map-y-or-n-p): Don't bind scrolling keys since they are now in query-replace-map. * doc/lispref/minibuf.texi (Yes-or-No Queries): Document recentering and scrolling in y-or-n-p. Remove gratuitous example. * doc/lispref/searching.texi (Search and Replace): Document window scrolling entries in query-replace-map. Fixes: debbugs:8948 --- doc/lispref/ChangeLog | 8 +++++++ doc/lispref/minibuf.texi | 48 +++++++------------------------------- doc/lispref/searching.texi | 8 ++++++- etc/NEWS | 4 ++++ lisp/ChangeLog | 15 ++++++++++++ lisp/custom.el | 45 +++++++++++------------------------ lisp/emacs-lisp/map-ynp.el | 10 -------- lisp/replace.el | 22 +++++++++++++---- lisp/subr.el | 42 ++++++++++++++++++++++++--------- lisp/window.el | 2 +- 10 files changed, 105 insertions(+), 99 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 57ee374af49..79691bfb181 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,11 @@ +2012-09-09 Chong Yidong + + * minibuf.texi (Yes-or-No Queries): Document recentering and + scrolling in y-or-n-p. Remove gratuitous example. + + * searching.texi (Search and Replace): Document window scrolling + entries in query-replace-map. + 2012-09-08 Chong Yidong * syntax.texi (Syntax Table Internals): Define "raw syntax diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index 4cf096b8663..cdc47b7c91d 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -1888,46 +1888,14 @@ Echo Area}), which uses the same screen space as the minibuffer. The cursor moves to the echo area while the question is being asked. The answers and their meanings, even @samp{y} and @samp{n}, are not -hardwired. The keymap @code{query-replace-map} specifies them. -@xref{Search and Replace}. - -In the following example, the user first types @kbd{q}, which is -invalid. At the next prompt the user types @kbd{y}. - -@c Need an interactive example, because otherwise the return value -@c obscures the display of the valid answer. -@smallexample -@group -(defun ask () - (interactive) - (y-or-n-p "Do you need a lift? ")) - -;; @r{After evaluation of the preceding definition, @kbd{M-x ask}} -;; @r{causes the following prompt to appear in the echo area:} -@end group - -@group ----------- Echo area ---------- -Do you need a lift? (y or n) ----------- Echo area ---------- -@end group - -;; @r{If the user then types @kbd{q}, the following appears:} - -@group ----------- Echo area ---------- -Please answer y or n. Do you need a lift? (y or n) ----------- Echo area ---------- -@end group - -;; @r{When the user types a valid answer,} -;; @r{it is displayed after the question:} - -@group ----------- Echo area ---------- -Do you need a lift? (y or n) y ----------- Echo area ---------- -@end group +hardwired, and are specified by the keymap @code{query-replace-map} +(@pxref{Search and Replace}). In particular, if the user enters the +special responses @code{recenter}, @code{scroll-up}, +@code{scroll-down}, @code{scroll-other-window}, or +@code{scroll-other-window-down} (respectively bound to @kbd{C-l}, +@kbd{C-v}, @kbd{M-v}, @kbd{C-M-v} and @kbd{C-M-S-v} in +@code{query-replace-map}), this function performs the specified window +recentering or scrolling operation, and poses the question again. @end smallexample @noindent diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi index 0fa681ecb51..edd1d30e28d 100644 --- a/doc/lispref/searching.texi +++ b/doc/lispref/searching.texi @@ -1796,7 +1796,13 @@ Delete the text being considered, then enter a recursive edit to replace it. @item recenter -Redisplay and center the window, then ask the same question again. +@itemx scroll-up +@itemx scroll-down +@itemx scroll-other-window +@itemx scroll-other-window-down +Perform the specified window scroll operation, then ask the same +question again. Only @code{y-or-n-p} and related functions use this +answer. @item quit Perform a quit right away. Only @code{y-or-n-p} and related functions diff --git a/etc/NEWS b/etc/NEWS index 742744fc9dd..dac7915767d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -78,6 +78,10 @@ been adding them there, put them somewhere else, eg site-lisp. * Changes in Emacs 24.3 +** You can now scroll the selected window in most y-or-n prompts. +Typing C-v or M-v at a prompt scrolls forward or backward +respectively, without leaving the y-or-n prompt. + ** Help changes *** `C-h f' (describe-function) can now perform autoloading. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index d7f730556ac..8f089af6f5c 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,18 @@ +2012-09-09 Chong Yidong + + * replace.el (query-replace-map): Bind four new symbols for + requesting window scrolling. + + * subr.el (y-or-n-p): Handle the window-scrolling bindings in + query-replace-map (Bug#8948). + + * custom.el (custom-theme-load-confirm): Use y-or-n-p. + + * emacs-lisp/map-ynp.el (map-y-or-n-p): Don't bind scrolling keys + since they are now in query-replace-map. + + * window.el (scroll-other-window-down): Make the arg optional. + 2012-09-09 Chong Yidong * files.el (hack-local-variables-confirm): Use quit-window to kill diff --git a/lisp/custom.el b/lisp/custom.el index fb166dd35f7..3eb2895888d 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -1223,38 +1223,19 @@ Return t if THEME was successfully loaded, nil otherwise." "Query the user about loading a Custom theme that may not be safe. The theme should be in the current buffer. If the user agrees, query also about adding HASH to `custom-safe-themes'." - (if noninteractive - nil - (let ((exit-chars '(?y ?n ?\s)) - window prompt char) - (save-window-excursion - (rename-buffer "*Custom Theme*" t) - (emacs-lisp-mode) - (setq window (display-buffer (current-buffer))) - (setq prompt - (format "Loading a theme can run Lisp code. Really load?%s" - (if (and window - (< (line-number-at-pos (point-max)) - (window-body-height))) - " (y or n) " - (push ?\C-v exit-chars) - "\nType y or n, or C-v to scroll: "))) - (goto-char (point-min)) - (while (null char) - (setq char (read-char-choice prompt exit-chars)) - (when (eq char ?\C-v) - (if window - (with-selected-window window - (condition-case nil - (scroll-up) - (error (goto-char (point-min)))))) - (setq char nil))) - (when (memq char '(?\s ?y)) - ;; Offer to save to `custom-safe-themes'. - (and (or custom-file user-init-file) - (y-or-n-p "Treat this theme as safe in future sessions? ") - (customize-push-and-save 'custom-safe-themes (list hash))) - t))))) + (unless noninteractive + (save-window-excursion + (rename-buffer "*Custom Theme*" t) + (emacs-lisp-mode) + (setq window (pop-to-buffer (current-buffer))) + (goto-char (point-min)) + (prog1 (when (y-or-n-p "Loading a theme can run Lisp code. Really load? ") + ;; Offer to save to `custom-safe-themes'. + (and (or custom-file user-init-file) + (y-or-n-p "Treat this theme as safe in future sessions? ") + (customize-push-and-save 'custom-safe-themes (list hash))) + t) + (quit-window))))) (defun custom-theme-name-valid-p (name) "Return t if NAME is a valid name for a Custom theme, nil otherwise. diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el index e7806440bf3..289751f4944 100644 --- a/lisp/emacs-lisp/map-ynp.el +++ b/lisp/emacs-lisp/map-ynp.el @@ -123,16 +123,6 @@ Returns the number of actions taken." map (let ((map (make-sparse-keymap))) (set-keymap-parent map query-replace-map) - (define-key map [?\C-\M-v] 'scroll-other-window) - (define-key map [M-next] 'scroll-other-window) - (define-key map [?\C-\M-\S-v] 'scroll-other-window-down) - (define-key map [M-prior] 'scroll-other-window-down) - ;; The above are rather inconvenient, so maybe we should - ;; provide the non-other keys for the other-scroll as well. - ;; (define-key map [?\C-v] 'scroll-other-window) - ;; (define-key map [next] 'scroll-other-window) - ;; (define-key map [?\M-v] 'scroll-other-window-down) - ;; (define-key map [prior] 'scroll-other-window-down) (dolist (elt action-alist) (define-key map (vector (car elt)) (vector (nth 1 elt)))) map))) diff --git a/lisp/replace.el b/lisp/replace.el index 194805a8f3e..b30b671122e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1617,14 +1617,28 @@ E to edit the replacement string" (define-key map "?" 'help) (define-key map "\C-g" 'quit) (define-key map "\C-]" 'quit) - (define-key map "\e" 'exit-prefix) + (define-key map "\C-v" 'scroll-up) + (define-key map "\M-v" 'scroll-down) + (define-key map [next] 'scroll-up) + (define-key map [prior] 'scroll-down) + (define-key map [?\C-\M-v] 'scroll-other-window) + (define-key map [M-next] 'scroll-other-window) + (define-key map [?\C-\M-\S-v] 'scroll-other-window-down) + (define-key map [M-prior] 'scroll-other-window-down) + ;; Binding ESC would prohibit the M-v binding. Instead, callers + ;; should check for ESC specially. + ;; (define-key map "\e" 'exit-prefix) (define-key map [escape] 'exit-prefix) map) - "Keymap that defines the responses to questions in `query-replace'. + "Keymap of responses to questions posed by commands like `query-replace'. The \"bindings\" in this map are not commands; they are answers. The valid answers include `act', `skip', `act-and-show', -`exit', `act-and-exit', `edit', `edit-replacement', `delete-and-edit', -`recenter', `automatic', `backup', `exit-prefix', `quit', and `help'.") +`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up', +`scroll-down', `scroll-other-window', `scroll-other-window-down', +`edit', `edit-replacement', `delete-and-edit', `automatic', +`backup', `quit', and `help'. + +This keymap is used by `y-or-n-p' as well as `query-replace'.") (defvar multi-query-replace-map (let ((map (make-sparse-keymap))) diff --git a/lisp/subr.el b/lisp/subr.el index 21dd270caef..be785ff8fba 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2319,11 +2319,19 @@ floating point support." PROMPT is the string to display to ask the question. It should end in a space; `y-or-n-p' adds \"(y or n) \" to it. -No confirmation of the answer is requested; a single character is enough. -Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses -the bindings in `query-replace-map'; see the documentation of that variable -for more information. In this case, the useful bindings are `act', `skip', -`recenter', and `quit'.\) +No confirmation of the answer is requested; a single character is +enough. SPC also means yes, and DEL means no. + +To be precise, this function translates user input into responses +by consulting the bindings in `query-replace-map'; see the +documentation of that variable for more information. In this +case, the useful bindings are `act', `skip', `recenter', +`scroll-up', `scroll-down', and `quit'. +An `act' response means yes, and a `skip' response means no. +A `quit' response means to invoke `keyboard-quit'. +If the user enters `recenter', `scroll-up', or `scroll-down' +responses, perform the requested window recentering or scrolling +and ask again. Under a windowing system a dialog box will be used if `last-nonmenu-event' is nil and `use-dialog-box' is non-nil." @@ -2355,21 +2363,33 @@ is nil and `use-dialog-box' is non-nil." "" " ") "(y or n) ")) (while - (let* ((key + (let* ((scroll-actions '(recenter scroll-up scroll-down + scroll-other-window scroll-other-window-down)) + (key (let ((cursor-in-echo-area t)) (when minibuffer-auto-raise (raise-frame (window-frame (minibuffer-window)))) - (read-key (propertize (if (eq answer 'recenter) + (read-key (propertize (if (memq answer scroll-actions) prompt (concat "Please answer y or n. " prompt)) 'face 'minibuffer-prompt))))) (setq answer (lookup-key query-replace-map (vector key) t)) (cond - ((memq answer '(skip act)) nil) - ((eq answer 'recenter) (recenter) t) - ((memq answer '(exit-prefix quit)) (signal 'quit nil) t) - (t t))) + ((memq answer '(skip act)) nil) + ((eq answer 'recenter) + (recenter) t) + ((eq answer 'scroll-up) + (ignore-errors (scroll-up-command)) t) + ((eq answer 'scroll-down) + (ignore-errors (scroll-down-command)) t) + ((eq answer 'scroll-other-window) + (ignore-errors (scroll-other-window)) t) + ((eq answer 'scroll-other-window-down) + (ignore-errors (scroll-other-window-down)) t) + ((or (memq answer '(exit-prefix quit)) (eq key ?\e)) + (signal 'quit nil) t) + (t t))) (ding) (discard-input)))) (let ((ret (eq answer 'act))) diff --git a/lisp/window.el b/lisp/window.el index b071a8e9c50..dd1f55450c3 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -6301,7 +6301,7 @@ This is different from `scroll-down-command' that scrolls a full screen." (put 'scroll-down-line 'scroll-command t) -(defun scroll-other-window-down (lines) +(defun scroll-other-window-down (&optional lines) "Scroll the \"other window\" down. For more details, see the documentation for `scroll-other-window'." (interactive "P") -- 2.39.2