Mercurial > emacs
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 |