summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog17
-rw-r--r--lisp/cus-edit.el3
-rw-r--r--lisp/wid-edit.el110
3 files changed, 113 insertions, 17 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index da52c2aa190..a2e7f95747c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -76,6 +76,23 @@
* info.el (Info-unescape-quotes, Info-split-parameter-string)
(Info-goto-emacs-command-node): Doc fixes.
+2003-12-12 Jesper Harder <harder@ifa.au.dk>
+
+ * cus-edit.el (custom-add-parent-links): Define "many".
+
+2003-12-08 Per Abrahamsen <abraham@dina.kvl.dk>
+
+ * wid-edit.el (widget-child-value-get, widget-child-value-inline)
+ (widget-child-validate, widget-type-value-create)
+ (widget-type-default-get, widget-type-match): New functions.
+ (lazy): New widget.
+ (menu-choice, checklist, radio-button-choice, editable-list)
+ (group, documentation-string): Removed redundant (per 2003-10-25
+ change) calls to `widget-children-value-delete'.
+ (widget-choice-value-get, widget-choice-value-inline): Removed
+ functions.
+ (menu-choice): Updated widget.
+
2003-12-03 Kenichi Handa <handa@m17n.org>
* language/cyrillic.el: Register "microsoft-cp1251" in
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index bf92e8df9cf..fc5e7ecb8af 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -1970,7 +1970,8 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
(setq parents (cons symbol parents))))))
(and (null (get symbol 'custom-links)) ;No links of its own.
(= (length parents) 1) ;A single parent.
- (let ((links (get (car parents) 'custom-links)))
+ (let* ((links (get (car parents) 'custom-links))
+ (many (> (length links) 2)))
(when links
(insert "\nParent documentation: ")
(while links
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 4c70334e908..63a254d1d67 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -1267,6 +1267,42 @@ Optional EVENT is the event that triggered the action."
found (widget-apply child :validate)))
found))
+(defun widget-child-value-get (widget)
+ "Get the value of the first member of :children in WIDGET."
+ (widget-value (car (widget-get widget :children))))
+
+(defun widget-child-value-inline (widget)
+ "Get the inline value of the first member of :children in WIDGET."
+ (widget-apply (car (widget-get widget :children)) :value-inline))
+
+(defun widget-child-validate (widget)
+ "The result of validating the first member of :children in WIDGET."
+ (widget-apply (car (widget-get widget :children)) :validate))
+
+(defun widget-type-value-create (widget)
+ "Convert and instantiate the value of the :type attribute of WIDGET.
+Store the newly created widget in the :children attribute.
+
+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)))))
+
+(defun widget-type-default-get (widget)
+ "Get default value from the :type attribute of WIDGET.
+
+The value of the :type attribute should be an unconverted widget type."
+ (widget-default-get (widget-convert (widget-get widget :type))))
+
+(defun widget-type-match (widget value)
+ "Non-nil if the :type value of WIDGET matches VALUE.
+
+The value of the :type attribute should be an unconverted widget type."
+ (widget-apply (widget-convert (widget-get widget :type)) :match value))
+
(defun widget-types-copy (widget)
"Copy :args as widget types in WIDGET."
(widget-put widget :args (mapcar 'widget-copy (widget-get widget :args)))
@@ -1862,9 +1898,8 @@ the earlier input."
:tag "choice"
:void '(item :format "invalid (%t)\n")
:value-create 'widget-choice-value-create
- :value-delete 'widget-children-value-delete
- :value-get 'widget-choice-value-get
- :value-inline 'widget-choice-value-inline
+ :value-get 'widget-child-value-get
+ :value-inline 'widget-child-value-inline
:default-get 'widget-choice-default-get
:mouse-down-action 'widget-choice-mouse-down-action
:action 'widget-choice-action
@@ -1901,14 +1936,6 @@ the earlier input."
widget void :value value)))
(widget-put widget :choice void))))))
-(defun widget-choice-value-get (widget)
- ;; Get value of the child widget.
- (widget-value (car (widget-get widget :children))))
-
-(defun widget-choice-value-inline (widget)
- ;; Get value of the child widget.
- (widget-apply (car (widget-get widget :children)) :value-inline))
-
(defun widget-choice-default-get (widget)
;; Get default for the first choice.
(widget-default-get (car (widget-get widget :args))))
@@ -2099,7 +2126,6 @@ when he invoked the menu."
:entry-format "%b %v"
:greedy nil
:value-create 'widget-checklist-value-create
- :value-delete 'widget-children-value-delete
:value-get 'widget-checklist-value-get
:validate 'widget-checklist-validate
:match 'widget-checklist-match
@@ -2276,7 +2302,6 @@ Return an alist of (TYPE MATCH)."
:format "%v"
:entry-format "%b %v"
:value-create 'widget-radio-value-create
- :value-delete 'widget-children-value-delete
:value-get 'widget-radio-value-get
:value-inline 'widget-radio-value-inline
:value-set 'widget-radio-value-set
@@ -2466,7 +2491,6 @@ Return an alist of (TYPE MATCH)."
:format-handler 'widget-editable-list-format-handler
:entry-format "%i %d %v"
:value-create 'widget-editable-list-value-create
- :value-delete 'widget-children-value-delete
:value-get 'widget-editable-list-value-get
:validate 'widget-children-validate
:match 'widget-editable-list-match
@@ -2637,7 +2661,6 @@ Return an alist of (TYPE MATCH)."
:copy 'widget-types-copy
:format "%v"
:value-create 'widget-group-value-create
- :value-delete 'widget-children-value-delete
:value-get 'widget-editable-list-value-get
:default-get 'widget-group-default-get
:validate 'widget-children-validate
@@ -2803,7 +2826,6 @@ link for that string."
"A documentation string."
:format "%v"
:action 'widget-documentation-string-action
- :value-delete 'widget-children-value-delete
:value-create 'widget-documentation-string-value-create)
(defun widget-documentation-string-value-create (widget)
@@ -3250,6 +3272,62 @@ To use this type, you must define :match or :match-alternatives."
(widget-group-match widget
(widget-apply widget :value-to-internal value))))
+;;; The `lazy' Widget.
+;;
+;; Recursive datatypes.
+
+(define-widget 'lazy 'default
+ "Base widget for recursive datastructures.
+
+The `lazy' widget will, when instantiated, contain a single inferior
+widget, of the widget type specified by the :type parameter. The
+value of the `lazy' widget is the same as the value of the inferior
+widget. When deriving a new widget from the 'lazy' widget, the :type
+parameter is allowed to refer to the widget currently being defined,
+thus allowing recursive datastructures to be described.
+
+The :type parameter takes the same arguments as the defcustom
+parameter with the same name.
+
+Most composite widgets, i.e. widgets containing other widgets, does
+not allow recursion. That is, when you define a new widget type, none
+of the inferior widgets may be of the same type you are currently
+defining.
+
+In Lisp, however, it is custom to define datastructures in terms of
+themselves. A list, for example, is defined as either nil, or a cons
+cell whose cdr itself is a list. The obvious way to translate this
+into a widget type would be
+
+ (define-widget 'my-list 'choice
+ \"A list of sexps.\"
+ :tag \"Sexp list\"
+ :args '((const nil) (cons :value (nil) sexp my-list)))
+
+Here we attempt to define my-list as a choice of either the constant
+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:
+
+ (define-widget 'sexp-list 'lazy
+ \"A list of sexps.\"
+ :tag \"Sexp list\"
+ :type '(choice (const nil) (cons :value (nil) sexp sexp-list)))"
+ :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.
+ :convert-widget 'widget-value-convert-widget
+ :value-create 'widget-type-value-create
+ :value-get 'widget-child-value-get
+ :value-inline 'widget-child-value-inline
+ :default-get 'widget-type-default-get
+ :match 'widget-type-match
+ :validate 'widget-child-validate)
+
+
;;; The `plist' Widget.
;;
;; Property lists.