-(defun read-face-name (prompt)
- "Read and return a face symbol, prompting with PROMPT.
-Value is a symbol naming a known face."
- (let ((face-list (mapcar #'(lambda (x) (cons (symbol-name x) x))
- (face-list)))
- (def (thing-at-point 'symbol))
- face)
- (cond ((assoc def face-list)
- (setq prompt (concat prompt " (default " def "): ")))
- (t (setq def nil)
- (setq prompt (concat prompt ": "))))
- (while (equal "" (setq face (completing-read
- prompt face-list nil t nil nil def))))
- (intern face)))
+(defun read-face-name (prompt &optional string-describing-default multiple)
+ "Read a face, defaulting to the face or faces on the char after point.
+If it has a `read-face-name' property, that overrides the `face' property.
+PROMPT describes what you will do with the face (don't end in a space).
+STRING-DESCRIBING-DEFAULT describes what default you will use
+if this function returns nil.
+If MULTIPLE is non-nil, return a list of faces (possibly only one).
+Otherwise, return a single face."
+ (let ((faceprop (or (get-char-property (point) 'read-face-name)
+ (get-char-property (point) 'face)))
+ (aliasfaces nil)
+ (nonaliasfaces nil)
+ faces)
+ ;; Try to get a face name from the buffer.
+ (if (memq (intern-soft (thing-at-point 'symbol)) (face-list))
+ (setq faces (list (intern-soft (thing-at-point 'symbol)))))
+ ;; Add the named faces that the `face' property uses.
+ (if (and (listp faceprop)
+ ;; Don't treat an attribute spec as a list of faces.
+ (not (keywordp (car faceprop)))
+ (not (memq (car faceprop) '(foreground-color background-color))))
+ (dolist (f faceprop)
+ (if (symbolp f)
+ (push f faces)))
+ (if (symbolp faceprop)
+ (push faceprop faces)))
+ (delete-dups faces)
+
+ ;; Build up the completion tables.
+ (mapatoms (lambda (s)
+ (if (custom-facep s)
+ (if (get s 'face-alias)
+ (push (symbol-name s) aliasfaces)
+ (push (symbol-name s) nonaliasfaces)))))
+
+ ;; If we only want one, and the default is more than one,
+ ;; discard the unwanted ones now.
+ (unless multiple
+ (if faces
+ (setq faces (list (car faces)))))
+ (require 'crm)
+ (let* ((input
+ ;; Read the input.
+ (completing-read-multiple
+ (if (or faces string-describing-default)
+ (format "%s (default %s): " prompt
+ (if faces (mapconcat 'symbol-name faces ",")
+ string-describing-default))
+ (format "%s: " prompt))
+ (complete-in-turn nonaliasfaces aliasfaces)
+ nil t nil nil
+ (if faces (mapconcat 'symbol-name faces ","))))
+ ;; Canonicalize the output.
+ (output
+ (cond ((or (equal input "") (equal input '("")))
+ faces)
+ ((stringp input)
+ (mapcar 'intern (split-string input ", *" t)))
+ ((listp input)
+ (mapcar 'intern input))
+ (input))))
+ ;; Return either a list of faces or just one face.
+ (if multiple
+ output
+ (car output)))))