Mercurial > hg > xemacs-beta
changeset 4178:e687f1912d5b
[xemacs-hg @ 2007-09-20 21:18:33 by didierv]
User options interactive prompting improvements
author | didierv |
---|---|
date | Thu, 20 Sep 2007 21:18:35 +0000 |
parents | d080fe09a356 |
children | 8284a525f1b4 |
files | lisp/ChangeLog lisp/cus-edit.el lisp/wid-edit.el |
diffstat | 3 files changed, 282 insertions(+), 163 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Wed Sep 19 21:50:57 2007 +0000 +++ b/lisp/ChangeLog Thu Sep 20 21:18:35 2007 +0000 @@ -1,3 +1,36 @@ +2007-09-20 Didier Verna <didier@xemacs.org> + + Improvements in user options interactive prompting. This mainly + involves the following: before this patch, options of type 'group + or 'checklist were prompted by full sexp, without taking a + possible default value into account. Now, the user interaction + features individual prompting _with completion_ for each group or + checklist member. For group options, an optional default value is + also handled on an individual group member basis. + + * cus-edit.el (customize-set-value): Suppress the final ": " from + created prompts. + (customize-set-variable): Ditto. + (customize-save-variable): Ditto. + (custom-prompt-variable): Add final ": " to prompts if needed. + + * wid-edit.el (widget-prompt-spaceify): New. Add trailing space to + string if needed. + (widget-prompt): New. Construct a prompt for a widget. + (widget-prompt-value): Use it; make prompt argument optional. + (widget-default-prompt-value): Add final ": " to prompt. + (widget-field-prompt-internal): Ditto. + (widget-sexp-prompt-value): Ditto. + (widget-file-prompt-value): Ditto. + (widget-symbol-prompt-internal): Ditto. + (widget-choice-prompt-value): Ditto. + (widget-boolean-prompt-value): Ditto. + (widget-checklist-prompt-value): New. Prompt value with completion. + (checklist): Make the widget aware of it. + (widget-group-prompt-value): New. Prompt value with completion; + handle default value individually for each group member. + * wid-edit.el (group): Make the widget aware of it. + 2007-09-19 Didier Verna <didier@xemacs.org> Update my personal info.
--- a/lisp/cus-edit.el Wed Sep 19 21:50:57 2007 +0000 +++ b/lisp/cus-edit.el Thu Sep 20 21:18:35 2007 +0000 @@ -1,10 +1,11 @@ ;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages. ;; +;; Copyright (C) 2007 Didier Verna +;; Copyright (C) 2003 Ben Wing ;; Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. -;; Copyright (C) 2003 Ben Wing. ;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> -;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> +;; Maintainer: Didier Verna <didier@xemacs.org> ;; Keywords: help, faces ;; Version: 1.9960-x ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ @@ -306,7 +307,7 @@ (and (boundp symbol) (or (get symbol 'custom-type) (user-variable-p symbol)))) - t nil nil (and v (symbol-name v)))) + t nil nil (and v (symbol-name v)))) (list (if (equal val "") (if (symbolp v) v nil) (intern val))))) @@ -651,8 +652,8 @@ (defun custom-prompt-variable (prompt-var prompt-val &optional comment) "Prompt for a variable and a value and return them as a list. PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the -prompt for the value. The %s escape in PROMPT-VAL is replaced with -the name of the variable. +prompt for the value. A %s escape in PROMPT-VAL is replaced with +the name of the variable. A final colon is appended to both prompts. If the variable has a `variable-interactive' property, that is used as if it were the arg to `interactive' (which see) to interactively read the value. @@ -662,7 +663,7 @@ If optional COMMENT argument is non nil, also prompt for a comment and return it as the third element in the list." - (let* ((var (read-variable prompt-var)) + (let* ((var (read-variable (concat prompt-var ": "))) (minibuffer-help-form '(describe-variable var)) (val (let ((prop (get var 'variable-interactive)) @@ -683,12 +684,11 @@ (symbol-value var)) (not (boundp var)))) (t - (eval-minibuffer prompt)))))) + (eval-minibuffer (concat prompt ": "))))))) (if comment (list var val (read-string "Comment: " (get var 'variable-comment))) - (list var val)) - )) + (list var val)))) ;;;###autoload (defun customize-set-value (var val &optional comment) @@ -701,8 +701,8 @@ `:prompt-value' property of that widget will be used for reading the value. If given a prefix (or a COMMENT argument), also prompt for a comment." - (interactive (custom-prompt-variable "Set variable: " - "Set %s to value: " + (interactive (custom-prompt-variable "Set variable" + "Set value of %s" current-prefix-arg)) (set var val) @@ -728,8 +728,8 @@ `:prompt-value' property of that widget will be used for reading the value. If given a prefix (or a COMMENT argument), also prompt for a comment." - (interactive (custom-prompt-variable "Set variable: " - "Set customized value for %s to: " + (interactive (custom-prompt-variable "Set variable" + "Set customized value of %s" current-prefix-arg)) (funcall (or (get variable 'custom-set) 'set-default) variable value) (put variable 'customized-value (list (custom-quote value))) @@ -757,8 +757,8 @@ `:prompt-value' property of that widget will be used for reading the value. If given a prefix (or a COMMENT argument), also prompt for a comment." - (interactive (custom-prompt-variable "Set and save variable: " - "Set and save value for %s as: " + (interactive (custom-prompt-variable "Set and save variable" + "Set and save value of %s" current-prefix-arg)) (funcall (or (get variable 'custom-set) 'set-default) variable value) (put variable 'saved-value (list (custom-quote value))) @@ -1770,7 +1770,7 @@ (return-from custom-load nil))) #'(lambda () (load (expand-file-name "custom-defines" dir)))))) - ;; we get here only from the `return-from'; see above + ;; we get here only from the `return-from'; see above (load source)))) (defun custom-load-widget (widget) @@ -2545,7 +2545,7 @@ :sample-face 'custom-face-tag-face :help-echo "Set or reset this face" :documentation-property #'(lambda (face) - (face-doc-string face)) + (face-doc-string face)) :value-create 'custom-face-value-create :action 'custom-face-action :custom-category 'face @@ -3496,40 +3496,40 @@ (goto-char (point-min)) (condition-case nil (while (not (eobp)) - (let ((sexp (read (current-buffer)))) - (when (and (listp sexp) - (memq (car sexp) symbols)) - (delete-region (save-excursion - (backward-sexp) - (point)) - (point)) - (while (and (eolp) (not (eobp))) - (delete-region (point) (prog2 (forward-line 1) (point)))) - ))) + (let ((sexp (read (current-buffer)))) + (when (and (listp sexp) + (memq (car sexp) symbols)) + (delete-region (save-excursion + (backward-sexp) + (point)) + (point)) + (while (and (eolp) (not (eobp))) + (delete-region (point) (prog2 (forward-line 1) (point)))) + ))) (end-of-file nil))) (defsubst custom-save-variable-p (symbol) "Return non-nil if symbol SYMBOL is a customized variable." (and (symbolp symbol) (let ((spec (car-safe (get symbol 'theme-value)))) - (or (and spec (eq (car spec) 'user) - (eq (second spec) 'set)) - (get symbol 'saved-variable-comment) - ;; support non-themed vars - (and (null spec) (get symbol 'saved-value)))))) + (or (and spec (eq (car spec) 'user) + (eq (second spec) 'set)) + (get symbol 'saved-variable-comment) + ;; support non-themed vars + (and (null spec) (get symbol 'saved-value)))))) (defun custom-save-variable-internal (symbol) "Print variable SYMBOL to the standard output. SYMBOL must be a customized variable." (let ((requests (get symbol 'custom-requests)) - (now (not (or (get symbol 'standard-value) - (and (not (boundp symbol)) - (not (eq (get symbol 'force-value) - 'rogue)))))) - (comment (get symbol 'saved-variable-comment)) - ;; Print everything, no placeholders `...' - (print-level nil) - (print-length nil)) + (now (not (or (get symbol 'standard-value) + (and (not (boundp symbol)) + (not (eq (get symbol 'force-value) + 'rogue)))))) + (comment (get symbol 'saved-variable-comment)) + ;; Print everything, no placeholders `...' + (print-level nil) + (print-length nil)) (unless (custom-save-variable-p symbol) (error 'wrong-type-argument "Not a customized variable" symbol)) (princ "\n '(") @@ -3540,10 +3540,10 @@ ;; (prin1 (third spec)) ;; XEmacs -- pretty-print value if available (if (and custom-save-pretty-print - (fboundp 'pp)) - ;; To suppress bytecompiler warning - (with-fboundp 'pp - (pp (car (get symbol 'saved-value)))) + (fboundp 'pp)) + ;; To suppress bytecompiler warning + (with-fboundp 'pp + (pp (car (get symbol 'saved-value)))) (prin1 (car (get symbol 'saved-value)))) (when (or now requests comment) (princ (if now " t" " nil"))) @@ -3570,21 +3570,21 @@ (custom-save-loaded-themes) (custom-save-resets 'theme-value 'custom-reset-variables nil) (let ((standard-output (current-buffer)) - (sorted-list ())) + (sorted-list ())) ;; First create a sorted list of saved variables. (mapatoms - (lambda (symbol) - (when (custom-save-variable-p symbol) - (push symbol sorted-list)))) + (lambda (symbol) + (when (custom-save-variable-p symbol) + (push symbol sorted-list)))) (setq sorted-list (sort sorted-list 'string<)) (unless (bolp) - (princ "\n")) + (princ "\n")) (princ "(custom-set-variables") (mapc 'custom-save-variable-internal - sorted-list) + sorted-list) (princ ")") (unless (looking-at "\n") - (princ "\n"))))) + (princ "\n"))))) (defvar custom-save-face-ignoring nil) @@ -3593,14 +3593,14 @@ (let ((theme-spec (car-safe (get symbol 'theme-face))) (comment (get symbol 'saved-face-comment))) (or (and (not (memq symbol custom-save-face-ignoring)) - ;; Don't print default face here. - (or (and theme-spec - (eq (car theme-spec) 'user) - (eq (second theme-spec) 'set)) - ;; cope with non-themed faces - (and (null theme-spec) - (get symbol 'saved-face)))) - comment))) + ;; Don't print default face here. + (or (and theme-spec + (eq (car theme-spec) 'user) + (eq (second theme-spec) 'set)) + ;; cope with non-themed faces + (and (null theme-spec) + (get symbol 'saved-face)))) + comment))) (defun custom-save-face-internal (symbol) "Print face SYMBOL to the standard output. @@ -3609,24 +3609,24 @@ (now (not (or (get symbol 'face-defface-spec) (and (not (find-face symbol)) (not (eq (get symbol 'force-face) 'rogue)))))) - ;; Print everything, no placeholders `...' - (print-level nil) - (print-length nil)) + ;; Print everything, no placeholders `...' + (print-level nil) + (print-length nil)) (if (memq symbol custom-save-face-ignoring) - ;; Do nothing - nil + ;; Do nothing + nil ;; Print face (unless (custom-save-face-p symbol) - (error 'wrong-type-argument "Not a customized face" symbol)) + (error 'wrong-type-argument "Not a customized face" symbol)) (princ "\n '(") (prin1 symbol) (princ " ") (prin1 (get symbol 'saved-face)) (if (or comment now) - (princ (if now " t" " nil"))) + (princ (if now " t" " nil"))) (when comment - (princ " ") - (prin1 comment)) + (princ " ") + (prin1 comment)) (princ ")")))) (defun custom-save-faces () @@ -3641,22 +3641,22 @@ ;; 'custom-set-faces) (custom-save-resets 'theme-face 'custom-reset-faces '(default)) (let ((standard-output (current-buffer)) - (sorted-list ())) + (sorted-list ())) ;; Create a sorted list of faces (mapatoms (lambda (symbol) - (when (custom-save-face-p symbol) - (push symbol sorted-list)))) + (when (custom-save-face-p symbol) + (push symbol sorted-list)))) (setq sorted-list (sort sorted-list 'string<)) (unless (bolp) (princ "\n")) (princ "(custom-set-faces") ;; The default face must be first, since it affects the others. (when (custom-save-face-p 'default) - (custom-save-face-internal 'default)) + (custom-save-face-internal 'default)) (let ((custom-save-face-ignoring '(default))) (mapc 'custom-save-face-internal - sorted-list)) + sorted-list)) (princ ")") (unless (looking-at "\n") (princ "\n"))))) @@ -3665,35 +3665,35 @@ "Create a mapper for `custom-save-resets'." `(lambda (object) (let ((spec (car-safe (get object (quote ,property)))) - (print-level nil) - (print-length nil)) + (print-level nil) + (print-length nil)) (with-boundp '(ignored-special started-writing) - (when (and (not (memq object ignored-special)) - (eq (car spec) 'user) - (eq (second spec) 'reset)) - ;; Do not write reset statements unless necessary. - (unless started-writing - (setq started-writing t) - (unless (bolp) - (princ "\n")) - (princ "(") - (princ (quote ,setter)) - (princ "\n '(") - (prin1 object) - (princ " ") - (prin1 (third spec)) - (princ ")"))))))) + (when (and (not (memq object ignored-special)) + (eq (car spec) 'user) + (eq (second spec) 'reset)) + ;; Do not write reset statements unless necessary. + (unless started-writing + (setq started-writing t) + (unless (bolp) + (princ "\n")) + (princ "(") + (princ (quote ,setter)) + (princ "\n '(") + (prin1 object) + (princ " ") + (prin1 (third spec)) + (princ ")"))))))) (defconst custom-save-resets-mapper-alist (eval-when-compile (list (list 'theme-value 'custom-reset-variables - (byte-compile - (make-custom-save-resets-mapper - 'theme-value 'custom-reset-variables))) - (list 'theme-face 'custom-reset-faces - (byte-compile - (make-custom-save-resets-mapper - 'theme-face 'custom-reset-faces))))) + (byte-compile + (make-custom-save-resets-mapper + 'theme-value 'custom-reset-variables))) + (list 'theme-face 'custom-reset-faces + (byte-compile + (make-custom-save-resets-mapper + 'theme-face 'custom-reset-faces))))) "Never use it. Hashes several heavily used functions for `custom-save-resets'") @@ -3703,9 +3703,9 @@ ;; (custom-save-delete setter) Done by caller (let ((standard-output (current-buffer)) (mapper (let ((triple (assq property custom-save-resets-mapper-alist))) - (if (and triple (eq (second triple) setter)) - (third triple) - (make-custom-save-resets-mapper property setter))))) + (if (and triple (eq (second triple) setter)) + (third triple) + (make-custom-save-resets-mapper property setter))))) (mapc mapper special) (setq ignored-special special) (mapatoms mapper) @@ -3716,8 +3716,8 @@ (defun custom-save-loaded-themes () (let ((themes (reverse (get 'user 'theme-loads-themes))) (standard-output (current-buffer)) - (print-level nil) - (print-length nil)) + (print-level nil) + (print-length nil)) (when themes (unless (bolp) (princ "\n")) (princ "(custom-load-themes") @@ -3910,7 +3910,7 @@ Invoke button under point. \\[widget-button-press] Set all modifications. \\[Custom-set] Make all modifications default. \\[Custom-save] -Reset all modified options. \\[Custom-reset-current] +Reset all modified options. \\[Custom-reset-current] Reset all modified or set options. \\[Custom-reset-saved] Reset all options. \\[Custom-reset-standard]
--- a/lisp/wid-edit.el Wed Sep 19 21:50:57 2007 +0000 +++ b/lisp/wid-edit.el Thu Sep 20 21:18:35 2007 +0000 @@ -1,9 +1,10 @@ ;;; wid-edit.el --- Functions for creating and using widgets. ;; +;; Copyright (C) 2007 Didier Verna ;; Copyright (C) 1996-1997, 1999-2002 Free Software Foundation, Inc. ;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> -;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> +;; Maintainer: Didier Verna <didier@xemacs.org> ;; Keywords: extensions ;; Version: 1.9960-x ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ @@ -330,7 +331,7 @@ (mouse-set-point event) (let ((pos (event-point event))) (if (and pos (get-char-property pos 'button)) - (widget-button-click event)))) + (widget-button-click event)))) ;;; Widget text specifications. ;; @@ -591,15 +592,15 @@ (defun widget-specify-active (widget) "Make WIDGET active for user modifications." (let ((inactive (widget-get widget :inactive)) - (from (widget-get widget :from)) - (to (widget-get widget :to))) + (from (widget-get widget :from)) + (to (widget-get widget :to))) (when (and inactive (not (extent-detached-p inactive))) ;; Reactivate the buttons and fields covered by the extent. (map-extents 'widget-activation-widget-mapper - nil from to :activate nil 'button-or-field) + nil from to :activate nil 'button-or-field) ;; Reactivate the glyphs. (map-extents 'widget-activation-glyph-mapper - nil from to :activate nil 'end-glyph) + nil from to :activate nil 'end-glyph) (delete-extent inactive) (widget-put widget :inactive nil)))) @@ -706,15 +707,44 @@ ;; ;; These are widget specific. +;; #### Note: this should probably be a more general utility -- dvl +(defsubst widget-prompt-spaceify (prompt) + ;; Add a space at the end of PROMPT if needed + (if (or (string= prompt "") (eq ? (aref prompt (1- (length prompt))))) + prompt + (concat prompt " "))) + +(defsubst widget-prompt (widget &optional prompt default-prompt) + ;; Construct a prompt for WIDGET. + ;; - If PROMPT is given, use it. + ;; - Otherwise, use the :tag property, if any. + ;; - Otherwise, use DEFAULT-PROMPT, if given. + ;; - Otherise, use "Value". + ;; - If the result is not the empty string, add a space for later addition + ;; of the widget type by `widget-prompt-value'. + (unless prompt + (setq prompt (or (and (widget-get widget :tag) + (replace-in-string (widget-get widget :tag) + "^[ \t]+" "" t)) + default-prompt + "Value"))) + (widget-prompt-spaceify prompt)) + + ;;;###autoload -(defun widget-prompt-value (widget prompt &optional value unbound) - "Prompt for a value matching WIDGET, using PROMPT. +(defun widget-prompt-value (widget &optional prompt value unbound) + "Prompt for a value matching WIDGET. +Prompt with PROMPT, or WIDGET's :tag otherwise. The current value is assumed to be VALUE, unless UNBOUND is non-nil." (unless (listp widget) (setq widget (list widget))) - (setq prompt (format "[%s] %s" (widget-type widget) prompt)) (setq widget (widget-convert widget)) - (let ((answer (widget-apply widget :prompt-value prompt value unbound))) + (let ((answer (widget-apply widget + :prompt-value + (format "%s[%s]" + (widget-prompt widget prompt) + (widget-type widget)) + value unbound))) (while (not (widget-apply widget :match answer)) (setq answer (signal 'error (list "Answer does not match type" answer (widget-type widget))))) @@ -1783,11 +1813,11 @@ (lambda () ;?\] (setq button-end (point-marker)) (set-marker-insertion-type button-end nil)) - (lambda () ;?\{ + (lambda () ;?\{ (setq sample-begin (point))) (lambda () ;?\} (setq sample-end (point))) - (lambda () ;?n + (lambda () ;?n (when (widget-get widget :indent) (insert ?\n) (insert-char ?\ (widget-get widget :indent)))) @@ -2001,7 +2031,7 @@ ;; It would be nice if we could do a `(cons val 1)' here. ;; (prin1-to-string (custom-quote value)))))) ;; XEmacs: make this use default VALUE. Need to check callers. - (eval-minibuffer prompt)) + (eval-minibuffer (concat prompt ": "))) ;;; The `item' Widget. @@ -2224,7 +2254,7 @@ "Read string for WIDGET prompting with PROMPT. INITIAL is the initial input and HISTORY is a symbol containing the earlier input." - (read-string prompt initial history)) + (read-string (concat prompt ": ") initial history)) (defun widget-field-prompt-value (widget prompt value unbound) "Prompt for a string." @@ -2577,6 +2607,7 @@ :value-create 'widget-checklist-value-create :value-delete 'widget-children-value-delete :value-get 'widget-checklist-value-get + :prompt-value 'widget-checklist-prompt-value :validate 'widget-checklist-validate :match 'widget-checklist-match :match-inline 'widget-checklist-match-inline) @@ -2701,6 +2732,27 @@ (setq result (append result (widget-apply child :value-inline))))) result)) +;; #### FIXME: should handle default value some day -- dvl +(defun widget-checklist-prompt-value (widget prompt value unbound) + ;; Prompt for items to be selected, and the prompt for their value + (let* ((args (widget-get widget :args)) + (choices (mapcar (lambda (elt) + (cons (widget-get elt :tag) elt)) + args)) + (continue t) + value) + (while continue + (setq continue (completing-read + (concat (widget-prompt-spaceify prompt) + "select [ret. when done]: ") + choices nil t)) + (if (string= continue "") + (setq continue nil) + (push (widget-prompt-value (cdr (assoc continue choices)) + prompt nil t) + value))) + (nreverse value))) + (defun widget-checklist-validate (widget) ;; Ticked children must be valid. (let ((children (widget-get widget :children)) @@ -3116,6 +3168,7 @@ :value-delete 'widget-children-value-delete :value-get 'widget-editable-list-value-get :default-get 'widget-group-default-get + :prompt-value 'widget-group-prompt-value :validate 'widget-children-validate :match 'widget-group-match :match-inline 'widget-group-match-inline) @@ -3146,6 +3199,36 @@ ;; Get the default of the components. (mapcar 'widget-default-get (widget-get widget :args))) +(defun widget-group-prompt-value (widget prompt value unbound) + ;; Prompt in turn for every component of the group. + (let ((args (widget-get widget :args))) + (widget-apply + widget :value-to-external + (if unbound + (mapcar #'(lambda (arg) + (widget-prompt-value + arg + (concat (widget-prompt-spaceify prompt) + (widget-prompt arg nil "")) + nil t)) + args) + ;; If VALUE is bound, the situation is a bit more complex because we + ;; have to split it into a list of default values for every child. Oh, + ;; boy, do I miss 'cl here... -- dvl + (let ((children args) + (defaults (widget-apply widget + :value-to-internal value)) + child default result) + (while (setq child (pop children)) + (setq default (pop defaults)) + (push + (widget-prompt-value + child + (concat (widget-prompt-spaceify prompt) + (widget-prompt child nil "")) + default) result)) + (nreverse result)))))) + (defun widget-group-match (widget values) ;; Match if the components match. (and (listp values) @@ -3378,7 +3461,7 @@ (defun widget-sexp-prompt-value (widget prompt value unbound) ;; Read an arbitrary sexp. - (let ((found (read-string prompt + (let ((found (read-string (concat prompt ": ") (if unbound nil (cons (prin1-to-string value) 0)) (widget-get widget :prompt-history)))) (save-excursion @@ -3502,8 +3585,8 @@ ;; Read file from minibuffer. (abbreviate-file-name (if unbound - (read-file-name prompt) - (let ((prompt2 (format "%s (default %s) " prompt value)) + (read-file-name (concat prompt ": ")) + (let ((prompt2 (format "%s: (default %s) " prompt value)) (dir (file-name-directory value)) (file (file-name-nondirectory value)) (must-match (widget-get widget :must-match))) @@ -3552,7 +3635,7 @@ (defun widget-symbol-prompt-internal (widget prompt initial history) ;; Read file from minibuffer. - (let ((answer (completing-read prompt obarray + (let ((answer (completing-read (concat prompt ": ") obarray (widget-get widget :prompt-match) nil initial history))) (if (and (stringp answer) @@ -3824,42 +3907,45 @@ (let ((args (widget-get widget :args)) (completion-ignore-case (widget-get widget :case-fold)) current choices old) - ;; Find the first arg that matches VALUE. - (let ((look args)) - (while look - (if (widget-apply (car look) :match value) - (setq old (car look) - look nil) - (setq look (cdr look))))) - ;; Find new choice. + ;; Find the first choice matching VALUE (if given): + (unless unbound + (let ((look args)) + (while look + (if (widget-apply (car look) :match value) + (setq old (car look) + look nil) + (setq look (cdr look))))) + ;; If VALUE is invalid (it doesn't match any choice), discard it by + ;; considering it unbound: + (unless old + (setq unbound t))) + ;; Now offer the choice, providing the given default value when/where + ;; appropriate: + (while args + (setq current (car args) + args (cdr args)) + (setq choices + (cons (cons (widget-apply current :menu-tag-get) + current) + choices))) (setq current - (cond ((= (length args) 0) - nil) - ((= (length args) 1) - (nth 0 args)) - ((and (= (length args) 2) - (memq old args)) - (if (eq old (nth 0 args)) - (nth 1 args) - (nth 0 args))) - (t - (while args - (setq current (car args) - args (cdr args)) - (setq choices - (cons (cons (widget-apply current :menu-tag-get) - current) - choices))) - (let ((val (completing-read prompt choices nil t))) - (if (stringp val) - (let ((try (try-completion val choices))) - (when (stringp try) - (setq val try)) - (cdr (assoc val choices))) - nil))))) + (let ((val (completing-read (concat prompt ": ") choices nil t + (when old + (widget-apply old :menu-tag-get))))) + (if (stringp val) ;; #### is this really needed ? --dvl + (let ((try (try-completion val choices))) + (when (stringp try) ;; #### and this ? --dvl + (setq val try)) + (cdr (assoc val choices))) + nil))) (if current - (widget-prompt-value current prompt nil t) - value))) + (widget-prompt-value current + (concat (widget-prompt-spaceify prompt) + (widget-get current :tag)) + (unless unbound + (when (eq current old) value)) + (or unbound (not (eq current old)))) + (and (not unbound) value)))) (define-widget 'radio 'radio-button-choice "A set widget, selecting exactly one from many. @@ -3891,7 +3977,7 @@ (defun widget-boolean-prompt-value (widget prompt value unbound) ;; Toggle a boolean. - (y-or-n-p prompt)) + (y-or-n-p (concat prompt ": "))) ;;; The `color' Widget. @@ -4002,8 +4088,8 @@ nil, or a cons-cell containing a sexp and my-lisp. This will not work because the `choice' widget does not allow recursion. -Using the `lazy' widget you can overcome this problem, as in this -example: +Using the `lazy' widget you can overcome this problem, as in this +example: (define-widget 'sexp-list 'lazy \"A list of sexps.\" @@ -4012,7 +4098,7 @@ :format "%{%t%}: %v" ;; We don't convert :type because we want to allow recursive ;; datastructures. This is slow, so we should not create speed - ;; critical widgets by deriving from this. + ;; critical widgets by deriving from this. :convert-widget 'widget-value-convert-widget :value-create 'widget-type-value-create :value-delete 'widget-children-value-delete @@ -4041,10 +4127,10 @@ The value of the :type attribute should be an unconverted widget type." (let ((value (widget-get widget :value)) (type (widget-get widget :type))) - (widget-put widget :children - (list (widget-create-child-value widget - (widget-convert type) - value))))) + (widget-put widget :children + (list (widget-create-child-value widget + (widget-convert type) + value))))) (defun widget-type-default-get (widget) "Get default value from the :type attribute of WIDGET.