diff options
| author | Juri Linkov | 2019-11-10 00:04:13 +0200 |
|---|---|---|
| committer | Juri Linkov | 2019-11-10 00:04:13 +0200 |
| commit | a26a8cc1c85f29fb11209c16d53a8ae4e4ab7ced (patch) | |
| tree | 73026908995a8daa8a96a6b1d0ebd9b64e169992 /lisp | |
| parent | 898cdc67f19ca15f4ac2b447adf350188baef604 (diff) | |
| download | emacs-a26a8cc1c85f29fb11209c16d53a8ae4e4ab7ced.tar.gz emacs-a26a8cc1c85f29fb11209c16d53a8ae4e4ab7ced.zip | |
'y-or-n-p' now uses the minibuffer to read 'y' or 'n' answer (bug#38076)
* doc/lispref/minibuf.texi (Yes-or-No Queries): Update the fact
that y-or-n-p uses the minibuffer.
* lisp/subr.el (y-or-n-p-history-variable): New variable.
(y-or-n-p-map): New keymap.
(y-or-n-p-insert-y, y-or-n-p-insert-n, y-or-n-p-insert-other):
New commands.
(y-or-n-p): Rewrite to use read-from-minibuffer and make-composed-keymap
with y-or-n-p-map and query-replace-map.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/subr.el | 103 |
1 files changed, 69 insertions, 34 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 85e7187fb6b..8ac2f868c01 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -2668,6 +2668,66 @@ floating point support." | |||
| 2668 | ;; Behind display-popup-menus-p test. | 2668 | ;; Behind display-popup-menus-p test. |
| 2669 | (declare-function x-popup-dialog "menu.c" (position contents &optional header)) | 2669 | (declare-function x-popup-dialog "menu.c" (position contents &optional header)) |
| 2670 | 2670 | ||
| 2671 | (defvar y-or-n-p-history-variable nil | ||
| 2672 | "History list symbol to add `y-or-n-p' answers to.") | ||
| 2673 | |||
| 2674 | (defvar y-or-n-p-map | ||
| 2675 | (let ((map (make-sparse-keymap))) | ||
| 2676 | (set-keymap-parent map minibuffer-local-map) | ||
| 2677 | |||
| 2678 | (dolist (symbol '(act act-and-show act-and-exit automatic)) | ||
| 2679 | (define-key map (vector 'remap symbol) 'y-or-n-p-insert-y)) | ||
| 2680 | |||
| 2681 | (define-key map [remap skip] 'y-or-n-p-insert-n) | ||
| 2682 | |||
| 2683 | (dolist (symbol '(help backup undo undo-all edit edit-replacement | ||
| 2684 | delete-and-edit ignore self-insert-command)) | ||
| 2685 | (define-key map (vector 'remap symbol) 'y-or-n-p-insert-other)) | ||
| 2686 | |||
| 2687 | (define-key map [remap recenter] 'minibuffer-recenter-top-bottom) | ||
| 2688 | (define-key map [remap scroll-up] 'minibuffer-scroll-up-command) | ||
| 2689 | (define-key map [remap scroll-down] 'minibuffer-scroll-down-command) | ||
| 2690 | (define-key map [remap scroll-other-window] 'minibuffer-scroll-other-window) | ||
| 2691 | (define-key map [remap scroll-other-window-down] 'minibuffer-scroll-other-window-down) | ||
| 2692 | |||
| 2693 | (define-key map [escape] 'abort-recursive-edit) | ||
| 2694 | (dolist (symbol '(quit exit exit-prefix)) | ||
| 2695 | (define-key map (vector 'remap symbol) 'abort-recursive-edit)) | ||
| 2696 | |||
| 2697 | ;; FIXME: try catch-all instead of explicit bindings: | ||
| 2698 | ;; (define-key map [remap t] 'y-or-n-p-insert-other) | ||
| 2699 | |||
| 2700 | map) | ||
| 2701 | "Keymap that defines additional bindings for `y-or-n-p' answers.") | ||
| 2702 | |||
| 2703 | (defun y-or-n-p-insert-y () | ||
| 2704 | "Insert the answer \"y\" and exit the minibuffer of `y-or-n-p'. | ||
| 2705 | Discard all previous input before inserting and exiting the minibuffer." | ||
| 2706 | (interactive) | ||
| 2707 | (delete-minibuffer-contents) | ||
| 2708 | (insert "y") | ||
| 2709 | (exit-minibuffer)) | ||
| 2710 | |||
| 2711 | (defun y-or-n-p-insert-n () | ||
| 2712 | "Insert the answer \"n\" and exit the minibuffer of `y-or-n-p'. | ||
| 2713 | Discard all previous input before inserting and exiting the minibuffer." | ||
| 2714 | (interactive) | ||
| 2715 | (delete-minibuffer-contents) | ||
| 2716 | (insert "n") | ||
| 2717 | (exit-minibuffer)) | ||
| 2718 | |||
| 2719 | (defun y-or-n-p-insert-other () | ||
| 2720 | "Handle inserting of other answers in the minibuffer of `y-or-n-p'. | ||
| 2721 | Display an error on trying to insert a disallowed character. | ||
| 2722 | Also discard all previous input in the minibuffer." | ||
| 2723 | (interactive) | ||
| 2724 | (delete-minibuffer-contents) | ||
| 2725 | (ding) | ||
| 2726 | (minibuffer-message "Please answer y or n") | ||
| 2727 | (sit-for 2)) | ||
| 2728 | |||
| 2729 | (defvar empty-history) | ||
| 2730 | |||
| 2671 | (defun y-or-n-p (prompt) | 2731 | (defun y-or-n-p (prompt) |
| 2672 | "Ask user a \"y or n\" question. | 2732 | "Ask user a \"y or n\" question. |
| 2673 | Return t if answer is \"y\" and nil if it is \"n\". | 2733 | Return t if answer is \"y\" and nil if it is \"n\". |
| @@ -2683,16 +2743,13 @@ documentation of that variable for more information. In this | |||
| 2683 | case, the useful bindings are `act', `skip', `recenter', | 2743 | case, the useful bindings are `act', `skip', `recenter', |
| 2684 | `scroll-up', `scroll-down', and `quit'. | 2744 | `scroll-up', `scroll-down', and `quit'. |
| 2685 | An `act' response means yes, and a `skip' response means no. | 2745 | An `act' response means yes, and a `skip' response means no. |
| 2686 | A `quit' response means to invoke `keyboard-quit'. | 2746 | A `quit' response means to invoke `abort-recursive-edit'. |
| 2687 | If the user enters `recenter', `scroll-up', or `scroll-down' | 2747 | If the user enters `recenter', `scroll-up', or `scroll-down' |
| 2688 | responses, perform the requested window recentering or scrolling | 2748 | responses, perform the requested window recentering or scrolling |
| 2689 | and ask again. | 2749 | and ask again. |
| 2690 | 2750 | ||
| 2691 | Under a windowing system a dialog box will be used if `last-nonmenu-event' | 2751 | Under a windowing system a dialog box will be used if `last-nonmenu-event' |
| 2692 | is nil and `use-dialog-box' is non-nil." | 2752 | is nil and `use-dialog-box' is non-nil." |
| 2693 | ;; ¡Beware! when I tried to edebug this code, Emacs got into a weird state | ||
| 2694 | ;; where all the keys were unbound (i.e. it somehow got triggered | ||
| 2695 | ;; within read-key, apparently). I had to kill it. | ||
| 2696 | (let ((answer 'recenter) | 2753 | (let ((answer 'recenter) |
| 2697 | (padded (lambda (prompt &optional dialog) | 2754 | (padded (lambda (prompt &optional dialog) |
| 2698 | (let ((l (length prompt))) | 2755 | (let ((l (length prompt))) |
| @@ -2718,36 +2775,14 @@ is nil and `use-dialog-box' is non-nil." | |||
| 2718 | answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip))))) | 2775 | answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip))))) |
| 2719 | (t | 2776 | (t |
| 2720 | (setq prompt (funcall padded prompt)) | 2777 | (setq prompt (funcall padded prompt)) |
| 2721 | (while | 2778 | (discard-input) |
| 2722 | (let* ((scroll-actions '(recenter scroll-up scroll-down | 2779 | (let* ((empty-history '()) |
| 2723 | scroll-other-window scroll-other-window-down)) | 2780 | (str (read-from-minibuffer |
| 2724 | (key | 2781 | prompt nil |
| 2725 | (let ((cursor-in-echo-area t)) | 2782 | (make-composed-keymap y-or-n-p-map query-replace-map) |
| 2726 | (when minibuffer-auto-raise | 2783 | nil |
| 2727 | (raise-frame (window-frame (minibuffer-window)))) | 2784 | (or y-or-n-p-history-variable 'empty-history)))) |
| 2728 | (read-key (propertize (if (memq answer scroll-actions) | 2785 | (setq answer (if (member str '("y" "Y")) 'act 'skip))))) |
| 2729 | prompt | ||
| 2730 | (concat "Please answer y or n. " | ||
| 2731 | prompt)) | ||
| 2732 | 'face 'minibuffer-prompt))))) | ||
| 2733 | (setq answer (lookup-key query-replace-map (vector key) t)) | ||
| 2734 | (cond | ||
| 2735 | ((memq answer '(skip act)) nil) | ||
| 2736 | ((eq answer 'recenter) | ||
| 2737 | (recenter) t) | ||
| 2738 | ((eq answer 'scroll-up) | ||
| 2739 | (ignore-errors (scroll-up-command)) t) | ||
| 2740 | ((eq answer 'scroll-down) | ||
| 2741 | (ignore-errors (scroll-down-command)) t) | ||
| 2742 | ((eq answer 'scroll-other-window) | ||
| 2743 | (ignore-errors (scroll-other-window)) t) | ||
| 2744 | ((eq answer 'scroll-other-window-down) | ||
| 2745 | (ignore-errors (scroll-other-window-down)) t) | ||
| 2746 | ((or (memq answer '(exit-prefix quit)) (eq key ?\e)) | ||
| 2747 | (signal 'quit nil) t) | ||
| 2748 | (t t))) | ||
| 2749 | (ding) | ||
| 2750 | (discard-input)))) | ||
| 2751 | (let ((ret (eq answer 'act))) | 2786 | (let ((ret (eq answer 'act))) |
| 2752 | (unless noninteractive | 2787 | (unless noninteractive |
| 2753 | (message "%s%c" prompt (if ret ?y ?n))) | 2788 | (message "%s%c" prompt (if ret ?y ?n))) |