Mercurial > hg > xemacs-beta
comparison lisp/custom/wid-edit.el @ 165:5a88923fcbfe r20-3b9
Import from CVS: tag r20-3b9
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:44:42 +0200 |
parents | 0132846995bd |
children | 85ec50267440 |
comparison
equal
deleted
inserted
replaced
164:4e0740e5aab2 | 165:5a88923fcbfe |
---|---|
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.9931 | 7 ;; Version: 1.9937 |
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 |
132 (defgroup widget-faces nil | 132 (defgroup widget-faces nil |
133 "Faces used by the widget library." | 133 "Faces used by the widget library." |
134 :group 'widgets | 134 :group 'widgets |
135 :group 'faces) | 135 :group 'faces) |
136 | 136 |
137 (defvar widget-documentation-face 'widget-documentation-face | |
138 "Face used for documentation strings in widges. | |
139 This exists as a variable so it can be set locally in certain buffers.") | |
140 | |
137 (defface widget-documentation-face '((((class color) | 141 (defface widget-documentation-face '((((class color) |
138 (background dark)) | 142 (background dark)) |
139 (:foreground "lime green")) | 143 (:foreground "lime green")) |
140 (((class color) | 144 (((class color) |
141 (background light)) | 145 (background light)) |
199 (defcustom widget-menu-max-size 40 | 203 (defcustom widget-menu-max-size 40 |
200 "Largest number of items allowed in a popup-menu. | 204 "Largest number of items allowed in a popup-menu. |
201 Larger menus are read through the minibuffer." | 205 Larger menus are read through the minibuffer." |
202 :group 'widgets | 206 :group 'widgets |
203 :type 'integer) | 207 :type 'integer) |
208 | |
209 (defcustom widget-menu-minibuffer-flag nil | |
210 "*Control how to ask for a choice from the keyboard. | |
211 Non-nil means use the minibuffer; | |
212 nil means read a single character." | |
213 :group 'widgets | |
214 :type 'boolean) | |
204 | 215 |
205 (defun widget-choose (title items &optional event) | 216 (defun widget-choose (title items &optional event) |
206 "Choose an item from a list. | 217 "Choose an item from a list. |
207 | 218 |
208 First argument TITLE is the name of the list. | 219 First argument TITLE is the name of the list. |
236 (setq val (and val | 247 (setq val (and val |
237 (listp (event-object val)) | 248 (listp (event-object val)) |
238 (stringp (car-safe (event-object val))) | 249 (stringp (car-safe (event-object val))) |
239 (car (event-object val)))) | 250 (car (event-object val)))) |
240 (cdr (assoc val items)))) | 251 (cdr (assoc val items)))) |
241 (t | 252 (widget-menu-minibuffer-flag |
253 ;; Read the choice of name from the minibuffer. | |
242 (setq items (widget-remove-if 'stringp items)) | 254 (setq items (widget-remove-if 'stringp items)) |
243 (let ((val (completing-read (concat title ": ") items nil t))) | 255 (let ((val (completing-read (concat title ": ") items nil t))) |
244 (if (stringp val) | 256 (if (stringp val) |
245 (let ((try (try-completion val items))) | 257 (let ((try (try-completion val items))) |
246 (when (stringp try) | 258 (when (stringp try) |
247 (setq val try)) | 259 (setq val try)) |
248 (cdr (assoc val items))) | 260 (cdr (assoc val items))) |
249 nil))))) | 261 nil))) |
262 (t | |
263 ;; Construct a menu of the choices | |
264 ;; and then use it for prompting for a single character. | |
265 (let* ((overriding-terminal-local-map | |
266 (make-sparse-keymap)) | |
267 map choice (next-digit ?0) | |
268 value) | |
269 ;; Define SPC as a prefix char to get to this menu. | |
270 (define-key overriding-terminal-local-map " " | |
271 (setq map (make-sparse-keymap title))) | |
272 (while items | |
273 (setq choice (car items) items (cdr items)) | |
274 (if (consp choice) | |
275 (let* ((name (car choice)) | |
276 (function (cdr choice)) | |
277 (character (aref name 0))) | |
278 ;; Pick a character for this choice; | |
279 ;; avoid duplication. | |
280 (when (lookup-key map (vector character)) | |
281 (setq character (downcase character)) | |
282 (when (lookup-key map (vector character)) | |
283 (setq character next-digit | |
284 next-digit (1+ next-digit)))) | |
285 (define-key map (vector character) | |
286 (cons (format "%c = %s" character name) function))))) | |
287 (define-key map [?\C-g] '("Quit" . keyboard-quit)) | |
288 (define-key map [t] 'keyboard-quit) | |
289 (setcdr map (nreverse (cdr map))) | |
290 ;; Unread a SPC to lead to our new menu. | |
291 (setq unread-command-events (cons ?\ unread-command-events)) | |
292 ;; Read a char with the menu, and return the result | |
293 ;; that corresponds to it. | |
294 (setq value | |
295 (lookup-key overriding-terminal-local-map | |
296 (read-key-sequence title) t)) | |
297 (when (eq value 'keyboard-quit) | |
298 (error "Canceled")) | |
299 value)))) | |
250 | 300 |
251 (defun widget-remove-if (predictate list) | 301 (defun widget-remove-if (predictate list) |
252 (let (result (tail list)) | 302 (let (result (tail list)) |
253 (while tail | 303 (while tail |
254 (or (funcall predictate (car tail)) | 304 (or (funcall predictate (car tail)) |
280 "Non-nil means add extra space at the end of editable text fields. | 330 "Non-nil means add extra space at the end of editable text fields. |
281 | 331 |
282 This is needed on all versions of Emacs, and on XEmacs before 20.3. | 332 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 | 333 If you don't add the space, it will become impossible to edit a zero |
284 size field." | 334 size field." |
335 :type 'boolean | |
336 :group 'widgets) | |
337 | |
338 (defcustom widget-field-use-before-change | |
339 (or (> emacs-minor-version 34) | |
340 (> emacs-major-version 20) | |
341 (string-match "XEmacs" emacs-version)) | |
342 "Non-nil means use `before-change-functions' to track editable fields. | |
343 This enables the use of undo, but doesn'f work on Emacs 19.34 and earlier. | |
344 Using before hooks also means that the :notify function can't know the | |
345 new value." | |
285 :type 'boolean | 346 :type 'boolean |
286 :group 'widgets) | 347 :group 'widgets) |
287 | 348 |
288 (defun widget-specify-field (widget from to) | 349 (defun widget-specify-field (widget from to) |
289 "Specify editable button for WIDGET between FROM and TO." | 350 "Specify editable button for WIDGET between FROM and TO." |
352 'end-open t | 413 'end-open t |
353 'face face))))) | 414 'face face))))) |
354 (defun widget-specify-doc (widget from to) | 415 (defun widget-specify-doc (widget from to) |
355 ;; Specify documentation for WIDGET between FROM and TO. | 416 ;; Specify documentation for WIDGET between FROM and TO. |
356 (add-text-properties from to (list 'widget-doc widget | 417 (add-text-properties from to (list 'widget-doc widget |
357 'face 'widget-documentation-face))) | 418 'face widget-documentation-face))) |
358 | 419 |
359 (defmacro widget-specify-insert (&rest form) | 420 (defmacro widget-specify-insert (&rest form) |
360 ;; Execute FORM without inheriting any text properties. | 421 ;; Execute FORM without inheriting any text properties. |
361 (` | 422 (` |
362 (save-restriction | 423 (save-restriction |
929 (when (and pos | 990 (when (and pos |
930 (eq (get-char-property pos 'button) button)) | 991 (eq (get-char-property pos 'button) button)) |
931 (widget-apply-action button event))) | 992 (widget-apply-action button event))) |
932 (overlay-put overlay 'face face) | 993 (overlay-put overlay 'face face) |
933 (overlay-put overlay 'mouse-face mouse-face))) | 994 (overlay-put overlay 'mouse-face mouse-face))) |
934 (let (command up) | 995 (let ((up t) |
996 command) | |
935 ;; Find the global command to run, and check whether it | 997 ;; Find the global command to run, and check whether it |
936 ;; is bound to an up event. | 998 ;; is bound to an up event. |
937 (cond ((setq command ;down event | 999 (cond ((setq command ;down event |
938 (lookup-key widget-global-map [ button2 ]))) | 1000 (lookup-key widget-global-map [ button2 ])) |
1001 (setq up nil)) | |
939 ((setq command ;down event | 1002 ((setq command ;down event |
940 (lookup-key widget-global-map [ down-mouse-2 ]))) | 1003 (lookup-key widget-global-map [ down-mouse-2 ])) |
1004 (setq up nil)) | |
941 ((setq command ;up event | 1005 ((setq command ;up event |
942 (lookup-key widget-global-map [ button2up ])) | 1006 (lookup-key widget-global-map [ button2up ]))) |
943 (setq up t)) | |
944 ((setq command ;up event | 1007 ((setq command ;up event |
945 (lookup-key widget-global-map [ mouse-2])) | 1008 (lookup-key widget-global-map [ mouse-2])))) |
946 (setq up t))) | 1009 (when up |
1010 ;; Don't execute up events twice. | |
1011 (while (not (button-release-event-p event)) | |
1012 (setq event (widget-read-event)))) | |
947 (when command | 1013 (when command |
948 ;; Don't execute up events twice. | |
949 (when up | |
950 (while (not (button-release-event-p event)) | |
951 (setq event (widget-read-event)))) | |
952 (call-interactively command)))))) | 1014 (call-interactively command)))))) |
953 (t | 1015 (t |
954 (message "You clicked somewhere weird.")))) | 1016 (message "You clicked somewhere weird.")))) |
955 | 1017 |
956 (defun widget-button1-click (event) | 1018 (defun widget-button1-click (event) |
1138 (set-marker from nil) | 1200 (set-marker from nil) |
1139 (set-marker to nil)))) | 1201 (set-marker to nil)))) |
1140 (widget-clear-undo) | 1202 (widget-clear-undo) |
1141 ;; We need to maintain text properties and size of the editing fields. | 1203 ;; We need to maintain text properties and size of the editing fields. |
1142 (make-local-variable 'after-change-functions) | 1204 (make-local-variable 'after-change-functions) |
1143 (make-local-variable 'before-change-functions) | |
1144 (setq after-change-functions | 1205 (setq after-change-functions |
1145 (if widget-field-list '(widget-after-change) nil)) | 1206 (if widget-field-list '(widget-after-change) nil)) |
1146 (setq before-change-functions | 1207 (when widget-field-use-before-change |
1147 (if widget-field-list '(widget-before-change) nil))) | 1208 (make-local-variable 'before-change-functions) |
1209 (setq before-change-functions | |
1210 (if widget-field-list '(widget-before-change) nil)))) | |
1148 | 1211 |
1149 (defvar widget-field-last nil) | 1212 (defvar widget-field-last nil) |
1150 ;; Last field containing point. | 1213 ;; Last field containing point. |
1151 (make-variable-buffer-local 'widget-field-last) | 1214 (make-variable-buffer-local 'widget-field-last) |
1152 | 1215 |
1435 buttons)))) | 1498 buttons)))) |
1436 (t | 1499 (t |
1437 (error "Unknown escape `%c'" escape))) | 1500 (error "Unknown escape `%c'" escape))) |
1438 (widget-put widget :buttons buttons))) | 1501 (widget-put widget :buttons buttons))) |
1439 | 1502 |
1503 (defvar widget-button-face nil | |
1504 "Face to use for buttons. | |
1505 This is a variable so that it can be buffer-local.") | |
1506 | |
1440 (defun widget-default-button-face-get (widget) | 1507 (defun widget-default-button-face-get (widget) |
1441 ;; Use :button-face or widget-button-face | 1508 ;; Use :button-face or widget-button-face |
1442 (or (widget-get widget :button-face) 'widget-button-face)) | 1509 (or (widget-get widget :button-face) |
1510 (let ((parent (widget-get widget :parent))) | |
1511 (if parent | |
1512 (widget-apply parent :button-face-get) | |
1513 'widget-button-face)))) | |
1443 | 1514 |
1444 (defun widget-default-sample-face-get (widget) | 1515 (defun widget-default-sample-face-get (widget) |
1445 ;; Use :sample-face. | 1516 ;; Use :sample-face. |
1446 (widget-get widget :sample-face)) | 1517 (widget-get widget :sample-face)) |
1447 | 1518 |
1466 (set-marker to nil)) | 1537 (set-marker to nil)) |
1467 (widget-clear-undo)) | 1538 (widget-clear-undo)) |
1468 | 1539 |
1469 (defun widget-default-value-set (widget value) | 1540 (defun widget-default-value-set (widget value) |
1470 ;; Recreate widget with new value. | 1541 ;; Recreate widget with new value. |
1471 (save-excursion | 1542 (let* ((old-pos (point)) |
1472 (goto-char (widget-get widget :from)) | 1543 (from (copy-marker (widget-get widget :from))) |
1473 (widget-apply widget :delete) | 1544 (to (copy-marker (widget-get widget :to))) |
1474 (widget-put widget :value value) | 1545 (offset (if (and (<= from old-pos) (<= old-pos to)) |
1475 (widget-apply widget :create))) | 1546 (if (>= old-pos (1- to)) |
1547 (- old-pos to 1) | |
1548 (- old-pos from))))) | |
1549 ;;??? Bug: this ought to insert the new value before deleting the old one, | |
1550 ;; so that markers on either side of the value automatically | |
1551 ;; stay on the same side. -- rms. | |
1552 (save-excursion | |
1553 (goto-char (widget-get widget :from)) | |
1554 (widget-apply widget :delete) | |
1555 (widget-put widget :value value) | |
1556 (widget-apply widget :create)) | |
1557 (if offset | |
1558 (if (< offset 0) | |
1559 (goto-char (+ (widget-get widget :to) offset 1)) | |
1560 (goto-char (min (+ from offset) (1- (widget-get widget :to)))))))) | |
1476 | 1561 |
1477 (defun widget-default-value-inline (widget) | 1562 (defun widget-default-value-inline (widget) |
1478 ;; Wrap value in a list unless it is inline. | 1563 ;; Wrap value in a list unless it is inline. |
1479 (if (widget-get widget :inline) | 1564 (if (widget-get widget :inline) |
1480 (widget-value widget) | 1565 (widget-value widget) |
1705 (history (widget-get widget :prompt-history))) | 1790 (history (widget-get widget :prompt-history))) |
1706 (let ((answer (widget-apply widget | 1791 (let ((answer (widget-apply widget |
1707 :prompt-internal prompt initial history))) | 1792 :prompt-internal prompt initial history))) |
1708 (widget-apply widget :value-to-external answer)))) | 1793 (widget-apply widget :value-to-external answer)))) |
1709 | 1794 |
1795 (defvar widget-edit-functions nil) | |
1796 | |
1710 (defun widget-field-action (widget &optional event) | 1797 (defun widget-field-action (widget &optional event) |
1711 ;; Edit the value in the minibuffer. | 1798 ;; Move to next field. |
1712 (let ((invalid (widget-apply widget :validate))) | 1799 (widget-forward 1) |
1713 (let ((prompt (concat (widget-apply widget :menu-tag-get) ": ")) | 1800 (run-hook-with-args 'widget-edit-functions widget)) |
1714 (value (unless invalid | |
1715 (widget-value widget)))) | |
1716 (let ((answer (widget-apply widget :prompt-value prompt value invalid) )) | |
1717 (widget-value-set widget answer))) | |
1718 (widget-setup) | |
1719 (widget-apply widget :notify widget event))) | |
1720 | 1801 |
1721 (defun widget-field-validate (widget) | 1802 (defun widget-field-validate (widget) |
1722 ;; Valid if the content matches `:valid-regexp'. | 1803 ;; Valid if the content matches `:valid-regexp'. |
1723 (save-excursion | 1804 (save-excursion |
1724 (let ((value (widget-apply widget :value-get)) | 1805 (let ((value (widget-apply widget :value-get)) |
1909 (when current | 1990 (when current |
1910 (widget-value-set widget | 1991 (widget-value-set widget |
1911 (widget-apply current :value-to-external | 1992 (widget-apply current :value-to-external |
1912 (widget-get current :value))) | 1993 (widget-get current :value))) |
1913 (widget-setup) | 1994 (widget-setup) |
1914 (widget-apply widget :notify widget event)))) | 1995 (widget-apply widget :notify widget event))) |
1996 (run-hooks 'widget-edit-hook)) | |
1915 | 1997 |
1916 (defun widget-choice-validate (widget) | 1998 (defun widget-choice-validate (widget) |
1917 ;; Valid if we have made a valid choice. | 1999 ;; Valid if we have made a valid choice. |
1918 (let ((void (widget-get widget :void)) | 2000 (let ((void (widget-get widget :void)) |
1919 (choice (widget-get widget :choice)) | 2001 (choice (widget-get widget :choice)) |
1964 (widget-get widget :off-glyph)))) | 2046 (widget-get widget :off-glyph)))) |
1965 | 2047 |
1966 (defun widget-toggle-action (widget &optional event) | 2048 (defun widget-toggle-action (widget &optional event) |
1967 ;; Toggle value. | 2049 ;; Toggle value. |
1968 (widget-value-set widget (not (widget-value widget))) | 2050 (widget-value-set widget (not (widget-value widget))) |
1969 (widget-apply widget :notify widget event)) | 2051 (widget-apply widget :notify widget event) |
2052 (run-hooks 'widget-edit-hook)) | |
1970 | 2053 |
1971 ;;; The `checkbox' Widget. | 2054 ;;; The `checkbox' Widget. |
1972 | 2055 |
1973 (define-widget 'checkbox 'toggle | 2056 (define-widget 'checkbox 'toggle |
1974 "A checkbox toggle." | 2057 "A checkbox toggle." |
2639 (defun widget-documentation-link-echo-help (widget) | 2722 (defun widget-documentation-link-echo-help (widget) |
2640 "Tell what this link will describe." | 2723 "Tell what this link will describe." |
2641 (concat "Describe the `" (widget-get widget :value) "' symbol.")) | 2724 (concat "Describe the `" (widget-get widget :value) "' symbol.")) |
2642 | 2725 |
2643 (defun widget-documentation-link-action (widget &optional event) | 2726 (defun widget-documentation-link-action (widget &optional event) |
2644 "Run apropos on WIDGET's value. Ignore optional argument EVENT." | 2727 "Display documentation for WIDGET's value. Ignore optional argument EVENT." |
2645 (apropos (concat "\\`" (regexp-quote (widget-get widget :value)) "\\'"))) | 2728 (let* ((string (widget-get widget :value)) |
2729 (symbol (intern string))) | |
2730 (if (and (fboundp symbol) (boundp symbol)) | |
2731 ;; If there are two doc strings, give the user a way to pick one. | |
2732 (apropos (concat "\\`" (regexp-quote string) "\\'")) | |
2733 (if (fboundp symbol) | |
2734 (describe-function symbol) | |
2735 (describe-variable symbol))))) | |
2646 | 2736 |
2647 (defcustom widget-documentation-links t | 2737 (defcustom widget-documentation-links t |
2648 "Add hyperlinks to documentation strings when non-nil." | 2738 "Add hyperlinks to documentation strings when non-nil." |
2649 :type 'boolean | 2739 :type 'boolean |
2650 :group 'widget-documentation) | 2740 :group 'widget-documentation) |
2800 widget)))) | 2890 widget)))) |
2801 | 2891 |
2802 (define-widget 'file 'string | 2892 (define-widget 'file 'string |
2803 "A file widget. | 2893 "A file widget. |
2804 It will read a file name from the minibuffer when invoked." | 2894 It will read a file name from the minibuffer when invoked." |
2895 :complete-function 'widget-file-complete | |
2805 :prompt-value 'widget-file-prompt-value | 2896 :prompt-value 'widget-file-prompt-value |
2806 :format "%{%t%}: %v" | 2897 :format "%{%t%}: %v" |
2807 :tag "File" | 2898 :tag "File") |
2808 :action 'widget-file-action) | 2899 |
2900 (defun widget-file-complete () | |
2901 "Perform completion on file name preceding point." | |
2902 (interactive) | |
2903 (let* ((end (point)) | |
2904 (beg (save-excursion | |
2905 (skip-chars-backward "^ ") | |
2906 (point))) | |
2907 (pattern (buffer-substring beg end)) | |
2908 (name-part (file-name-nondirectory pattern)) | |
2909 (directory (file-name-directory pattern)) | |
2910 (completion (file-name-completion name-part directory))) | |
2911 (cond ((eq completion t)) | |
2912 ((null completion) | |
2913 (message "Can't find completion for \"%s\"" pattern) | |
2914 (ding)) | |
2915 ((not (string= name-part completion)) | |
2916 (delete-region beg end) | |
2917 (insert (expand-file-name completion directory))) | |
2918 (t | |
2919 (message "Making completion list...") | |
2920 (let ((list (file-name-all-completions name-part directory))) | |
2921 (setq list (sort list 'string<)) | |
2922 (with-output-to-temp-buffer "*Completions*" | |
2923 (display-completion-list list))) | |
2924 (message "Making completion list...%s" "done"))))) | |
2809 | 2925 |
2810 (defun widget-file-prompt-value (widget prompt value unbound) | 2926 (defun widget-file-prompt-value (widget prompt value unbound) |
2811 ;; Read file from minibuffer. | 2927 ;; Read file from minibuffer. |
2812 (abbreviate-file-name | 2928 (abbreviate-file-name |
2813 (if unbound | 2929 (if unbound |
2816 (dir (file-name-directory value)) | 2932 (dir (file-name-directory value)) |
2817 (file (file-name-nondirectory value)) | 2933 (file (file-name-nondirectory value)) |
2818 (must-match (widget-get widget :must-match))) | 2934 (must-match (widget-get widget :must-match))) |
2819 (read-file-name prompt2 dir nil must-match file))))) | 2935 (read-file-name prompt2 dir nil must-match file))))) |
2820 | 2936 |
2821 (defun widget-file-action (widget &optional event) | 2937 ;;;(defun widget-file-action (widget &optional event) |
2822 ;; Read a file name from the minibuffer. | 2938 ;;; ;; Read a file name from the minibuffer. |
2823 (let* ((value (widget-value widget)) | 2939 ;;; (let* ((value (widget-value widget)) |
2824 (dir (file-name-directory value)) | 2940 ;;; (dir (file-name-directory value)) |
2825 (file (file-name-nondirectory value)) | 2941 ;;; (file (file-name-nondirectory value)) |
2826 (menu-tag (widget-apply widget :menu-tag-get)) | 2942 ;;; (menu-tag (widget-apply widget :menu-tag-get)) |
2827 (must-match (widget-get widget :must-match)) | 2943 ;;; (must-match (widget-get widget :must-match)) |
2828 (answer (read-file-name (concat menu-tag ": (default `" value "') ") | 2944 ;;; (answer (read-file-name (concat menu-tag ": (default `" value "') ") |
2829 dir nil must-match file))) | 2945 ;;; dir nil must-match file))) |
2830 (widget-value-set widget (abbreviate-file-name answer)) | 2946 ;;; (widget-value-set widget (abbreviate-file-name answer)) |
2831 (widget-setup) | 2947 ;;; (widget-setup) |
2832 (widget-apply widget :notify widget event))) | 2948 ;;; (widget-apply widget :notify widget event))) |
2833 | 2949 |
2834 (define-widget 'directory 'file | 2950 (define-widget 'directory 'file |
2835 "A directory widget. | 2951 "A directory widget. |
2836 It will read a directory name from the minibuffer when invoked." | 2952 It will read a directory name from the minibuffer when invoked." |
2837 :tag "Directory") | 2953 :tag "Directory") |
2843 "A lisp symbol." | 2959 "A lisp symbol." |
2844 :value nil | 2960 :value nil |
2845 :tag "Symbol" | 2961 :tag "Symbol" |
2846 :format "%{%t%}: %v" | 2962 :format "%{%t%}: %v" |
2847 :match (lambda (widget value) (symbolp value)) | 2963 :match (lambda (widget value) (symbolp value)) |
2964 :complete-function 'lisp-complete-symbol | |
2848 :prompt-internal 'widget-symbol-prompt-internal | 2965 :prompt-internal 'widget-symbol-prompt-internal |
2849 :prompt-match 'symbolp | 2966 :prompt-match 'symbolp |
2850 :prompt-history 'widget-symbol-prompt-value-history | 2967 :prompt-history 'widget-symbol-prompt-value-history |
2851 :value-to-internal (lambda (widget value) | 2968 :value-to-internal (lambda (widget value) |
2852 (if (symbolp value) | 2969 (if (symbolp value) |
2988 (unless (eobp) | 3105 (unless (eobp) |
2989 (error "Junk at end of expression: %s" | 3106 (error "Junk at end of expression: %s" |
2990 (buffer-substring (point) (point-max)))) | 3107 (buffer-substring (point) (point-max)))) |
2991 answer))))) | 3108 answer))))) |
2992 | 3109 |
2993 (define-widget 'integer 'sexp | 3110 (define-widget 'restricted-sexp 'sexp |
3111 "A Lisp expression restricted to values that match. | |
3112 To use this type, you must define :match or :match-alternatives." | |
3113 :type-error "The specified value is not valid" | |
3114 :match 'widget-restricted-sexp-match | |
3115 :value-to-internal (lambda (widget value) | |
3116 (if (widget-apply widget :match value) | |
3117 (prin1-to-string value) | |
3118 value))) | |
3119 | |
3120 (defun widget-restricted-sexp-match (widget value) | |
3121 (let ((alternatives (widget-get widget :match-alternatives)) | |
3122 matched) | |
3123 (while (and alternatives (not matched)) | |
3124 (if (cond ((functionp (car alternatives)) | |
3125 (funcall (car alternatives) value)) | |
3126 ((and (consp (car alternatives)) | |
3127 (eq (car (car alternatives)) 'quote)) | |
3128 (eq value (nth 1 (car alternatives))))) | |
3129 (setq matched t)) | |
3130 (setq alternatives (cdr alternatives))) | |
3131 matched)) | |
3132 | |
3133 (define-widget 'integer 'restricted-sexp | |
2994 "An integer." | 3134 "An integer." |
2995 :tag "Integer" | 3135 :tag "Integer" |
2996 :value 0 | 3136 :value 0 |
2997 :type-error "This field should contain an integer" | 3137 :type-error "This field should contain an integer" |
2998 :value-to-internal (lambda (widget value) | 3138 :match-alternatives '(integerp)) |
2999 (if (integerp value) | 3139 |
3000 (prin1-to-string value) | 3140 (define-widget 'number 'restricted-sexp |
3001 value)) | 3141 "A floating point number." |
3002 :match (lambda (widget value) (integerp value))) | 3142 :tag "Number" |
3143 :value 0.0 | |
3144 :type-error "This field should contain a number" | |
3145 :match-alternatives '(numberp)) | |
3003 | 3146 |
3004 (define-widget 'character 'editable-field | 3147 (define-widget 'character 'editable-field |
3005 "An character." | 3148 "A character." |
3006 :tag "Character" | 3149 :tag "Character" |
3007 :value 0 | 3150 :value 0 |
3008 :size 1 | 3151 :size 1 |
3009 :format "%{%t%}: %v\n" | 3152 :format "%{%t%}: %v\n" |
3010 :valid-regexp "\\`.\\'" | 3153 :valid-regexp "\\`.\\'" |
3019 value)) | 3162 value)) |
3020 :match (lambda (widget value) | 3163 :match (lambda (widget value) |
3021 (if (fboundp 'characterp) | 3164 (if (fboundp 'characterp) |
3022 (characterp value) | 3165 (characterp value) |
3023 (integerp value)))) | 3166 (integerp value)))) |
3024 | |
3025 (define-widget 'number 'sexp | |
3026 "A floating point number." | |
3027 :tag "Number" | |
3028 :value 0.0 | |
3029 :type-error "This field should contain a number" | |
3030 :value-to-internal (lambda (widget value) | |
3031 (if (numberp value) | |
3032 (prin1-to-string value) | |
3033 value)) | |
3034 :match (lambda (widget value) (numberp value))) | |
3035 | 3167 |
3036 (define-widget 'list 'group | 3168 (define-widget 'list 'group |
3037 "A lisp list." | 3169 "A lisp list." |
3038 :tag "List" | 3170 :tag "List" |
3039 :format "%{%t%}:\n%v") | 3171 :format "%{%t%}:\n%v") |