diff options
| author | Roland McGrath | 1991-06-29 20:04:01 +0000 |
|---|---|---|
| committer | Roland McGrath | 1991-06-29 20:04:01 +0000 |
| commit | 60205e0bcbcaa8f4ad01226450d80baaf03eccde (patch) | |
| tree | 9efa4458353654af5c053cf3088b6854b2689e5e | |
| parent | 84545e78c3c53148d033d00386d9c1f4ff50f03c (diff) | |
| download | emacs-60205e0bcbcaa8f4ad01226450d80baaf03eccde.tar.gz emacs-60205e0bcbcaa8f4ad01226450d80baaf03eccde.zip | |
Initial revision
| -rw-r--r-- | lisp/map-ynp.el | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/lisp/map-ynp.el b/lisp/map-ynp.el new file mode 100644 index 00000000000..b562234e9a7 --- /dev/null +++ b/lisp/map-ynp.el | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | ;;; map-ynp.el -- General-purpose boolean question-asker. | ||
| 2 | ;;; Copyright (C) 1991 Free Software Foundation, Inc. | ||
| 3 | ;;; Written by Roland McGrath. | ||
| 4 | ;;; | ||
| 5 | ;;; This program is free software; you can redistribute it and/or modify | ||
| 6 | ;;; it under the terms of the GNU General Public License as published by | ||
| 7 | ;;; the Free Software Foundation; either version 1, or (at your option) | ||
| 8 | ;;; any later version. | ||
| 9 | ;;; | ||
| 10 | ;;; This program is distributed in the hope that it will be useful, | ||
| 11 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | ;;; GNU General Public License for more details. | ||
| 14 | ;;; | ||
| 15 | ;;; A copy of the GNU General Public License can be obtained from this | ||
| 16 | ;;; program's author (send electronic mail to roland@ai.mit.edu) or from | ||
| 17 | ;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA | ||
| 18 | ;;; 02139, USA. | ||
| 19 | ;;; | ||
| 20 | ;;; map-y-or-n-p is a general-purpose question-asking function. | ||
| 21 | ;;; It asks a series of y/n questions (a la y-or-n-p), and decides to | ||
| 22 | ;;; applies an action to each element of a list based on the answer. | ||
| 23 | ;;; The nice thing is that you also get some other possible answers | ||
| 24 | ;;; to use, reminiscent of query-replace: ! to answer y to all remaining | ||
| 25 | ;;; questions; ESC or q to answer n to all remaining questions; . to answer | ||
| 26 | ;;; y once and then n for the remainder; and you can get help with C-h. | ||
| 27 | |||
| 28 | (defun map-y-or-n-p-help (object objects action) | ||
| 29 | (format "Type SPC or `y' to %s the current %s; | ||
| 30 | DEL or `n' to skip the current %s; | ||
| 31 | ! to %s all remaining %s; | ||
| 32 | ESC or `q' to exit; | ||
| 33 | or . (period) to %s the current %s and exit." | ||
| 34 | action object object action objects action object)) | ||
| 35 | |||
| 36 | ;;;###autoload | ||
| 37 | (defun map-y-or-n-p (prompter actor list &optional help) | ||
| 38 | "Ask a series of boolean questions. | ||
| 39 | Takes args PROMPTER ACTOR LIST, and optional arg HELP. | ||
| 40 | |||
| 41 | LIST is a list of objects, or a function of no arguments to return the next | ||
| 42 | object or nil. | ||
| 43 | |||
| 44 | PROMPTER is a function of one arg (an object from LIST), | ||
| 45 | which returns a string to be used as the prompt for that object. | ||
| 46 | If the return value is not a string, it is eval'd to get the answer. | ||
| 47 | So, it may be nil to ignore the object, t to act on the object without | ||
| 48 | asking the user, or a form to do a more complex prompt. | ||
| 49 | PROMPTER may instead be a string, in which case the prompt is | ||
| 50 | \(format PROMPTER OBJECT\). | ||
| 51 | |||
| 52 | ACTOR is a function of one arg (an object from LIST), | ||
| 53 | which gets called with each object that the user answers `yes' for. | ||
| 54 | |||
| 55 | If HELP is given, it is a list (OBJECT OBJECTS ACTION), | ||
| 56 | where OBJECT is a string giving the singular noun for an elt of LIST; | ||
| 57 | OBJECTS is the plural noun for elts of LIST, and ACTION is a transitive | ||
| 58 | verb describing ACTOR. The default is \(\"object\" \"objects\" \"act on\"\). | ||
| 59 | |||
| 60 | At the prompts, the user may enter y, Y, or SPC to act on that object; | ||
| 61 | n, N, or DEL to skip that object; ! to act on all following objects; | ||
| 62 | ESC or q to exit (skip all following objects); . (period) to act on the | ||
| 63 | current object and then exit; or \\[help-command] to get help. | ||
| 64 | |||
| 65 | Returns the number of actions taken." | ||
| 66 | (let ((old-help-form help-form) | ||
| 67 | (help-form (cons 'map-y-or-n-p-help | ||
| 68 | (or help '("object" "objects" "act on")))) | ||
| 69 | (actions 0) | ||
| 70 | prompt | ||
| 71 | char | ||
| 72 | (next (if (or (symbolp list) | ||
| 73 | (subrp list) | ||
| 74 | (compiled-function-p list) | ||
| 75 | (and (consp list) | ||
| 76 | (eq (car list) 'lambda))) | ||
| 77 | list | ||
| 78 | (function (lambda () | ||
| 79 | (if list | ||
| 80 | (prog1 | ||
| 81 | (car list) | ||
| 82 | (setq list (cdr list))) | ||
| 83 | nil))))) | ||
| 84 | elt) | ||
| 85 | (if (stringp prompter) | ||
| 86 | (setq prompter (` (lambda (object) | ||
| 87 | (format (, prompter) object))))) | ||
| 88 | (while (setq elt (funcall next)) | ||
| 89 | (setq prompt (funcall prompter elt)) | ||
| 90 | (if (stringp prompt) | ||
| 91 | (progn | ||
| 92 | ;; Prompt the user about this object. | ||
| 93 | (let ((cursor-in-echo-area t)) | ||
| 94 | (message "%s(y, n, ! ., q, or %s)" | ||
| 95 | prompt (key-description (char-to-string help-char))) | ||
| 96 | (setq char (read-char))) | ||
| 97 | (cond ((or (= ?q char) | ||
| 98 | (= ?\e char)) | ||
| 99 | (setq next (function (lambda () nil)))) | ||
| 100 | ((or (= ?y char) | ||
| 101 | (= ?Y char) | ||
| 102 | (= ? char)) | ||
| 103 | ;; Act on the object. | ||
| 104 | (let ((help-form old-help-form)) | ||
| 105 | (funcall actor elt)) | ||
| 106 | (setq actions (1+ actions))) | ||
| 107 | ((or (= ?n char) | ||
| 108 | (= ?N char) | ||
| 109 | (= ?\^? char)) | ||
| 110 | ;; Skip the object. | ||
| 111 | ) | ||
| 112 | ((= ?. char) | ||
| 113 | ;; Act on the object and then exit. | ||
| 114 | (funcall actor elt) | ||
| 115 | (setq actions (1+ actions) | ||
| 116 | next (function (lambda () nil)))) | ||
| 117 | ((= ?! char) | ||
| 118 | ;; Act on all following objects. | ||
| 119 | (while (setq elt (funcall next)) | ||
| 120 | (if (funcall prompter elt) | ||
| 121 | (progn | ||
| 122 | (funcall actor elt) | ||
| 123 | (setq actions (1+ actions))))) | ||
| 124 | ((= ?? char) | ||
| 125 | (setq unread-command-char help-char) | ||
| 126 | (setq next (` (function (lambda () | ||
| 127 | (setq next (, next)) | ||
| 128 | t))))) | ||
| 129 | (t | ||
| 130 | ;; Random char. | ||
| 131 | (message "Type %s for help." | ||
| 132 | (key-description (char-to-string help-char))) | ||
| 133 | (beep) | ||
| 134 | (sit-for 1) | ||
| 135 | (setq next (` (function (lambda () | ||
| 136 | (setq next (, next)) | ||
| 137 | t)))))))) | ||
| 138 | (if (eval prompt) | ||
| 139 | (progn | ||
| 140 | (funcall actor (car list)) | ||
| 141 | (setq actions (1+ actions))))) | ||
| 142 | (setq list (cdr list))) | ||
| 143 | ;; Clear the last prompt from the minibuffer. | ||
| 144 | (message "") | ||
| 145 | ;; Return the number of actions that were taken. | ||
| 146 | actions)) | ||
| 147 | |||
| 148 | (provide 'map-ynp) | ||