;;; multi-prompt.el --- completing read of multiple strings.
;; Copyright (C) 1996, 1997, 2000 Per Abrahamsen.
;; Author: Per Abrahamsen <firstname.lastname@example.org>
;; Keywords: extensions
;; Version: 0.4
;; Bogus-Bureaucratic-Cruft: How 'bout ESR and the LCD people agreed
;; on a common format?
;; LCD Archive Entry:
;; multi-prompt|Per Abrahamsenemail@example.com|
;; completing read of multiple strings|
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;; This package is written for use in emacs lisp programs, where the
;; user is prompted for a string of the form:
;; where FOO, BAR, and BAZ are elements of some table. The function
;; `multi-prompt' is a replacement `completing-read' that will allow
;; the user to enter a string like the above, yet get completion on
;; both FOO, BAR, and BAZ.
;;; Change Log:
;; Wed Oct 3 14:48:11 EDT 2001 Peter S Galbraith <firstname.lastname@example.org>
;; * Version 0.4 released.
;; multi-prompt-next fixed for emacs-21.
;; Mon Jan 3 16:58:49 MET 2000
;; * Version 0.2 released.
;; Don't allow partial completions when require-match is true.
;; Reported by 'anonymous'.
;; Sat Feb 15 17:58:31 MET 1997
;; * Version 0.2 released.
;; Renamed predicate to `mp-predicate'.
;; Sat Aug 31 18:32:20 MET DST 1996
;; * Version 0.1 released.
;; Fixed `predicate' bug.
;; Added provide.
;; Added `multi-prompt-found' variable.
;; Sat Aug 31 16:29:14 MET DST 1996
;; * Created.
(defvar multi-prompt-found nil
"List of entries currently added during a `multi-prompt'.")
(defun multi-prompt (separator
unique prompt table
&optional mp-predicate require-match initial history)
"Completing prompt for a list of strings.
The first argument SEPARATOR should be the string (of length 1) to
separate the elements in the list. The second argument UNIQUE should
be non-nil, if each element must be unique. The remaining elements
are the arguments to `completing-read'. See that."
(let ((old-map (if require-match
(if (fboundp 'set-keymap-parent)
;; `set-keymap-parent' was introduced in Emacs 19.32.
(set-keymap-parent new-map old-map)
(setq new-map (copy-keymap old-map)))
(define-key new-map separator (if require-match
(define-key new-map "\C-?" 'multi-prompt-delete)
(let* ((minibuffer-local-completion-map new-map)
(filter (cond (unique
(and (not (member (car x) multi-prompt-found))
(or (null mp-predicate)
(funcall mp-predicate x)))))
(answer (catch 'multi-prompt-exit
(let ((extra (catch 'multi-prompt-next
(cond ((eq extra 'back)
(setq prompt (substring
(- 0 (length separator)
initial (car multi-prompt-found))
(setq prompt (concat prompt extra separator)
(cons extra multi-prompt-found)))))))))
(nreverse (cons answer multi-prompt-found))
(defun multi-prompt-delete ()
(throw 'multi-prompt-next 'back)
(defun multi-prompt-next ()
;; buffer-substring no longer works in emacs-21, it returns
;; the whole prompt line. Use this instead.
(buffer-substring-no-properties (point-min) (point-max))))))
(defun multi-prompt-next-must-match ()
(when (call-interactively 'minibuffer-complete)
(let ((content (buffer-substring-no-properties (point-min) (point-max))))
(when (or (not require-match)
(assoc content table))
(throw 'multi-prompt-next content)))))
;;; multi-prompt.el ends here