comparison lisp/wid-edit.el @ 18258:e83bc8150072

Synched with 1.9920.
author Per Abrahamsen <abraham@dina.kvl.dk>
date Sun, 15 Jun 1997 15:31:32 +0000
parents 909a0f9169b8
children 325190603227
comparison
equal deleted inserted replaced
18257:34f1f8c5eda3 18258:e83bc8150072
2 ;; 2 ;;
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 ;; 4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6 ;; Keywords: extensions 6 ;; Keywords: extensions
7 ;; Version: 1.9914 7 ;; Version: 1.9920
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
11 11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify 12 ;; GNU Emacs is free software; you can redistribute it and/or modify
123 "http://www.dina.kvl.dk/~abraham/custom/") 123 "http://www.dina.kvl.dk/~abraham/custom/")
124 :prefix "widget-" 124 :prefix "widget-"
125 :group 'extensions 125 :group 'extensions
126 :group 'hypermedia) 126 :group 'hypermedia)
127 127
128 (defgroup widget-documentation nil
129 "Options controling the display of documentation strings."
130 :group 'widgets)
131
128 (defgroup widget-faces nil 132 (defgroup widget-faces nil
129 "Faces used by the widget library." 133 "Faces used by the widget library."
130 :group 'widgets 134 :group 'widgets
131 :group 'faces) 135 :group 'faces)
136
137 (defface widget-documentation-face '((((class color)
138 (background dark))
139 (:foreground "lime green"))
140 (((class color)
141 (background light))
142 (:foreground "dark green"))
143 (t nil))
144 "Face used for documentation text."
145 :group 'widget-documentation
146 :group 'widget-faces)
132 147
133 (defface widget-button-face '((t (:bold t))) 148 (defface widget-button-face '((t (:bold t)))
134 "Face used for widget buttons." 149 "Face used for widget buttons."
135 :group 'widget-faces) 150 :group 'widget-faces)
136 151
255 'front-sticky t 270 'front-sticky t
256 'rear-nonsticky nil 271 'rear-nonsticky nil
257 'start-open nil 272 'start-open nil
258 'end-open nil))) 273 'end-open nil)))
259 274
275 (defcustom widget-field-add-space
276 (or (< emacs-major-version 20)
277 (and (eq emacs-major-version 20)
278 (< emacs-minor-version 3))
279 (not (string-match "XEmacs" emacs-version)))
280 "Non-nil means add extra space at the end of editable text fields.
281
282 This is needed on all versions of Emacs, and on XEmacs before 20.3.
283 If you don't add the space, it will become impossible to edit a zero
284 size field."
285 :type 'boolean
286 :group 'widgets)
287
260 (defun widget-specify-field (widget from to) 288 (defun widget-specify-field (widget from to)
261 "Specify editable button for WIDGET between FROM and TO." 289 "Specify editable button for WIDGET between FROM and TO."
262 (put-text-property from to 'read-only nil) 290 (put-text-property from to 'read-only nil)
263 ;; Terminating space is not part of the field, but necessary in 291 ;; Terminating space is not part of the field, but necessary in
264 ;; order for local-map to work. Remove next sexp if local-map works 292 ;; order for local-map to work. Remove next sexp if local-map works
265 ;; at the end of the overlay. 293 ;; at the end of the overlay.
266 (save-excursion 294 (save-excursion
267 (goto-char to) 295 (goto-char to)
268 (insert-and-inherit " ") 296 (when widget-field-add-space
297 (insert-and-inherit " "))
269 (setq to (point))) 298 (setq to (point)))
270 (add-text-properties (1- to) to ;to (1+ to) 299 (add-text-properties (1- to) to ;to (1+ to)
271 '(front-sticky nil start-open t read-only to)) 300 '(front-sticky nil start-open t read-only to))
272 (add-text-properties (1- from) from 301 (add-text-properties (1- from) from
273 '(rear-nonsticky t end-open t read-only from)) 302 '(rear-nonsticky t end-open t read-only from))
317 (let ((face (widget-apply widget :sample-face-get))) 346 (let ((face (widget-apply widget :sample-face-get)))
318 (when face 347 (when face
319 (add-text-properties from to (list 'start-open t 348 (add-text-properties from to (list 'start-open t
320 'end-open t 349 'end-open t
321 'face face))))) 350 'face face)))))
322
323 (defun widget-specify-doc (widget from to) 351 (defun widget-specify-doc (widget from to)
324 ;; Specify documentation for WIDGET between FROM and TO. 352 ;; Specify documentation for WIDGET between FROM and TO.
325 (add-text-properties from to (list 'widget-doc widget 353 (add-text-properties from to (list 'widget-doc widget
326 'face 'widget-documentation-face))) 354 'face 'widget-documentation-face)))
327 355
441 (cons (list (car vals)) (cdr vals))) 469 (cons (list (car vals)) (cdr vals)))
442 (t nil))) 470 (t nil)))
443 471
444 (defun widget-apply-action (widget &optional event) 472 (defun widget-apply-action (widget &optional event)
445 "Apply :action in WIDGET in response to EVENT." 473 "Apply :action in WIDGET in response to EVENT."
446 (let (after-change-functions) 474 (if (widget-apply widget :active)
447 (if (widget-apply widget :active) 475 (widget-apply widget :action event)
448 (widget-apply widget :action event) 476 (error "Attempt to perform action on inactive widget")))
449 (error "Attempt to perform action on inactive widget"))))
450 477
451 ;;; Helper functions. 478 ;;; Helper functions.
452 ;; 479 ;;
453 ;; These are widget specific. 480 ;; These are widget specific.
454 481
608 (set-glyph-property inactive 'widget widget)) 635 (set-glyph-property inactive 'widget widget))
609 (insert "*") 636 (insert "*")
610 (let ((ext (make-extent (point) (1- (point)))) 637 (let ((ext (make-extent (point) (1- (point))))
611 (help-echo (widget-get widget :help-echo))) 638 (help-echo (widget-get widget :help-echo)))
612 (set-extent-property ext 'invisible t) 639 (set-extent-property ext 'invisible t)
640 (set-extent-property ext 'start-open t)
641 (set-extent-property ext 'end-open t)
613 (set-extent-end-glyph ext glyph) 642 (set-extent-end-glyph ext glyph)
614 (when help-echo 643 (when help-echo
615 (set-extent-property ext 'balloon-help help-echo) 644 (set-extent-property ext 'balloon-help help-echo)
616 (set-extent-property ext 'help-echo help-echo))) 645 (set-extent-property ext 'help-echo help-echo)))
617 (widget-put widget :glyph-up glyph) 646 (widget-put widget :glyph-up glyph)
743 after-change-functions 772 after-change-functions
744 (from (point))) 773 (from (point)))
745 (apply 'insert args) 774 (apply 'insert args)
746 (widget-specify-text from (point)))) 775 (widget-specify-text from (point))))
747 776
748 (defun widget-convert-text (type from to &optional button-from button-to) 777 (defun widget-convert-text (type from to
778 &optional button-from button-to
779 &rest args)
749 "Return a widget of type TYPE with endpoint FROM TO. 780 "Return a widget of type TYPE with endpoint FROM TO.
750 No text will be inserted to the buffer, instead the text between FROM 781 Optional ARGS are extra keyword arguments for TYPE.
751 and TO will be used as the widgets end points. If optional arguments 782 and TO will be used as the widgets end points. If optional arguments
752 BUTTON-FROM and BUTTON-TO are given, these will be used as the widgets 783 BUTTON-FROM and BUTTON-TO are given, these will be used as the widgets
753 button end points." 784 button end points.
754 (let ((widget (widget-convert type)) 785 Optional ARGS are extra keyword arguments for TYPE."
786 (let ((widget (apply 'widget-convert type :delete 'widget-leave-text args))
755 (from (copy-marker from)) 787 (from (copy-marker from))
756 (to (copy-marker to))) 788 (to (copy-marker to)))
757 (widget-specify-text from to) 789 (widget-specify-text from to)
758 (set-marker-insertion-type from t) 790 (set-marker-insertion-type from t)
759 (set-marker-insertion-type to nil) 791 (set-marker-insertion-type to nil)
761 (widget-put widget :to to) 793 (widget-put widget :to to)
762 (when button-from 794 (when button-from
763 (widget-specify-button widget button-from button-to)) 795 (widget-specify-button widget button-from button-to))
764 widget)) 796 widget))
765 797
766 (defun widget-convert-button (type from to) 798 (defun widget-convert-button (type from to &rest args)
767 "Return a widget of type TYPE with endpoint FROM TO. 799 "Return a widget of type TYPE with endpoint FROM TO.
800 Optional ARGS are extra keyword arguments for TYPE.
768 No text will be inserted to the buffer, instead the text between FROM 801 No text will be inserted to the buffer, instead the text between FROM
769 and TO will be used as the widgets end points, as well as the widgets 802 and TO will be used as the widgets end points, as well as the widgets
770 button end points." 803 button end points."
771 (widget-convert-text type from to from to)) 804 (apply 'widget-convert-text type from to from to args))
805
806 (defun widget-leave-text (widget)
807 "Remove markers and overlays from WIDGET and its children."
808 (let ((from (widget-get widget :from))
809 (to (widget-get widget :to))
810 (button (widget-get widget :button-overlay))
811 (field (widget-get widget :field-overlay))
812 (children (widget-get widget :children)))
813 (set-marker from nil)
814 (set-marker to nil)
815 (delete-overlay button)
816 (delete-overlay field)
817 (mapcar 'widget-leave-text children)))
772 818
773 ;;; Keymap and Commands. 819 ;;; Keymap and Commands.
774 820
775 (defvar widget-keymap nil 821 (defvar widget-keymap nil
776 "Keymap containing useful binding for buffers containing widgets. 822 "Keymap containing useful binding for buffers containing widgets.
940 (widget-apply-action button event) 986 (widget-apply-action button event)
941 (let ((command (lookup-key widget-global-map (this-command-keys)))) 987 (let ((command (lookup-key widget-global-map (this-command-keys))))
942 (when (commandp command) 988 (when (commandp command)
943 (call-interactively command)))))) 989 (call-interactively command))))))
944 990
991 (defun widget-tabable-at (&optional pos)
992 "Return the tabable widget at POS, or nil.
993 POS defaults to the value of (point)."
994 (unless pos
995 (setq pos (point)))
996 (let ((widget (or (get-char-property (point) 'button)
997 (get-char-property (point) 'field))))
998 (if widget
999 (let ((order (widget-get widget :tab-order)))
1000 (if order
1001 (if (>= order 0)
1002 widget
1003 nil)
1004 widget))
1005 nil)))
1006
945 (defun widget-move (arg) 1007 (defun widget-move (arg)
946 "Move point to the ARG next field or button. 1008 "Move point to the ARG next field or button.
947 ARG may be negative to move backward." 1009 ARG may be negative to move backward."
948 (or (bobp) (> arg 0) (backward-char)) 1010 (or (bobp) (> arg 0) (backward-char))
949 (let ((pos (point)) 1011 (let ((pos (point))
950 (number arg) 1012 (number arg)
951 (old (or (get-char-property (point) 'button) 1013 (old (widget-tabable-at))
952 (get-char-property (point) 'field)))
953 new) 1014 new)
954 ;; Forward. 1015 ;; Forward.
955 (while (> arg 0) 1016 (while (> arg 0)
956 (if (eobp) 1017 (if (eobp)
957 (goto-char (point-min)) 1018 (goto-char (point-min))
958 (forward-char 1)) 1019 (forward-char 1))
959 (and (eq pos (point)) 1020 (and (eq pos (point))
960 (eq arg number) 1021 (eq arg number)
961 (error "No buttons or fields found")) 1022 (error "No buttons or fields found"))
962 (let ((new (or (get-char-property (point) 'button) 1023 (let ((new (widget-tabable-at)))
963 (get-char-property (point) 'field))))
964 (when new 1024 (when new
965 (unless (eq new old) 1025 (unless (eq new old)
966 (unless (and (widget-get new :tab-order) 1026 (setq arg (1- arg))
967 (< (widget-get new :tab-order) 0))
968 (setq arg (1- arg)))
969 (setq old new))))) 1027 (setq old new)))))
970 ;; Backward. 1028 ;; Backward.
971 (while (< arg 0) 1029 (while (< arg 0)
972 (if (bobp) 1030 (if (bobp)
973 (goto-char (point-max)) 1031 (goto-char (point-max))
974 (backward-char 1)) 1032 (backward-char 1))
975 (and (eq pos (point)) 1033 (and (eq pos (point))
976 (eq arg number) 1034 (eq arg number)
977 (error "No buttons or fields found")) 1035 (error "No buttons or fields found"))
978 (let ((new (or (get-char-property (point) 'button) 1036 (let ((new (widget-tabable-at)))
979 (get-char-property (point) 'field))))
980 (when new 1037 (when new
981 (unless (eq new old) 1038 (unless (eq new old)
982 (unless (and (widget-get new :tab-order) 1039 (setq arg (1+ arg))))))
983 (< (widget-get new :tab-order) 0)) 1040 (let ((new (widget-tabable-at)))
984 (setq arg (1+ arg))))))) 1041 (while (eq (widget-tabable-at) new)
985 (while (or (get-char-property (point) 'button) 1042 (backward-char)))
986 (get-char-property (point) 'field))
987 (backward-char))
988 (forward-char)) 1043 (forward-char))
989 (widget-echo-help (point)) 1044 (widget-echo-help (point))
990 (run-hooks 'widget-move-hook)) 1045 (run-hooks 'widget-move-hook))
991 1046
992 (defun widget-forward (arg) 1047 (defun widget-forward (arg)
1072 (set-marker from nil) 1127 (set-marker from nil)
1073 (set-marker to nil)))) 1128 (set-marker to nil))))
1074 (widget-clear-undo) 1129 (widget-clear-undo)
1075 ;; We need to maintain text properties and size of the editing fields. 1130 ;; We need to maintain text properties and size of the editing fields.
1076 (make-local-variable 'after-change-functions) 1131 (make-local-variable 'after-change-functions)
1077 (if (and widget-field-list) 1132 (if widget-field-list
1078 (setq after-change-functions '(widget-after-change)) 1133 (setq after-change-functions '(widget-after-change))
1079 (setq after-change-functions nil))) 1134 (setq after-change-functions nil)))
1080 1135
1081 (defvar widget-field-last nil) 1136 (defvar widget-field-last nil)
1082 ;; Last field containing point. 1137 ;; Last field containing point.
1098 1153
1099 (defun widget-field-end (widget) 1154 (defun widget-field-end (widget)
1100 "Return the end of WIDGET's editing field." 1155 "Return the end of WIDGET's editing field."
1101 (let ((overlay (widget-get widget :field-overlay))) 1156 (let ((overlay (widget-get widget :field-overlay)))
1102 ;; Don't subtract one if local-map works at the end of the overlay. 1157 ;; Don't subtract one if local-map works at the end of the overlay.
1103 (and overlay (1- (overlay-end overlay))))) 1158 (and overlay (if widget-field-add-space
1159 (1- (overlay-end overlay))
1160 (overlay-end overlay)))))
1104 1161
1105 (defun widget-field-find (pos) 1162 (defun widget-field-find (pos)
1106 "Return the field at POS. 1163 "Return the field at POS.
1107 Unlike (get-char-property POS 'field) this, works with empty fields too." 1164 Unlike (get-char-property POS 'field) this, works with empty fields too."
1108 (let ((fields widget-field-list) 1165 (let ((fields widget-field-list)
1124 (let ((field (widget-field-find from)) 1181 (let ((field (widget-field-find from))
1125 (other (widget-field-find to))) 1182 (other (widget-field-find to)))
1126 (when field 1183 (when field
1127 (unless (eq field other) 1184 (unless (eq field other)
1128 (debug "Change in different fields")) 1185 (debug "Change in different fields"))
1129 (let ((size (widget-get field :size))) 1186 (let ((size (widget-get field :size))
1187 (secret (widget-get field :secret)))
1130 (when size 1188 (when size
1131 (let ((begin (widget-field-start field)) 1189 (let ((begin (widget-field-start field))
1132 (end (widget-field-end field))) 1190 (end (widget-field-end field)))
1133 (cond ((< (- end begin) size) 1191 (cond ((< (- end begin) size)
1134 ;; Field too small. 1192 ;; Field too small.
1145 (setq begin (point))) 1203 (setq begin (point)))
1146 (save-excursion 1204 (save-excursion
1147 (goto-char end) 1205 (goto-char end)
1148 (while (and (eq (preceding-char) ?\ ) 1206 (while (and (eq (preceding-char) ?\ )
1149 (> (point) begin)) 1207 (> (point) begin))
1150 (delete-backward-char 1)))))))) 1208 (delete-backward-char 1)))))))
1209 (when secret
1210 (let ((begin (widget-field-start field))
1211 (end (widget-field-end field)))
1212 (when size
1213 (while (and (> end begin)
1214 (eq (char-after (1- end)) ?\ ))
1215 (setq end (1- end))))
1216 (while (< begin end)
1217 (let ((old (char-after begin)))
1218 (unless (eq old secret)
1219 (subst-char-in-region begin (1+ begin) old secret)
1220 (put-text-property begin (1+ begin) 'secret old))
1221 (setq begin (1+ begin)))))))
1151 (widget-apply field :notify field))) 1222 (widget-apply field :notify field)))
1152 (error (debug "After Change")))) 1223 (error (debug "After Change"))))
1153 1224
1154 ;;; Widget Functions 1225 ;;; Widget Functions
1155 ;; 1226 ;;
1318 (t 1389 (t
1319 (funcall doc-property 1390 (funcall doc-property
1320 (widget-get widget :value))))) 1391 (widget-get widget :value)))))
1321 (doc-text (and (stringp doc-try) 1392 (doc-text (and (stringp doc-try)
1322 (> (length doc-try) 1) 1393 (> (length doc-try) 1)
1323 doc-try))) 1394 doc-try))
1395 (doc-indent (widget-get widget :documentation-indent)))
1324 (when doc-text 1396 (when doc-text
1325 (and (eq (preceding-char) ?\n) 1397 (and (eq (preceding-char) ?\n)
1326 (widget-get widget :indent) 1398 (widget-get widget :indent)
1327 (insert-char ? (widget-get widget :indent))) 1399 (insert-char ? (widget-get widget :indent)))
1328 ;; The `*' in the beginning is redundant. 1400 ;; The `*' in the beginning is redundant.
1331 ;; Get rid of trailing newlines. 1403 ;; Get rid of trailing newlines.
1332 (when (string-match "\n+\\'" doc-text) 1404 (when (string-match "\n+\\'" doc-text)
1333 (setq doc-text (substring doc-text 0 (match-beginning 0)))) 1405 (setq doc-text (substring doc-text 0 (match-beginning 0))))
1334 (push (widget-create-child-and-convert 1406 (push (widget-create-child-and-convert
1335 widget 'documentation-string 1407 widget 'documentation-string
1408 :indent (cond ((numberp doc-indent )
1409 doc-indent)
1410 ((null doc-indent)
1411 nil)
1412 (t 0))
1336 doc-text) 1413 doc-text)
1337 buttons)))) 1414 buttons))))
1338 (t 1415 (t
1339 (error "Unknown escape `%c'" escape))) 1416 (error "Unknown escape `%c'" escape)))
1340 (widget-put widget :buttons buttons))) 1417 (widget-put widget :buttons buttons)))
2520 (if (widget-value widget) 2597 (if (widget-value widget)
2521 (widget-glyph-insert widget on "down" "down-pushed") 2598 (widget-glyph-insert widget on "down" "down-pushed")
2522 (widget-glyph-insert widget off "right" "right-pushed") 2599 (widget-glyph-insert widget off "right" "right-pushed")
2523 (insert "...")))) 2600 (insert "..."))))
2524 2601
2602 ;;; The `documentation-link' Widget.
2603 ;;
2604 ;; This is a helper widget for `documentation-string'.
2605
2606 (define-widget 'documentation-link 'link
2607 "Link type used in documentation strings."
2608 :tab-order -1
2609 :help-echo 'widget-documentation-link-echo-help
2610 :action 'widget-documentation-link-action)
2611
2612 (defun widget-documentation-link-echo-help (widget)
2613 "Tell what this link will describe."
2614 (concat "Describe the `" (widget-get widget :value) "' symbol."))
2615
2616 (defun widget-documentation-link-action (widget &optional event)
2617 "Run apropos on WIDGET's value. Ignore optional argument EVENT."
2618 (apropos (concat "\\`" (regexp-quote (widget-get widget :value)) "\\'")))
2619
2620 (defcustom widget-documentation-links t
2621 "Add hyperlinks to documentation strings when non-nil."
2622 :type 'boolean
2623 :group 'widget-documentation)
2624
2625 (defcustom widget-documentation-link-regexp "`\\([^\n`' ]+\\)'"
2626 "Regexp for matching potential links in documentation strings.
2627 The first group should be the link itself."
2628 :type 'regexp
2629 :group 'widget-documentation)
2630
2631 (defcustom widget-documentation-link-p 'intern-soft
2632 "Predicate used to test if a string is useful as a link.
2633 The value should be a function. The function will be called one
2634 argument, a string, and should return non-nil if there should be a
2635 link for that string."
2636 :type 'function
2637 :options '(widget-documentation-link-p)
2638 :group 'widget-documentation)
2639
2640 (defcustom widget-documentation-link-type 'documentation-link
2641 "Widget type used for links in documentation strings."
2642 :type 'symbol
2643 :group 'widget-documentation)
2644
2645 (defun widget-documentation-link-add (widget from to)
2646 (widget-specify-doc widget from to)
2647 (when widget-documentation-links
2648 (let ((regexp widget-documentation-link-regexp)
2649 (predicate widget-documentation-link-p)
2650 (type widget-documentation-link-type)
2651 (buttons (widget-get widget :buttons)))
2652 (save-excursion
2653 (goto-char from)
2654 (while (re-search-forward regexp to t)
2655 (let ((name (match-string 1))
2656 (begin (match-beginning 0))
2657 (end (match-end 0)))
2658 (when (funcall predicate name)
2659 (push (widget-convert-button type begin end :value name)
2660 buttons)))))
2661 (widget-put widget :buttons buttons)))
2662 (let ((indent (widget-get widget :indent)))
2663 (when (and indent (not (zerop indent)))
2664 (save-excursion
2665 (save-restriction
2666 (narrow-to-region from to)
2667 (goto-char (point-min))
2668 (while (search-forward "\n" nil t)
2669 (insert-char ?\ indent)))))))
2670
2525 ;;; The `documentation-string' Widget. 2671 ;;; The `documentation-string' Widget.
2526
2527 (defface widget-documentation-face '((((class color)
2528 (background dark))
2529 (:foreground "lime green"))
2530 (((class color)
2531 (background light))
2532 (:foreground "dark green"))
2533 (t nil))
2534 "Face used for documentation text."
2535 :group 'widget-faces)
2536 2672
2537 (define-widget 'documentation-string 'item 2673 (define-widget 'documentation-string 'item
2538 "A documentation string." 2674 "A documentation string."
2539 :format "%v" 2675 :format "%v"
2540 :action 'widget-documentation-string-action 2676 :action 'widget-documentation-string-action
2542 :value-create 'widget-documentation-string-value-create) 2678 :value-create 'widget-documentation-string-value-create)
2543 2679
2544 (defun widget-documentation-string-value-create (widget) 2680 (defun widget-documentation-string-value-create (widget)
2545 ;; Insert documentation string. 2681 ;; Insert documentation string.
2546 (let ((doc (widget-value widget)) 2682 (let ((doc (widget-value widget))
2683 (indent (widget-get widget :indent))
2547 (shown (widget-get (widget-get widget :parent) :documentation-shown)) 2684 (shown (widget-get (widget-get widget :parent) :documentation-shown))
2548 (start (point))) 2685 (start (point)))
2549 (if (string-match "\n" doc) 2686 (if (string-match "\n" doc)
2550 (let ((before (substring doc 0 (match-beginning 0))) 2687 (let ((before (substring doc 0 (match-beginning 0)))
2551 (after (substring doc (match-beginning 0))) 2688 (after (substring doc (match-beginning 0)))
2552 buttons) 2689 buttons)
2553 (insert before " ") 2690 (insert before " ")
2554 (widget-specify-doc widget start (point)) 2691 (widget-documentation-link-add widget start (point))
2555 (push (widget-create-child-and-convert 2692 (push (widget-create-child-and-convert
2556 widget 'visibility 2693 widget 'visibility
2694 :help-echo "Show or hide rest of the documentation."
2557 :off nil 2695 :off nil
2558 :action 'widget-parent-action 2696 :action 'widget-parent-action
2559 shown) 2697 shown)
2560 buttons) 2698 buttons)
2561 (when shown 2699 (when shown
2562 (setq start (point)) 2700 (setq start (point))
2701 (when (and indent (not (zerop indent)))
2702 (insert-char ?\ indent))
2563 (insert after) 2703 (insert after)
2564 (widget-specify-doc widget start (point))) 2704 (widget-documentation-link-add widget start (point)))
2565 (widget-put widget :buttons buttons)) 2705 (widget-put widget :buttons buttons))
2566 (insert doc) 2706 (insert doc)
2567 (widget-specify-doc widget start (point)))) 2707 (widget-documentation-link-add widget start (point))))
2568 (insert "\n")) 2708 (insert "\n"))
2569 2709
2570 (defun widget-documentation-string-action (widget &rest ignore) 2710 (defun widget-documentation-string-action (widget &rest ignore)
2571 ;; Toggle documentation. 2711 ;; Toggle documentation.
2572 (let ((parent (widget-get widget :parent))) 2712 (let ((parent (widget-get widget :parent)))
2900 (widget-apply widget :value-to-internal value)))) 3040 (widget-apply widget :value-to-internal value))))
2901 3041
2902 (define-widget 'choice 'menu-choice 3042 (define-widget 'choice 'menu-choice
2903 "A union of several sexp types." 3043 "A union of several sexp types."
2904 :tag "Choice" 3044 :tag "Choice"
2905 :format "%[%t%]: %v" 3045 :format "%{%t%}: %[value menu%] %v"
3046 :button-prefix 'widget-push-button-prefix
3047 :button-suffix 'widget-push-button-suffix
2906 :prompt-value 'widget-choice-prompt-value) 3048 :prompt-value 'widget-choice-prompt-value)
2907 3049
2908 (defun widget-choice-prompt-value (widget prompt value unbound) 3050 (defun widget-choice-prompt-value (widget prompt value unbound)
2909 "Make a choice." 3051 "Make a choice."
2910 (let ((args (widget-get widget :args)) 3052 (let ((args (widget-get widget :args))
2965 3107
2966 (define-widget 'boolean 'toggle 3108 (define-widget 'boolean 'toggle
2967 "To be nil or non-nil, that is the question." 3109 "To be nil or non-nil, that is the question."
2968 :tag "Boolean" 3110 :tag "Boolean"
2969 :prompt-value 'widget-boolean-prompt-value 3111 :prompt-value 'widget-boolean-prompt-value
2970 :format "%[%t%]: %v\n") 3112 :button-prefix 'widget-push-button-prefix
3113 :button-suffix 'widget-push-button-suffix
3114 :format "%{%t%}: %[toggle%] %v\n")
2971 3115
2972 (defun widget-boolean-prompt-value (widget prompt value unbound) 3116 (defun widget-boolean-prompt-value (widget prompt value unbound)
2973 ;; Toggle a boolean. 3117 ;; Toggle a boolean.
2974 (y-or-n-p prompt)) 3118 (y-or-n-p prompt))
2975 3119