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