1 ;;; map-ynp.el -- General-purpose boolean question-asker.
2 ;;; Copyright (C) 1991 Free Software Foundation, Inc.
3 ;;; Written by Roland McGrath.
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)
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.
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
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.
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;
33 or . (period) to %s the current %s and exit."
34 action object object action objects action object
))
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.
41 LIST is a list of objects, or a function of no arguments to return the next
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\).
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.
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\"\).
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.
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"))))
73 (next (if (or (symbolp list
)
75 (compiled-function-p list
)
77 (eq (car list
) 'lambda
)))
79 (setq elt
(funcall list
))))
87 (if (stringp prompter
)
88 (setq prompter
(` (lambda (object)
89 (format (, prompter
) object
)))))
91 (setq prompt
(funcall prompter elt
))
94 ;; Prompt the user about this object.
95 (let ((cursor-in-echo-area t
))
96 (message "%s(y, n, ! ., q, or %s)"
97 prompt
(key-description (char-to-string help-char
)))
98 (setq char
(read-char)))
99 (cond ((or (= ?q char
)
101 (setq next
(function (lambda () nil
))))
105 ;; Act on the object.
106 (let ((help-form old-help-form
))
108 (setq actions
(1+ actions
)))
115 ;; Act on the object and then exit.
117 (setq actions
(1+ actions
)
118 next
(function (lambda () nil
))))
120 ;; Act on this and all following objects.
121 (if (eval (funcall prompter elt
))
124 (setq actions
(1+ actions
))))
125 (while (setq elt
(funcall next
))
126 (if (eval (funcall prompter elt
))
129 (setq actions
(1+ actions
))))))
131 (setq unread-command-char help-char
)
132 (setq next
(` (lambda ()
133 (setq next
'(, next
))
137 (message "Type %s for help."
138 (key-description (char-to-string help-char
)))
141 (setq next
(` (lambda ()
142 (setq next
'(, next
))
147 (setq actions
(1+ actions
))))))
148 ;; Clear the last prompt from the minibuffer.
150 ;; Return the number of actions that were taken.