diff options
| -rw-r--r-- | lisp/cus-edit.el | 398 | ||||
| -rw-r--r-- | lisp/custom.el | 154 | ||||
| -rw-r--r-- | lisp/wid-browse.el | 35 | ||||
| -rw-r--r-- | lisp/wid-edit.el | 180 | ||||
| -rw-r--r-- | lisp/widget.el | 13 |
5 files changed, 622 insertions, 158 deletions
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 43a8ca53ade..eafbcec48c9 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | ;; | 4 | ;; |
| 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> | 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> |
| 6 | ;; Keywords: help, faces | 6 | ;; Keywords: help, faces |
| 7 | ;; Version: 1.84 | 7 | ;; Version: 1.90 |
| 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. |
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | ;;; Commentary: | 27 | ;;; Commentary: |
| 28 | ;; | 28 | ;; |
| 29 | ;; This file implements the code to create and edit customize buffers. | ||
| 30 | ;; | ||
| 29 | ;; See `custom.el'. | 31 | ;; See `custom.el'. |
| 30 | 32 | ||
| 31 | ;;; Code: | 33 | ;;; Code: |
| @@ -33,6 +35,11 @@ | |||
| 33 | (require 'cus-face) | 35 | (require 'cus-face) |
| 34 | (require 'wid-edit) | 36 | (require 'wid-edit) |
| 35 | (require 'easymenu) | 37 | (require 'easymenu) |
| 38 | (eval-when-compile (require 'cl)) | ||
| 39 | |||
| 40 | (condition-case nil | ||
| 41 | (require 'cus-load) | ||
| 42 | (error nil)) | ||
| 36 | 43 | ||
| 37 | (defun custom-face-display-set (face spec &optional frame) | 44 | (defun custom-face-display-set (face spec &optional frame) |
| 38 | (face-spec-set face spec frame)) | 45 | (face-spec-set face spec frame)) |
| @@ -355,10 +362,30 @@ Return a list suitable for use in `interactive'." | |||
| 355 | (if v | 362 | (if v |
| 356 | (format "Customize variable (default %s): " v) | 363 | (format "Customize variable (default %s): " v) |
| 357 | "Customize variable: ") | 364 | "Customize variable: ") |
| 358 | obarray 'boundp t)) | 365 | obarray (lambda (symbol) |
| 366 | (and (boundp symbol) | ||
| 367 | (or (get symbol 'custom-type) | ||
| 368 | (user-variable-p symbol)))))) | ||
| 359 | (list (if (equal val "") | 369 | (list (if (equal val "") |
| 360 | v (intern val))))) | 370 | v (intern val))))) |
| 361 | 371 | ||
| 372 | (defun custom-menu-filter (menu widget) | ||
| 373 | "Convert MENU to the form used by `widget-choose'. | ||
| 374 | MENU should be in the same format as `custom-variable-menu'. | ||
| 375 | WIDGET is the widget to apply the filter entries of MENU on." | ||
| 376 | (let ((result nil) | ||
| 377 | current name action filter) | ||
| 378 | (while menu | ||
| 379 | (setq current (car menu) | ||
| 380 | name (nth 0 current) | ||
| 381 | action (nth 1 current) | ||
| 382 | filter (nth 2 current) | ||
| 383 | menu (cdr menu)) | ||
| 384 | (if (or (null filter) (funcall filter widget)) | ||
| 385 | (push (cons name action) result) | ||
| 386 | (push name result))) | ||
| 387 | (nreverse result))) | ||
| 388 | |||
| 362 | ;;; Unlispify. | 389 | ;;; Unlispify. |
| 363 | 390 | ||
| 364 | (defvar custom-prefix-list nil | 391 | (defvar custom-prefix-list nil |
| @@ -552,6 +579,74 @@ when the action is chosen.") | |||
| 552 | 579 | ||
| 553 | ;;; The Customize Commands | 580 | ;;; The Customize Commands |
| 554 | 581 | ||
| 582 | (defun custom-prompt-variable (prompt-var prompt-val) | ||
| 583 | "Prompt for a variable and a value and return them as a list. | ||
| 584 | PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the | ||
| 585 | prompt for the value. The %s escape in PROMPT-VAL is replaced with | ||
| 586 | the name of the variable. | ||
| 587 | |||
| 588 | If the variable has a `variable-interactive' property, that is used as if | ||
| 589 | it were the arg to `interactive' (which see) to interactively read the value. | ||
| 590 | |||
| 591 | If the variable has a `custom-type' property, it must be a widget and the | ||
| 592 | `:prompt-value' property of that widget will be used for reading the value." | ||
| 593 | (let* ((var (read-variable prompt-var)) | ||
| 594 | (minibuffer-help-form '(describe-variable var))) | ||
| 595 | (list var | ||
| 596 | (let ((prop (get var 'variable-interactive)) | ||
| 597 | (type (get var 'custom-type)) | ||
| 598 | (prompt (format prompt-val var))) | ||
| 599 | (unless (listp type) | ||
| 600 | (setq type (list type))) | ||
| 601 | (cond (prop | ||
| 602 | ;; Use VAR's `variable-interactive' property | ||
| 603 | ;; as an interactive spec for prompting. | ||
| 604 | (call-interactively (list 'lambda '(arg) | ||
| 605 | (list 'interactive prop) | ||
| 606 | 'arg))) | ||
| 607 | (type | ||
| 608 | (widget-prompt-value type | ||
| 609 | prompt | ||
| 610 | (if (boundp var) | ||
| 611 | (symbol-value var)) | ||
| 612 | (not (boundp var)))) | ||
| 613 | (t | ||
| 614 | (eval-minibuffer prompt))))))) | ||
| 615 | |||
| 616 | ;;;###autoload | ||
| 617 | (defun custom-set-value (var val) | ||
| 618 | "Set VARIABLE to VALUE. VALUE is a Lisp object. | ||
| 619 | |||
| 620 | If VARIABLE has a `variable-interactive' property, that is used as if | ||
| 621 | it were the arg to `interactive' (which see) to interactively read the value. | ||
| 622 | |||
| 623 | If VARIABLE has a `custom-type' property, it must be a widget and the | ||
| 624 | `:prompt-value' property of that widget will be used for reading the value." | ||
| 625 | (interactive (custom-prompt-variable "Set variable: " | ||
| 626 | "Set %s to value: ")) | ||
| 627 | |||
| 628 | (set var val)) | ||
| 629 | |||
| 630 | ;;;###autoload | ||
| 631 | (defun custom-set-variable (var val) | ||
| 632 | "Set the default for VARIABLE to VALUE. VALUE is a Lisp object. | ||
| 633 | |||
| 634 | If VARIABLE has a `custom-set' property, that is used for setting | ||
| 635 | VARIABLE, otherwise `set-default' is used. | ||
| 636 | |||
| 637 | The `customized-value' property of the VARIABLE will be set to a list | ||
| 638 | with a quoted VALUE as its sole list member. | ||
| 639 | |||
| 640 | If VARIABLE has a `variable-interactive' property, that is used as if | ||
| 641 | it were the arg to `interactive' (which see) to interactively read the value. | ||
| 642 | |||
| 643 | If VARIABLE has a `custom-type' property, it must be a widget and the | ||
| 644 | `:prompt-value' property of that widget will be used for reading the value. " | ||
| 645 | (interactive (custom-prompt-variable "Set variable: " | ||
| 646 | "Set customized value for %s to: ")) | ||
| 647 | (funcall (or (get var 'custom-set) 'set-default) var val) | ||
| 648 | (put var 'customized-value (list (custom-quote val)))) | ||
| 649 | |||
| 555 | ;;;###autoload | 650 | ;;;###autoload |
| 556 | (defun customize (symbol) | 651 | (defun customize (symbol) |
| 557 | "Customize SYMBOL, which must be a customization group." | 652 | "Customize SYMBOL, which must be a customization group." |
| @@ -568,6 +663,21 @@ when the action is chosen.") | |||
| 568 | (custom-buffer-create (list (list symbol 'custom-group)))) | 663 | (custom-buffer-create (list (list symbol 'custom-group)))) |
| 569 | 664 | ||
| 570 | ;;;###autoload | 665 | ;;;###autoload |
| 666 | (defun customize-other-window (symbol) | ||
| 667 | "Customize SYMBOL, which must be a customization group." | ||
| 668 | (interactive (list (completing-read "Customize group: (default emacs) " | ||
| 669 | obarray | ||
| 670 | (lambda (symbol) | ||
| 671 | (get symbol 'custom-group)) | ||
| 672 | t))) | ||
| 673 | |||
| 674 | (when (stringp symbol) | ||
| 675 | (if (string-equal "" symbol) | ||
| 676 | (setq symbol 'emacs) | ||
| 677 | (setq symbol (intern symbol)))) | ||
| 678 | (custom-buffer-create-other-window (list (list symbol 'custom-group)))) | ||
| 679 | |||
| 680 | ;;;###autoload | ||
| 571 | (defun customize-variable (symbol) | 681 | (defun customize-variable (symbol) |
| 572 | "Customize SYMBOL, which must be a variable." | 682 | "Customize SYMBOL, which must be a variable." |
| 573 | (interactive (custom-variable-prompt)) | 683 | (interactive (custom-variable-prompt)) |
| @@ -617,7 +727,24 @@ If SYMBOL is nil, customize all faces." | |||
| 617 | 727 | ||
| 618 | ;;;###autoload | 728 | ;;;###autoload |
| 619 | (defun customize-customized () | 729 | (defun customize-customized () |
| 620 | "Customize all already customized user options." | 730 | "Customize all user options set since the last save in this session." |
| 731 | (interactive) | ||
| 732 | (let ((found nil)) | ||
| 733 | (mapatoms (lambda (symbol) | ||
| 734 | (and (get symbol 'customized-face) | ||
| 735 | (custom-facep symbol) | ||
| 736 | (setq found (cons (list symbol 'custom-face) found))) | ||
| 737 | (and (get symbol 'customized-value) | ||
| 738 | (boundp symbol) | ||
| 739 | (setq found | ||
| 740 | (cons (list symbol 'custom-variable) found))))) | ||
| 741 | (if found | ||
| 742 | (custom-buffer-create found) | ||
| 743 | (error "No customized user options")))) | ||
| 744 | |||
| 745 | ;;;###autoload | ||
| 746 | (defun customize-saved () | ||
| 747 | "Customize all already saved user options." | ||
| 621 | (interactive) | 748 | (interactive) |
| 622 | (let ((found nil)) | 749 | (let ((found nil)) |
| 623 | (mapatoms (lambda (symbol) | 750 | (mapatoms (lambda (symbol) |
| @@ -630,7 +757,7 @@ If SYMBOL is nil, customize all faces." | |||
| 630 | (cons (list symbol 'custom-variable) found))))) | 757 | (cons (list symbol 'custom-variable) found))))) |
| 631 | (if found | 758 | (if found |
| 632 | (custom-buffer-create found) | 759 | (custom-buffer-create found) |
| 633 | (error "No customized user options")))) | 760 | (error "No saved user options")))) |
| 634 | 761 | ||
| 635 | ;;;###autoload | 762 | ;;;###autoload |
| 636 | (defun customize-apropos (regexp &optional all) | 763 | (defun customize-apropos (regexp &optional all) |
| @@ -657,6 +784,8 @@ user-settable." | |||
| 657 | (custom-buffer-create found) | 784 | (custom-buffer-create found) |
| 658 | (error "No matches")))) | 785 | (error "No matches")))) |
| 659 | 786 | ||
| 787 | ;;; Buffer. | ||
| 788 | |||
| 660 | ;;;###autoload | 789 | ;;;###autoload |
| 661 | (defun custom-buffer-create (options) | 790 | (defun custom-buffer-create (options) |
| 662 | "Create a buffer containing OPTIONS. | 791 | "Create a buffer containing OPTIONS. |
| @@ -667,6 +796,7 @@ that option." | |||
| 667 | (switch-to-buffer (get-buffer-create "*Customization*")) | 796 | (switch-to-buffer (get-buffer-create "*Customization*")) |
| 668 | (custom-buffer-create-internal options)) | 797 | (custom-buffer-create-internal options)) |
| 669 | 798 | ||
| 799 | ;;;###autoload | ||
| 670 | (defun custom-buffer-create-other-window (options) | 800 | (defun custom-buffer-create-other-window (options) |
| 671 | "Create a buffer containing OPTIONS. | 801 | "Create a buffer containing OPTIONS. |
| 672 | OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where | 802 | OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where |
| @@ -758,6 +888,7 @@ Make the modifications default for future sessions." | |||
| 758 | (message "Creating customization setup...") | 888 | (message "Creating customization setup...") |
| 759 | (widget-setup) | 889 | (widget-setup) |
| 760 | (goto-char (point-min)) | 890 | (goto-char (point-min)) |
| 891 | (forward-line 3) ;Kludge: bob is writable in XEmacs. | ||
| 761 | (message "Creating customization buffer...done")) | 892 | (message "Creating customization buffer...done")) |
| 762 | 893 | ||
| 763 | ;;; Modification of Basic Widgets. | 894 | ;;; Modification of Basic Widgets. |
| @@ -939,6 +1070,7 @@ The list should be sorted most significant first." | |||
| 939 | "Show and manipulate state for a customization option." | 1070 | "Show and manipulate state for a customization option." |
| 940 | :format "%v" | 1071 | :format "%v" |
| 941 | :action 'widget-choice-item-action | 1072 | :action 'widget-choice-item-action |
| 1073 | :notify 'ignore | ||
| 942 | :value-get 'ignore | 1074 | :value-get 'ignore |
| 943 | :value-create 'custom-magic-value-create | 1075 | :value-create 'custom-magic-value-create |
| 944 | :value-delete 'widget-children-value-delete) | 1076 | :value-delete 'widget-children-value-delete) |
| @@ -998,15 +1130,7 @@ Change the state of this item." | |||
| 998 | 1130 | ||
| 999 | (defun custom-level-action (widget &optional event) | 1131 | (defun custom-level-action (widget &optional event) |
| 1000 | "Toggle visibility for parent to WIDGET." | 1132 | "Toggle visibility for parent to WIDGET." |
| 1001 | (let* ((parent (widget-get widget :parent)) | 1133 | (custom-toggle-hide (widget-get widget :parent))) |
| 1002 | (state (widget-get parent :custom-state))) | ||
| 1003 | (cond ((memq state '(invalid modified)) | ||
| 1004 | (error "There are unset changes")) | ||
| 1005 | ((eq state 'hidden) | ||
| 1006 | (widget-put parent :custom-state 'unknown)) | ||
| 1007 | (t | ||
| 1008 | (widget-put parent :custom-state 'hidden))) | ||
| 1009 | (custom-redraw parent))) | ||
| 1010 | 1134 | ||
| 1011 | ;;; The `custom' Widget. | 1135 | ;;; The `custom' Widget. |
| 1012 | 1136 | ||
| @@ -1094,14 +1218,20 @@ Change the state of this item." | |||
| 1094 | 1218 | ||
| 1095 | (defun custom-redraw (widget) | 1219 | (defun custom-redraw (widget) |
| 1096 | "Redraw WIDGET with current settings." | 1220 | "Redraw WIDGET with current settings." |
| 1097 | (let ((pos (point)) | 1221 | (let ((line (count-lines (point-min) (point))) |
| 1222 | (column (current-column)) | ||
| 1223 | (pos (point)) | ||
| 1098 | (from (marker-position (widget-get widget :from))) | 1224 | (from (marker-position (widget-get widget :from))) |
| 1099 | (to (marker-position (widget-get widget :to)))) | 1225 | (to (marker-position (widget-get widget :to)))) |
| 1100 | (save-excursion | 1226 | (save-excursion |
| 1101 | (widget-value-set widget (widget-value widget)) | 1227 | (widget-value-set widget (widget-value widget)) |
| 1102 | (custom-redraw-magic widget)) | 1228 | (custom-redraw-magic widget)) |
| 1103 | (when (and (>= pos from) (<= pos to)) | 1229 | (when (and (>= pos from) (<= pos to)) |
| 1104 | (goto-char pos)))) | 1230 | (condition-case nil |
| 1231 | (progn | ||
| 1232 | (goto-line line) | ||
| 1233 | (move-to-column column)) | ||
| 1234 | (error nil))))) | ||
| 1105 | 1235 | ||
| 1106 | (defun custom-redraw-magic (widget) | 1236 | (defun custom-redraw-magic (widget) |
| 1107 | "Redraw WIDGET state with current settings." | 1237 | "Redraw WIDGET state with current settings." |
| @@ -1150,6 +1280,17 @@ Change the state of this item." | |||
| 1150 | "Load all dependencies for WIDGET." | 1280 | "Load all dependencies for WIDGET." |
| 1151 | (custom-load-symbol (widget-value widget))) | 1281 | (custom-load-symbol (widget-value widget))) |
| 1152 | 1282 | ||
| 1283 | (defun custom-toggle-hide (widget) | ||
| 1284 | "Toggle visibility of WIDGET." | ||
| 1285 | (let ((state (widget-get widget :custom-state))) | ||
| 1286 | (cond ((memq state '(invalid modified)) | ||
| 1287 | (error "There are unset changes")) | ||
| 1288 | ((eq state 'hidden) | ||
| 1289 | (widget-put widget :custom-state 'unknown)) | ||
| 1290 | (t | ||
| 1291 | (widget-put widget :custom-state 'hidden))) | ||
| 1292 | (custom-redraw widget))) | ||
| 1293 | |||
| 1153 | ;;; The `custom-variable' Widget. | 1294 | ;;; The `custom-variable' Widget. |
| 1154 | 1295 | ||
| 1155 | (defface custom-variable-sample-face '((t (:underline t))) | 1296 | (defface custom-variable-sample-face '((t (:underline t))) |
| @@ -1203,8 +1344,10 @@ Otherwise, look up symbol in `custom-guess-type-alist'." | |||
| 1203 | (tag (widget-get widget :tag)) | 1344 | (tag (widget-get widget :tag)) |
| 1204 | (type (custom-variable-type symbol)) | 1345 | (type (custom-variable-type symbol)) |
| 1205 | (conv (widget-convert type)) | 1346 | (conv (widget-convert type)) |
| 1347 | (get (or (get symbol 'custom-get) 'default-value)) | ||
| 1348 | (set (or (get symbol 'custom-set) 'set-default)) | ||
| 1206 | (value (if (default-boundp symbol) | 1349 | (value (if (default-boundp symbol) |
| 1207 | (default-value symbol) | 1350 | (funcall get symbol) |
| 1208 | (widget-get conv :value)))) | 1351 | (widget-get conv :value)))) |
| 1209 | ;; If the widget is new, the child determine whether it is hidden. | 1352 | ;; If the widget is new, the child determine whether it is hidden. |
| 1210 | (cond (state) | 1353 | (cond (state) |
| @@ -1234,7 +1377,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'." | |||
| 1234 | ((get symbol 'factory-value) | 1377 | ((get symbol 'factory-value) |
| 1235 | (car (get symbol 'factory-value))) | 1378 | (car (get symbol 'factory-value))) |
| 1236 | ((default-boundp symbol) | 1379 | ((default-boundp symbol) |
| 1237 | (custom-quote (default-value symbol))) | 1380 | (custom-quote (funcall get symbol))) |
| 1238 | (t | 1381 | (t |
| 1239 | (custom-quote (widget-get conv :value)))))) | 1382 | (custom-quote (widget-get conv :value)))))) |
| 1240 | (push (widget-create-child-and-convert | 1383 | (push (widget-create-child-and-convert |
| @@ -1266,8 +1409,9 @@ Otherwise, look up symbol in `custom-guess-type-alist'." | |||
| 1266 | (defun custom-variable-state-set (widget) | 1409 | (defun custom-variable-state-set (widget) |
| 1267 | "Set the state of WIDGET." | 1410 | "Set the state of WIDGET." |
| 1268 | (let* ((symbol (widget-value widget)) | 1411 | (let* ((symbol (widget-value widget)) |
| 1412 | (get (or (get symbol 'custom-get) 'default-value)) | ||
| 1269 | (value (if (default-boundp symbol) | 1413 | (value (if (default-boundp symbol) |
| 1270 | (default-value symbol) | 1414 | (funcall get symbol) |
| 1271 | (widget-get widget :value))) | 1415 | (widget-get widget :value))) |
| 1272 | tmp | 1416 | tmp |
| 1273 | (state (cond ((setq tmp (get symbol 'customized-value)) | 1417 | (state (cond ((setq tmp (get symbol 'customized-value)) |
| @@ -1292,29 +1436,52 @@ Otherwise, look up symbol in `custom-guess-type-alist'." | |||
| 1292 | (widget-put widget :custom-state state))) | 1436 | (widget-put widget :custom-state state))) |
| 1293 | 1437 | ||
| 1294 | (defvar custom-variable-menu | 1438 | (defvar custom-variable-menu |
| 1295 | '(("Edit" . custom-variable-edit) | 1439 | '(("Hide" custom-toggle-hide |
| 1296 | ("Edit Lisp" . custom-variable-edit-lisp) | 1440 | (lambda (widget) |
| 1297 | ("Set" . custom-variable-set) | 1441 | (not (memq (widget-get widget :custom-state) '(modified invalid))))) |
| 1298 | ("Save" . custom-variable-save) | 1442 | ("Edit" custom-variable-edit |
| 1299 | ("Reset to Current" . custom-redraw) | 1443 | (lambda (widget) |
| 1300 | ("Reset to Saved" . custom-variable-reset-saved) | 1444 | (not (eq (widget-get widget :custom-form) 'edit)))) |
| 1301 | ("Reset to Factory Settings" . custom-variable-reset-factory)) | 1445 | ("Edit Lisp" custom-variable-edit-lisp |
| 1446 | (lambda (widget) | ||
| 1447 | (not (eq (widget-get widget :custom-form) 'lisp)))) | ||
| 1448 | ("Set" custom-variable-set | ||
| 1449 | (lambda (widget) | ||
| 1450 | (eq (widget-get widget :custom-state) 'modified))) | ||
| 1451 | ("Save" custom-variable-save | ||
| 1452 | (lambda (widget) | ||
| 1453 | (memq (widget-get widget :custom-state) '(modified set changed rogue)))) | ||
| 1454 | ("Reset to Current" custom-redraw | ||
| 1455 | (lambda (widget) | ||
| 1456 | (and (default-boundp (widget-value widget)) | ||
| 1457 | (memq (widget-get widget :custom-state) '(modified))))) | ||
| 1458 | ("Reset to Saved" custom-variable-reset-saved | ||
| 1459 | (lambda (widget) | ||
| 1460 | (and (get (widget-value widget) 'saved-value) | ||
| 1461 | (memq (widget-get widget :custom-state) | ||
| 1462 | '(modified set changed rogue))))) | ||
| 1463 | ("Reset to Factory Settings" custom-variable-reset-factory | ||
| 1464 | (lambda (widget) | ||
| 1465 | (and (get (widget-value widget) 'factory-value) | ||
| 1466 | (memq (widget-get widget :custom-state) | ||
| 1467 | '(modified set changed saved rogue)))))) | ||
| 1302 | "Alist of actions for the `custom-variable' widget. | 1468 | "Alist of actions for the `custom-variable' widget. |
| 1303 | The key is a string containing the name of the action, the value is a | 1469 | Each entry has the form (NAME ACTION FILTER) where NAME is the name of |
| 1304 | lisp function taking the widget as an element which will be called | 1470 | the menu entry, ACTION is the function to call on the widget when the |
| 1305 | when the action is chosen.") | 1471 | menu is selected, and FILTER is a predicate which takes a `custom-variable' |
| 1472 | widget as an argument, and returns non-nil if ACTION is valid on that | ||
| 1473 | widget. If FILTER is nil, ACTION is always valid.") | ||
| 1306 | 1474 | ||
| 1307 | (defun custom-variable-action (widget &optional event) | 1475 | (defun custom-variable-action (widget &optional event) |
| 1308 | "Show the menu for `custom-variable' WIDGET. | 1476 | "Show the menu for `custom-variable' WIDGET. |
| 1309 | Optional EVENT is the location for the menu." | 1477 | Optional EVENT is the location for the menu." |
| 1310 | (if (eq (widget-get widget :custom-state) 'hidden) | 1478 | (if (eq (widget-get widget :custom-state) 'hidden) |
| 1311 | (progn | 1479 | (custom-toggle-hide widget) |
| 1312 | (widget-put widget :custom-state 'unknown) | ||
| 1313 | (custom-redraw widget)) | ||
| 1314 | (let* ((completion-ignore-case t) | 1480 | (let* ((completion-ignore-case t) |
| 1315 | (answer (widget-choose (custom-unlispify-tag-name | 1481 | (answer (widget-choose (custom-unlispify-tag-name |
| 1316 | (widget-get widget :value)) | 1482 | (widget-get widget :value)) |
| 1317 | custom-variable-menu | 1483 | (custom-menu-filter custom-variable-menu |
| 1484 | widget) | ||
| 1318 | event))) | 1485 | event))) |
| 1319 | (if answer | 1486 | (if answer |
| 1320 | (funcall answer widget))))) | 1487 | (funcall answer widget))))) |
| @@ -1333,32 +1500,34 @@ Optional EVENT is the location for the menu." | |||
| 1333 | 1500 | ||
| 1334 | (defun custom-variable-set (widget) | 1501 | (defun custom-variable-set (widget) |
| 1335 | "Set the current value for the variable being edited by WIDGET." | 1502 | "Set the current value for the variable being edited by WIDGET." |
| 1336 | (let ((form (widget-get widget :custom-form)) | 1503 | (let* ((form (widget-get widget :custom-form)) |
| 1337 | (state (widget-get widget :custom-state)) | 1504 | (state (widget-get widget :custom-state)) |
| 1338 | (child (car (widget-get widget :children))) | 1505 | (child (car (widget-get widget :children))) |
| 1339 | (symbol (widget-value widget)) | 1506 | (symbol (widget-value widget)) |
| 1340 | val) | 1507 | (set (or (get symbol 'custom-set) 'set-default)) |
| 1508 | val) | ||
| 1341 | (cond ((eq state 'hidden) | 1509 | (cond ((eq state 'hidden) |
| 1342 | (error "Cannot set hidden variable.")) | 1510 | (error "Cannot set hidden variable.")) |
| 1343 | ((setq val (widget-apply child :validate)) | 1511 | ((setq val (widget-apply child :validate)) |
| 1344 | (goto-char (widget-get val :from)) | 1512 | (goto-char (widget-get val :from)) |
| 1345 | (error "%s" (widget-get val :error))) | 1513 | (error "%s" (widget-get val :error))) |
| 1346 | ((eq form 'lisp) | 1514 | ((eq form 'lisp) |
| 1347 | (set-default symbol (eval (setq val (widget-value child)))) | 1515 | (funcall set symbol (eval (setq val (widget-value child)))) |
| 1348 | (put symbol 'customized-value (list val))) | 1516 | (put symbol 'customized-value (list val))) |
| 1349 | (t | 1517 | (t |
| 1350 | (set-default symbol (setq val (widget-value child))) | 1518 | (funcall set symbol (setq val (widget-value child))) |
| 1351 | (put symbol 'customized-value (list (custom-quote val))))) | 1519 | (put symbol 'customized-value (list (custom-quote val))))) |
| 1352 | (custom-variable-state-set widget) | 1520 | (custom-variable-state-set widget) |
| 1353 | (custom-redraw-magic widget))) | 1521 | (custom-redraw-magic widget))) |
| 1354 | 1522 | ||
| 1355 | (defun custom-variable-save (widget) | 1523 | (defun custom-variable-save (widget) |
| 1356 | "Set the default value for the variable being edited by WIDGET." | 1524 | "Set the default value for the variable being edited by WIDGET." |
| 1357 | (let ((form (widget-get widget :custom-form)) | 1525 | (let* ((form (widget-get widget :custom-form)) |
| 1358 | (state (widget-get widget :custom-state)) | 1526 | (state (widget-get widget :custom-state)) |
| 1359 | (child (car (widget-get widget :children))) | 1527 | (child (car (widget-get widget :children))) |
| 1360 | (symbol (widget-value widget)) | 1528 | (symbol (widget-value widget)) |
| 1361 | val) | 1529 | (set (or (get symbol 'custom-set) 'set-default)) |
| 1530 | val) | ||
| 1362 | (cond ((eq state 'hidden) | 1531 | (cond ((eq state 'hidden) |
| 1363 | (error "Cannot set hidden variable.")) | 1532 | (error "Cannot set hidden variable.")) |
| 1364 | ((setq val (widget-apply child :validate)) | 1533 | ((setq val (widget-apply child :validate)) |
| @@ -1366,12 +1535,12 @@ Optional EVENT is the location for the menu." | |||
| 1366 | (error "%s" (widget-get val :error))) | 1535 | (error "%s" (widget-get val :error))) |
| 1367 | ((eq form 'lisp) | 1536 | ((eq form 'lisp) |
| 1368 | (put symbol 'saved-value (list (widget-value child))) | 1537 | (put symbol 'saved-value (list (widget-value child))) |
| 1369 | (set-default symbol (eval (widget-value child)))) | 1538 | (funcall set symbol (eval (widget-value child)))) |
| 1370 | (t | 1539 | (t |
| 1371 | (put symbol | 1540 | (put symbol |
| 1372 | 'saved-value (list (custom-quote (widget-value | 1541 | 'saved-value (list (custom-quote (widget-value |
| 1373 | child)))) | 1542 | child)))) |
| 1374 | (set-default symbol (widget-value child)))) | 1543 | (funcall set symbol (widget-value child)))) |
| 1375 | (put symbol 'customized-value nil) | 1544 | (put symbol 'customized-value nil) |
| 1376 | (custom-save-all) | 1545 | (custom-save-all) |
| 1377 | (custom-variable-state-set widget) | 1546 | (custom-variable-state-set widget) |
| @@ -1379,10 +1548,11 @@ Optional EVENT is the location for the menu." | |||
| 1379 | 1548 | ||
| 1380 | (defun custom-variable-reset-saved (widget) | 1549 | (defun custom-variable-reset-saved (widget) |
| 1381 | "Restore the saved value for the variable being edited by WIDGET." | 1550 | "Restore the saved value for the variable being edited by WIDGET." |
| 1382 | (let ((symbol (widget-value widget))) | 1551 | (let* ((symbol (widget-value widget)) |
| 1552 | (set (or (get symbol 'custom-set) 'set-default))) | ||
| 1383 | (if (get symbol 'saved-value) | 1553 | (if (get symbol 'saved-value) |
| 1384 | (condition-case nil | 1554 | (condition-case nil |
| 1385 | (set-default symbol (eval (car (get symbol 'saved-value)))) | 1555 | (funcall set symbol (eval (car (get symbol 'saved-value)))) |
| 1386 | (error nil)) | 1556 | (error nil)) |
| 1387 | (error "No saved value for %s" symbol)) | 1557 | (error "No saved value for %s" symbol)) |
| 1388 | (put symbol 'customized-value nil) | 1558 | (put symbol 'customized-value nil) |
| @@ -1391,9 +1561,10 @@ Optional EVENT is the location for the menu." | |||
| 1391 | 1561 | ||
| 1392 | (defun custom-variable-reset-factory (widget) | 1562 | (defun custom-variable-reset-factory (widget) |
| 1393 | "Restore the factory setting for the variable being edited by WIDGET." | 1563 | "Restore the factory setting for the variable being edited by WIDGET." |
| 1394 | (let ((symbol (widget-value widget))) | 1564 | (let* ((symbol (widget-value widget)) |
| 1565 | (set (or (get symbol 'custom-set) 'set-default))) | ||
| 1395 | (if (get symbol 'factory-value) | 1566 | (if (get symbol 'factory-value) |
| 1396 | (set-default symbol (eval (car (get symbol 'factory-value)))) | 1567 | (funcall set symbol (eval (car (get symbol 'factory-value)))) |
| 1397 | (error "No factory default for %S" symbol)) | 1568 | (error "No factory default for %S" symbol)) |
| 1398 | (put symbol 'customized-value nil) | 1569 | (put symbol 'customized-value nil) |
| 1399 | (when (get symbol 'saved-value) | 1570 | (when (get symbol 'saved-value) |
| @@ -1550,9 +1721,7 @@ Match frames with dark backgrounds.") | |||
| 1550 | 1721 | ||
| 1551 | (defun custom-display-unselected-match (widget value) | 1722 | (defun custom-display-unselected-match (widget value) |
| 1552 | "Non-nil if VALUE is an unselected display specification." | 1723 | "Non-nil if VALUE is an unselected display specification." |
| 1553 | (and (listp value) | 1724 | (not (custom-display-match-frame value (selected-frame)))) |
| 1554 | (eq (length value) 2) | ||
| 1555 | (not (custom-display-match-frame value (selected-frame))))) | ||
| 1556 | 1725 | ||
| 1557 | (define-widget 'custom-face-selected 'group | 1726 | (define-widget 'custom-face-selected 'group |
| 1558 | "Edit the attributes of the selected display in a face specification." | 1727 | "Edit the attributes of the selected display in a face specification." |
| @@ -1600,17 +1769,32 @@ Match frames with dark backgrounds.") | |||
| 1600 | (message "Creating face editor...done"))) | 1769 | (message "Creating face editor...done"))) |
| 1601 | 1770 | ||
| 1602 | (defvar custom-face-menu | 1771 | (defvar custom-face-menu |
| 1603 | '(("Edit Selected" . custom-face-edit-selected) | 1772 | '(("Hide" custom-toggle-hide |
| 1604 | ("Edit All" . custom-face-edit-all) | 1773 | (lambda (widget) |
| 1605 | ("Edit Lisp" . custom-face-edit-lisp) | 1774 | (not (memq (widget-get widget :custom-state) '(modified invalid))))) |
| 1606 | ("Set" . custom-face-set) | 1775 | ("Edit Selected" custom-face-edit-selected |
| 1607 | ("Save" . custom-face-save) | 1776 | (lambda (widget) |
| 1608 | ("Reset to Saved" . custom-face-reset-saved) | 1777 | (not (eq (widget-get widget :custom-form) 'selected)))) |
| 1609 | ("Reset to Factory Setting" . custom-face-reset-factory)) | 1778 | ("Edit All" custom-face-edit-all |
| 1779 | (lambda (widget) | ||
| 1780 | (not (eq (widget-get widget :custom-form) 'all)))) | ||
| 1781 | ("Edit Lisp" custom-face-edit-lisp | ||
| 1782 | (lambda (widget) | ||
| 1783 | (not (eq (widget-get widget :custom-form) 'lisp)))) | ||
| 1784 | ("Set" custom-face-set) | ||
| 1785 | ("Save" custom-face-save) | ||
| 1786 | ("Reset to Saved" custom-face-reset-saved | ||
| 1787 | (lambda (widget) | ||
| 1788 | (get (widget-value widget) 'saved-face))) | ||
| 1789 | ("Reset to Factory Setting" custom-face-reset-factory | ||
| 1790 | (lambda (widget) | ||
| 1791 | (get (widget-value widget) 'factory-face)))) | ||
| 1610 | "Alist of actions for the `custom-face' widget. | 1792 | "Alist of actions for the `custom-face' widget. |
| 1611 | The key is a string containing the name of the action, the value is a | 1793 | Each entry has the form (NAME ACTION FILTER) where NAME is the name of |
| 1612 | lisp function taking the widget as an element which will be called | 1794 | the menu entry, ACTION is the function to call on the widget when the |
| 1613 | when the action is chosen.") | 1795 | menu is selected, and FILTER is a predicate which takes a `custom-face' |
| 1796 | widget as an argument, and returns non-nil if ACTION is valid on that | ||
| 1797 | widget. If FILTER is nil, ACTION is always valid.") | ||
| 1614 | 1798 | ||
| 1615 | (defun custom-face-edit-selected (widget) | 1799 | (defun custom-face-edit-selected (widget) |
| 1616 | "Edit selected attributes of the value of WIDGET." | 1800 | "Edit selected attributes of the value of WIDGET." |
| @@ -1646,13 +1830,13 @@ when the action is chosen.") | |||
| 1646 | "Show the menu for `custom-face' WIDGET. | 1830 | "Show the menu for `custom-face' WIDGET. |
| 1647 | Optional EVENT is the location for the menu." | 1831 | Optional EVENT is the location for the menu." |
| 1648 | (if (eq (widget-get widget :custom-state) 'hidden) | 1832 | (if (eq (widget-get widget :custom-state) 'hidden) |
| 1649 | (progn | 1833 | (custom-toggle-hide widget) |
| 1650 | (widget-put widget :custom-state 'unknown) | ||
| 1651 | (custom-redraw widget)) | ||
| 1652 | (let* ((completion-ignore-case t) | 1834 | (let* ((completion-ignore-case t) |
| 1653 | (symbol (widget-get widget :value)) | 1835 | (symbol (widget-get widget :value)) |
| 1654 | (answer (widget-choose (custom-unlispify-tag-name symbol) | 1836 | (answer (widget-choose (custom-unlispify-tag-name symbol) |
| 1655 | custom-face-menu event))) | 1837 | (custom-menu-filter custom-face-menu |
| 1838 | widget) | ||
| 1839 | event))) | ||
| 1656 | (if answer | 1840 | (if answer |
| 1657 | (funcall answer widget))))) | 1841 | (funcall answer widget))))) |
| 1658 | 1842 | ||
| @@ -1865,27 +2049,44 @@ and so forth. The remaining group tags are shown with | |||
| 1865 | (message "Creating group... done"))))) | 2049 | (message "Creating group... done"))))) |
| 1866 | 2050 | ||
| 1867 | (defvar custom-group-menu | 2051 | (defvar custom-group-menu |
| 1868 | '(("Set" . custom-group-set) | 2052 | '(("Hide" custom-toggle-hide |
| 1869 | ("Save" . custom-group-save) | 2053 | (lambda (widget) |
| 1870 | ("Reset to Current" . custom-group-reset-current) | 2054 | (not (memq (widget-get widget :custom-state) '(modified invalid))))) |
| 1871 | ("Reset to Saved" . custom-group-reset-saved) | 2055 | ("Set" custom-group-set |
| 1872 | ("Reset to Factory" . custom-group-reset-factory)) | 2056 | (lambda (widget) |
| 2057 | (eq (widget-get widget :custom-state) 'modified))) | ||
| 2058 | ("Save" custom-group-save | ||
| 2059 | (lambda (widget) | ||
| 2060 | (memq (widget-get widget :custom-state) '(modified set)))) | ||
| 2061 | ("Reset to Current" custom-group-reset-current | ||
| 2062 | (lambda (widget) | ||
| 2063 | (and (default-boundp (widget-value widget)) | ||
| 2064 | (memq (widget-get widget :custom-state) '(modified))))) | ||
| 2065 | ("Reset to Saved" custom-group-reset-saved | ||
| 2066 | (lambda (widget) | ||
| 2067 | (and (get (widget-value widget) 'saved-value) | ||
| 2068 | (memq (widget-get widget :custom-state) '(modified set))))) | ||
| 2069 | ("Reset to Factory" custom-group-reset-factory | ||
| 2070 | (lambda (widget) | ||
| 2071 | (and (get (widget-value widget) 'factory-value) | ||
| 2072 | (memq (widget-get widget :custom-state) '(modified set saved)))))) | ||
| 1873 | "Alist of actions for the `custom-group' widget. | 2073 | "Alist of actions for the `custom-group' widget. |
| 1874 | The key is a string containing the name of the action, the value is a | 2074 | Each entry has the form (NAME ACTION FILTER) where NAME is the name of |
| 1875 | lisp function taking the widget as an element which will be called | 2075 | the menu entry, ACTION is the function to call on the widget when the |
| 1876 | when the action is chosen.") | 2076 | menu is selected, and FILTER is a predicate which takes a `custom-group' |
| 2077 | widget as an argument, and returns non-nil if ACTION is valid on that | ||
| 2078 | widget. If FILTER is nil, ACTION is always valid.") | ||
| 1877 | 2079 | ||
| 1878 | (defun custom-group-action (widget &optional event) | 2080 | (defun custom-group-action (widget &optional event) |
| 1879 | "Show the menu for `custom-group' WIDGET. | 2081 | "Show the menu for `custom-group' WIDGET. |
| 1880 | Optional EVENT is the location for the menu." | 2082 | Optional EVENT is the location for the menu." |
| 1881 | (if (eq (widget-get widget :custom-state) 'hidden) | 2083 | (if (eq (widget-get widget :custom-state) 'hidden) |
| 1882 | (progn | 2084 | (custom-toggle-hide widget) |
| 1883 | (widget-put widget :custom-state 'unknown) | ||
| 1884 | (custom-redraw widget)) | ||
| 1885 | (let* ((completion-ignore-case t) | 2085 | (let* ((completion-ignore-case t) |
| 1886 | (answer (widget-choose (custom-unlispify-tag-name | 2086 | (answer (widget-choose (custom-unlispify-tag-name |
| 1887 | (widget-get widget :value)) | 2087 | (widget-get widget :value)) |
| 1888 | custom-group-menu | 2088 | (custom-menu-filter custom-group-menu |
| 2089 | widget) | ||
| 1889 | event))) | 2090 | event))) |
| 1890 | (if answer | 2091 | (if answer |
| 1891 | (funcall answer widget))))) | 2092 | (funcall answer widget))))) |
| @@ -1986,17 +2187,26 @@ Leave point at the location of the call, or after the last expression." | |||
| 1986 | (princ "\n")) | 2187 | (princ "\n")) |
| 1987 | (princ "(custom-set-variables") | 2188 | (princ "(custom-set-variables") |
| 1988 | (mapatoms (lambda (symbol) | 2189 | (mapatoms (lambda (symbol) |
| 1989 | (let ((value (get symbol 'saved-value))) | 2190 | (let ((value (get symbol 'saved-value)) |
| 2191 | (requests (get symbol 'custom-requests)) | ||
| 2192 | (now (not (or (get symbol 'factory-value) | ||
| 2193 | (and (not (boundp symbol)) | ||
| 2194 | (not (get symbol 'force-value))))))) | ||
| 1990 | (when value | 2195 | (when value |
| 1991 | (princ "\n '(") | 2196 | (princ "\n '(") |
| 1992 | (princ symbol) | 2197 | (princ symbol) |
| 1993 | (princ " ") | 2198 | (princ " ") |
| 1994 | (prin1 (car value)) | 2199 | (prin1 (car value)) |
| 1995 | (if (or (get symbol 'factory-value) | 2200 | (cond (requests |
| 1996 | (and (not (boundp symbol)) | 2201 | (if now |
| 1997 | (not (get symbol 'force-value)))) | 2202 | (princ " t ") |
| 1998 | (princ ")") | 2203 | (princ " nil ")) |
| 1999 | (princ " t)")))))) | 2204 | (prin1 requests) |
| 2205 | (princ ")")) | ||
| 2206 | (now | ||
| 2207 | (princ " t)")) | ||
| 2208 | (t | ||
| 2209 | (princ ")"))))))) | ||
| 2000 | (princ ")") | 2210 | (princ ")") |
| 2001 | (unless (looking-at "\n") | 2211 | (unless (looking-at "\n") |
| 2002 | (princ "\n"))))) | 2212 | (princ "\n"))))) |
| @@ -2038,6 +2248,22 @@ Leave point at the location of the call, or after the last expression." | |||
| 2038 | (princ "\n"))))) | 2248 | (princ "\n"))))) |
| 2039 | 2249 | ||
| 2040 | ;;;###autoload | 2250 | ;;;###autoload |
| 2251 | (defun custom-save-customized () | ||
| 2252 | "Save all user options which have been set in this session." | ||
| 2253 | (interactive) | ||
| 2254 | (mapatoms (lambda (symbol) | ||
| 2255 | (let ((face (get symbol 'customized-face)) | ||
| 2256 | (value (get symbol 'customized-value))) | ||
| 2257 | (when face | ||
| 2258 | (put symbol 'saved-face face) | ||
| 2259 | (put symbol 'customized-face nil)) | ||
| 2260 | (when value | ||
| 2261 | (put symbol 'saved-value value) | ||
| 2262 | (put symbol 'customized-value nil))))) | ||
| 2263 | ;; We really should update all custom buffers here. | ||
| 2264 | (custom-save-all)) | ||
| 2265 | |||
| 2266 | ;;;###autoload | ||
| 2041 | (defun custom-save-all () | 2267 | (defun custom-save-all () |
| 2042 | "Save all customizations in `custom-file'." | 2268 | "Save all customizations in `custom-file'." |
| 2043 | (custom-save-variables) | 2269 | (custom-save-variables) |
| @@ -2178,7 +2404,7 @@ The format is suitable for use with `easy-menu-define'." | |||
| 2178 | 2404 | ||
| 2179 | (easy-menu-define custom-mode-customize-menu | 2405 | (easy-menu-define custom-mode-customize-menu |
| 2180 | custom-mode-map | 2406 | custom-mode-map |
| 2181 | "Menu used in customization buffers." | 2407 | "Menu used to customize customization buffers." |
| 2182 | (customize-menu-create 'customize)) | 2408 | (customize-menu-create 'customize)) |
| 2183 | 2409 | ||
| 2184 | (easy-menu-define custom-mode-menu | 2410 | (easy-menu-define custom-mode-menu |
diff --git a/lisp/custom.el b/lisp/custom.el index afa5b20ca21..58cc6e3468c 100644 --- a/lisp/custom.el +++ b/lisp/custom.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | ;; | 4 | ;; |
| 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> | 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> |
| 6 | ;; Keywords: help, faces | 6 | ;; Keywords: help, faces |
| 7 | ;; Version: 1.84 | 7 | ;; Version: 1.90 |
| 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. |
| @@ -38,7 +38,9 @@ | |||
| 38 | 38 | ||
| 39 | (require 'widget) | 39 | (require 'widget) |
| 40 | 40 | ||
| 41 | (define-widget-keywords :prefix :tag :load :link :options :type :group) | 41 | (define-widget-keywords :initialize :set :get :require :prefix :tag |
| 42 | :load :link :options :type :group) | ||
| 43 | |||
| 42 | 44 | ||
| 43 | (defvar custom-define-hook nil | 45 | (defvar custom-define-hook nil |
| 44 | ;; Customize information for this option is in `cus-edit.el'. | 46 | ;; Customize information for this option is in `cus-edit.el'. |
| @@ -46,14 +48,62 @@ | |||
| 46 | 48 | ||
| 47 | ;;; The `defcustom' Macro. | 49 | ;;; The `defcustom' Macro. |
| 48 | 50 | ||
| 49 | (defun custom-declare-variable (symbol value doc &rest args) | 51 | (defun custom-initialize-default (symbol value) |
| 50 | "Like `defcustom', but SYMBOL and VALUE are evaluated as normal arguments." | 52 | "Initialize SYMBOL with VALUE. |
| 51 | ;; Bind this variable unless it already is bound. | 53 | This will do nothing if symbol already has a default binding. |
| 54 | Otherwise, if symbol has a `saved-value' property, it will evaluate | ||
| 55 | the car of that and used as the default binding for symbol. | ||
| 56 | Otherwise, VALUE will be evaluated and used as the default binding for | ||
| 57 | symbol." | ||
| 52 | (unless (default-boundp symbol) | 58 | (unless (default-boundp symbol) |
| 53 | ;; Use the saved value if it exists, otherwise the factory setting. | 59 | ;; Use the saved value if it exists, otherwise the factory setting. |
| 54 | (set-default symbol (if (get symbol 'saved-value) | 60 | (set-default symbol (if (get symbol 'saved-value) |
| 55 | (eval (car (get symbol 'saved-value))) | 61 | (eval (car (get symbol 'saved-value))) |
| 56 | (eval value)))) | 62 | (eval value))))) |
| 63 | |||
| 64 | (defun custom-initialize-set (symbol value) | ||
| 65 | "Initialize SYMBOL with VALUE. | ||
| 66 | Like `custom-initialize-default', but use the function specified by | ||
| 67 | `:set' to initialize SYMBOL." | ||
| 68 | (unless (default-boundp symbol) | ||
| 69 | (funcall (or (get symbol 'custom-set) 'set-default) | ||
| 70 | symbol | ||
| 71 | (if (get symbol 'saved-value) | ||
| 72 | (eval (car (get symbol 'saved-value))) | ||
| 73 | (eval value))))) | ||
| 74 | |||
| 75 | (defun custom-initialize-reset (symbol value) | ||
| 76 | "Initialize SYMBOL with VALUE. | ||
| 77 | Like `custom-initialize-set', but use the function specified by | ||
| 78 | `:get' to reinitialize SYMBOL if it is already bound." | ||
| 79 | (funcall (or (get symbol 'custom-set) 'set-default) | ||
| 80 | symbol | ||
| 81 | (cond ((default-boundp symbol) | ||
| 82 | (funcall (or (get symbol 'custom-get) 'default-value) | ||
| 83 | symbol)) | ||
| 84 | ((get symbol 'saved-value) | ||
| 85 | (eval (car (get symbol 'saved-value)))) | ||
| 86 | (t | ||
| 87 | (eval value))))) | ||
| 88 | |||
| 89 | (defun custom-initialize-changed (symbol value) | ||
| 90 | "Initialize SYMBOL with VALUE. | ||
| 91 | Like `custom-initialize-reset', but only use the `:set' function if the | ||
| 92 | not using the factory setting. Otherwise, use the `set-default'." | ||
| 93 | (cond ((default-boundp symbol) | ||
| 94 | (funcall (or (get symbol 'custom-set) 'set-default) | ||
| 95 | symbol | ||
| 96 | (funcall (or (get symbol 'custom-get) 'default-value) | ||
| 97 | symbol))) | ||
| 98 | ((get symbol 'saved-value) | ||
| 99 | (funcall (or (get symbol 'custom-set) 'set-default) | ||
| 100 | symbol | ||
| 101 | (eval (car (get symbol 'saved-value))))) | ||
| 102 | (t | ||
| 103 | (set-default symbol (eval value))))) | ||
| 104 | |||
| 105 | (defun custom-declare-variable (symbol value doc &rest args) | ||
| 106 | "Like `defcustom', but SYMBOL and VALUE are evaluated as normal arguments." | ||
| 57 | ;; Remember the factory setting. | 107 | ;; Remember the factory setting. |
| 58 | (put symbol 'factory-value (list value)) | 108 | (put symbol 'factory-value (list value)) |
| 59 | ;; Maybe this option was rogue in an earlier version. It no longer is. | 109 | ;; Maybe this option was rogue in an earlier version. It no longer is. |
| @@ -62,29 +112,42 @@ | |||
| 62 | (put symbol 'force-value nil)) | 112 | (put symbol 'force-value nil)) |
| 63 | (when doc | 113 | (when doc |
| 64 | (put symbol 'variable-documentation doc)) | 114 | (put symbol 'variable-documentation doc)) |
| 65 | (while args | 115 | (let ((initialize 'custom-initialize-set) |
| 66 | (let ((arg (car args))) | 116 | (requests nil)) |
| 67 | (setq args (cdr args)) | 117 | (while args |
| 68 | (unless (symbolp arg) | 118 | (let ((arg (car args))) |
| 69 | (error "Junk in args %S" args)) | ||
| 70 | (let ((keyword arg) | ||
| 71 | (value (car args))) | ||
| 72 | (unless args | ||
| 73 | (error "Keyword %s is missing an argument" keyword)) | ||
| 74 | (setq args (cdr args)) | 119 | (setq args (cdr args)) |
| 75 | (cond ((eq keyword :type) | 120 | (unless (symbolp arg) |
| 76 | (put symbol 'custom-type value)) | 121 | (error "Junk in args %S" args)) |
| 77 | ((eq keyword :options) | 122 | (let ((keyword arg) |
| 78 | (if (get symbol 'custom-options) | 123 | (value (car args))) |
| 79 | ;; Slow safe code to avoid duplicates. | 124 | (unless args |
| 80 | (mapcar (lambda (option) | 125 | (error "Keyword %s is missing an argument" keyword)) |
| 81 | (custom-add-option symbol option)) | 126 | (setq args (cdr args)) |
| 82 | value) | 127 | (cond ((eq keyword :initialize) |
| 83 | ;; Fast code for the common case. | 128 | (setq initialize value)) |
| 84 | (put symbol 'custom-options (copy-sequence value)))) | 129 | ((eq keyword :set) |
| 85 | (t | 130 | (put symbol 'custom-set value)) |
| 86 | (custom-handle-keyword symbol keyword value | 131 | ((eq keyword :get) |
| 87 | 'custom-variable)))))) | 132 | (put symbol 'custom-get value)) |
| 133 | ((eq keyword :require) | ||
| 134 | (push value requests)) | ||
| 135 | ((eq keyword :type) | ||
| 136 | (put symbol 'custom-type value)) | ||
| 137 | ((eq keyword :options) | ||
| 138 | (if (get symbol 'custom-options) | ||
| 139 | ;; Slow safe code to avoid duplicates. | ||
| 140 | (mapcar (lambda (option) | ||
| 141 | (custom-add-option symbol option)) | ||
| 142 | value) | ||
| 143 | ;; Fast code for the common case. | ||
| 144 | (put symbol 'custom-options (copy-sequence value)))) | ||
| 145 | (t | ||
| 146 | (custom-handle-keyword symbol keyword value | ||
| 147 | 'custom-variable)))))) | ||
| 148 | (put symbol 'custom-requests requests) | ||
| 149 | ;; Do the actual initialization. | ||
| 150 | (funcall initialize symbol value)) | ||
| 88 | (run-hooks 'custom-define-hook) | 151 | (run-hooks 'custom-define-hook) |
| 89 | symbol) | 152 | symbol) |
| 90 | 153 | ||
| @@ -100,10 +163,25 @@ The remaining arguments should have the form | |||
| 100 | 163 | ||
| 101 | The following KEYWORD's are defined: | 164 | The following KEYWORD's are defined: |
| 102 | 165 | ||
| 103 | :type VALUE should be a widget type. | 166 | :type VALUE should be a widget type for editing the symbols value. |
| 167 | The default is `sexp'. | ||
| 104 | :options VALUE should be a list of valid members of the widget type. | 168 | :options VALUE should be a list of valid members of the widget type. |
| 105 | :group VALUE should be a customization group. | 169 | :group VALUE should be a customization group. |
| 106 | Add SYMBOL to that group. | 170 | Add SYMBOL to that group. |
| 171 | :initialize VALUE should be a function used to initialize the | ||
| 172 | variable. It takes two arguments, the symbol and value | ||
| 173 | given in the `defcustom' call. The default is | ||
| 174 | `custom-initialize-default' | ||
| 175 | :set VALUE should be a function to set the value of the symbol. | ||
| 176 | It takes two arguments, the symbol to set and the value to | ||
| 177 | give it. The default is `set-default'. | ||
| 178 | :get VALUE should be a function to extract the value of symbol. | ||
| 179 | The function takes one argument, a symbol, and should return | ||
| 180 | the current value for that symbol. The default is | ||
| 181 | `default-value'. | ||
| 182 | :require VALUE should be a feature symbol. Each feature will be | ||
| 183 | required after initialization, of the the user have saved this | ||
| 184 | option. | ||
| 107 | 185 | ||
| 108 | Read the section about customization in the Emacs Lisp manual for more | 186 | Read the section about customization in the Emacs Lisp manual for more |
| 109 | information." | 187 | information." |
| @@ -163,6 +241,9 @@ information." | |||
| 163 | 241 | ||
| 164 | (defun custom-declare-group (symbol members doc &rest args) | 242 | (defun custom-declare-group (symbol members doc &rest args) |
| 165 | "Like `defgroup', but SYMBOL is evaluated as a normal argument." | 243 | "Like `defgroup', but SYMBOL is evaluated as a normal argument." |
| 244 | (while members | ||
| 245 | (apply 'custom-add-to-group symbol (car members)) | ||
| 246 | (setq members (cdr members))) | ||
| 166 | (put symbol 'custom-group (nconc members (get symbol 'custom-group))) | 247 | (put symbol 'custom-group (nconc members (get symbol 'custom-group))) |
| 167 | (when doc | 248 | (when doc |
| 168 | (put symbol 'group-documentation doc)) | 249 | (put symbol 'group-documentation doc)) |
| @@ -285,17 +366,22 @@ the default value for the SYMBOL." | |||
| 285 | (while args | 366 | (while args |
| 286 | (let ((entry (car args))) | 367 | (let ((entry (car args))) |
| 287 | (if (listp entry) | 368 | (if (listp entry) |
| 288 | (let ((symbol (nth 0 entry)) | 369 | (let* ((symbol (nth 0 entry)) |
| 289 | (value (nth 1 entry)) | 370 | (value (nth 1 entry)) |
| 290 | (now (nth 2 entry))) | 371 | (now (nth 2 entry)) |
| 372 | (requests (nth 3 entry)) | ||
| 373 | (set (or (get symbol 'custom-set) 'set-default))) | ||
| 291 | (put symbol 'saved-value (list value)) | 374 | (put symbol 'saved-value (list value)) |
| 292 | (cond (now | 375 | (cond (now |
| 293 | ;; Rogue variable, set it now. | 376 | ;; Rogue variable, set it now. |
| 294 | (put symbol 'force-value t) | 377 | (put symbol 'force-value t) |
| 295 | (set-default symbol (eval value))) | 378 | (funcall set symbol (eval value))) |
| 296 | ((default-boundp symbol) | 379 | ((default-boundp symbol) |
| 297 | ;; Something already set this, overwrite it. | 380 | ;; Something already set this, overwrite it. |
| 298 | (set-default symbol (eval value)))) | 381 | (funcall set symbol (eval value)))) |
| 382 | (when requests | ||
| 383 | (put symbol 'custom-requests requests) | ||
| 384 | (mapcar 'require requests)) | ||
| 299 | (setq args (cdr args))) | 385 | (setq args (cdr args))) |
| 300 | ;; Old format, a plist of SYMBOL VALUE pairs. | 386 | ;; Old format, a plist of SYMBOL VALUE pairs. |
| 301 | (message "Warning: old format `custom-set-variables'") | 387 | (message "Warning: old format `custom-set-variables'") |
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el index f656a3b9020..984d802f75b 100644 --- a/lisp/wid-browse.el +++ b/lisp/wid-browse.el | |||
| @@ -4,7 +4,7 @@ | |||
| 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.84 | 7 | ;; Version: 1.90 |
| 8 | ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ | 8 | ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ |
| 9 | 9 | ||
| 10 | ;;; Commentary: | 10 | ;;; Commentary: |
| @@ -16,7 +16,7 @@ | |||
| 16 | (require 'easymenu) | 16 | (require 'easymenu) |
| 17 | (require 'custom) | 17 | (require 'custom) |
| 18 | (require 'wid-edit) | 18 | (require 'wid-edit) |
| 19 | (require 'cl) | 19 | (eval-when-compile (require 'cl)) |
| 20 | 20 | ||
| 21 | (defgroup widget-browse nil | 21 | (defgroup widget-browse nil |
| 22 | "Customization support for browsing widgets." | 22 | "Customization support for browsing widgets." |
| @@ -245,6 +245,37 @@ VALUE is assumed to be a list of widgets." | |||
| 245 | (put :button 'widget-keyword-printer 'widget-browse-widget) | 245 | (put :button 'widget-keyword-printer 'widget-browse-widget) |
| 246 | (put :args 'widget-keyword-printer 'widget-browse-sexps) | 246 | (put :args 'widget-keyword-printer 'widget-browse-sexps) |
| 247 | 247 | ||
| 248 | ;;; Widget Minor Mode. | ||
| 249 | |||
| 250 | (defvar widget-minor-mode nil | ||
| 251 | "I non-nil, we are in Widget Minor Mode.") | ||
| 252 | (make-variable-buffer-local 'widget-minor-mode) | ||
| 253 | |||
| 254 | (defvar widget-minor-mode-map nil | ||
| 255 | "Keymap used in Widget Minor Mode.") | ||
| 256 | |||
| 257 | (unless widget-minor-mode-map | ||
| 258 | (setq widget-minor-mode-map (make-sparse-keymap)) | ||
| 259 | (set-keymap-parent widget-minor-mode-map widget-keymap)) | ||
| 260 | |||
| 261 | ;;;###autoload | ||
| 262 | (defun widget-minor-mode (&optional arg) | ||
| 263 | "Togle minor mode for traversing widgets. | ||
| 264 | With arg, turn widget mode on if and only if arg is positive." | ||
| 265 | (interactive "P") | ||
| 266 | (cond ((null arg) | ||
| 267 | (setq widget-minor-mode (not widget-minor-mode))) | ||
| 268 | ((<= 0 arg) | ||
| 269 | (setq widget-minor-mode nil)) | ||
| 270 | (t | ||
| 271 | (setq widget-minor-mode t))) | ||
| 272 | (force-mode-line-update)) | ||
| 273 | |||
| 274 | (add-to-list 'minor-mode-alist '(widget-minor-mode " Widget")) | ||
| 275 | |||
| 276 | (add-to-list 'minor-mode-map-alist | ||
| 277 | (cons 'widget-minor-mode widget-minor-mode-map)) | ||
| 278 | |||
| 248 | ;;; The End: | 279 | ;;; The End: |
| 249 | 280 | ||
| 250 | (provide 'wid-browse) | 281 | (provide 'wid-browse) |
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 62b0274676d..555ab181f1a 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el | |||
| @@ -4,7 +4,7 @@ | |||
| 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.84 | 7 | ;; Version: 1.90 |
| 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. |
| @@ -32,8 +32,7 @@ | |||
| 32 | 32 | ||
| 33 | (require 'widget) | 33 | (require 'widget) |
| 34 | 34 | ||
| 35 | (eval-when-compile | 35 | (eval-when-compile (require 'cl)) |
| 36 | (require 'cl)) | ||
| 37 | 36 | ||
| 38 | ;;; Compatibility. | 37 | ;;; Compatibility. |
| 39 | 38 | ||
| @@ -75,7 +74,7 @@ and `end-open' if it should sticky to the front." | |||
| 75 | ;; We have the old custom-library, hack around it! | 74 | ;; We have the old custom-library, hack around it! |
| 76 | (defmacro defgroup (&rest args) nil) | 75 | (defmacro defgroup (&rest args) nil) |
| 77 | (defmacro defcustom (var value doc &rest args) | 76 | (defmacro defcustom (var value doc &rest args) |
| 78 | `(defvar ,var ,value ,doc)) | 77 | (` (defvar (, var) (, value) (, doc)))) |
| 79 | (defmacro defface (&rest args) nil) | 78 | (defmacro defface (&rest args) nil) |
| 80 | (define-widget-keywords :prefix :tag :load :link :options :type :group) | 79 | (define-widget-keywords :prefix :tag :load :link :options :type :group) |
| 81 | (when (fboundp 'copy-face) | 80 | (when (fboundp 'copy-face) |
| @@ -134,7 +133,7 @@ into the buffer visible in the event's window." | |||
| 134 | 133 | ||
| 135 | (defface widget-field-face '((((class grayscale color) | 134 | (defface widget-field-face '((((class grayscale color) |
| 136 | (background light)) | 135 | (background light)) |
| 137 | (:background "light gray")) | 136 | (:background "gray85")) |
| 138 | (((class grayscale color) | 137 | (((class grayscale color) |
| 139 | (background dark)) | 138 | (background dark)) |
| 140 | (:background "dark gray")) | 139 | (:background "dark gray")) |
| @@ -184,7 +183,9 @@ Larger menus are read through the minibuffer." | |||
| 184 | "Choose an item from a list. | 183 | "Choose an item from a list. |
| 185 | 184 | ||
| 186 | First argument TITLE is the name of the list. | 185 | First argument TITLE is the name of the list. |
| 187 | Second argument ITEMS is an alist (NAME . VALUE). | 186 | Second argument ITEMS is an list whose members are either |
| 187 | (NAME . VALUE), to indicate selectable items, or just strings to | ||
| 188 | indicate unselectable items. | ||
| 188 | Optional third argument EVENT is an input event. | 189 | Optional third argument EVENT is an input event. |
| 189 | 190 | ||
| 190 | The user is asked to choose between each NAME from the items alist, | 191 | The user is asked to choose between each NAME from the items alist, |
| @@ -205,7 +206,9 @@ minibuffer." | |||
| 205 | (mapcar | 206 | (mapcar |
| 206 | (function | 207 | (function |
| 207 | (lambda (x) | 208 | (lambda (x) |
| 208 | (vector (car x) (list (car x)) t))) | 209 | (if (stringp x) |
| 210 | (vector x nil nil) | ||
| 211 | (vector (car x) (list (car x)) t)))) | ||
| 209 | items))))) | 212 | items))))) |
| 210 | (setq val (and val | 213 | (setq val (and val |
| 211 | (listp (event-object val)) | 214 | (listp (event-object val)) |
| @@ -213,6 +216,7 @@ minibuffer." | |||
| 213 | (car (event-object val)))) | 216 | (car (event-object val)))) |
| 214 | (cdr (assoc val items)))) | 217 | (cdr (assoc val items)))) |
| 215 | (t | 218 | (t |
| 219 | (setq items (remove-if 'stringp items)) | ||
| 216 | (let ((val (completing-read (concat title ": ") items nil t))) | 220 | (let ((val (completing-read (concat title ": ") items nil t))) |
| 217 | (if (stringp val) | 221 | (if (stringp val) |
| 218 | (let ((try (try-completion val items))) | 222 | (let ((try (try-completion val items))) |
| @@ -235,6 +239,22 @@ This is only meaningful for radio buttons or checkboxes in a list." | |||
| 235 | (throw 'child child))) | 239 | (throw 'child child))) |
| 236 | nil))) | 240 | nil))) |
| 237 | 241 | ||
| 242 | ;;; Helper functions. | ||
| 243 | ;; | ||
| 244 | ;; These are widget specific. | ||
| 245 | |||
| 246 | ;;;###autoload | ||
| 247 | (defun widget-prompt-value (widget prompt &optional value unbound) | ||
| 248 | "Prompt for a value matching WIDGET, using PROMPT. | ||
| 249 | The current value is assumed to be VALUE, unless UNBOUND is non-nil." | ||
| 250 | (unless (listp widget) | ||
| 251 | (setq widget (list widget))) | ||
| 252 | (setq widget (widget-convert widget)) | ||
| 253 | (let ((answer (widget-apply widget :prompt-value prompt value unbound))) | ||
| 254 | (unless (widget-apply widget :match answer) | ||
| 255 | (error "Value does not match %S type." (car widget))) | ||
| 256 | answer)) | ||
| 257 | |||
| 238 | ;;; Widget text specifications. | 258 | ;;; Widget text specifications. |
| 239 | ;; | 259 | ;; |
| 240 | ;; These functions are for specifying text properties. | 260 | ;; These functions are for specifying text properties. |
| @@ -388,7 +408,8 @@ This is only meaningful for radio buttons or checkboxes in a list." | |||
| 388 | 408 | ||
| 389 | (defmacro widget-specify-insert (&rest form) | 409 | (defmacro widget-specify-insert (&rest form) |
| 390 | ;; Execute FORM without inheriting any text properties. | 410 | ;; Execute FORM without inheriting any text properties. |
| 391 | `(save-restriction | 411 | (` |
| 412 | (save-restriction | ||
| 392 | (let ((inhibit-read-only t) | 413 | (let ((inhibit-read-only t) |
| 393 | result | 414 | result |
| 394 | after-change-functions) | 415 | after-change-functions) |
| @@ -396,11 +417,11 @@ This is only meaningful for radio buttons or checkboxes in a list." | |||
| 396 | (narrow-to-region (- (point) 2) (point)) | 417 | (narrow-to-region (- (point) 2) (point)) |
| 397 | (widget-specify-none (point-min) (point-max)) | 418 | (widget-specify-none (point-min) (point-max)) |
| 398 | (goto-char (1+ (point-min))) | 419 | (goto-char (1+ (point-min))) |
| 399 | (setq result (progn ,@form)) | 420 | (setq result (progn (,@ form))) |
| 400 | (delete-region (point-min) (1+ (point-min))) | 421 | (delete-region (point-min) (1+ (point-min))) |
| 401 | (delete-region (1- (point-max)) (point-max)) | 422 | (delete-region (1- (point-max)) (point-max)) |
| 402 | (goto-char (point-max)) | 423 | (goto-char (point-max)) |
| 403 | result))) | 424 | result)))) |
| 404 | 425 | ||
| 405 | (defface widget-inactive-face '((((class grayscale color) | 426 | (defface widget-inactive-face '((((class grayscale color) |
| 406 | (background dark)) | 427 | (background dark)) |
| @@ -418,7 +439,8 @@ This is only meaningful for radio buttons or checkboxes in a list." | |||
| 418 | (unless (widget-get widget :inactive) | 439 | (unless (widget-get widget :inactive) |
| 419 | (let ((overlay (make-overlay from to nil t nil))) | 440 | (let ((overlay (make-overlay from to nil t nil))) |
| 420 | (overlay-put overlay 'face 'widget-inactive-face) | 441 | (overlay-put overlay 'face 'widget-inactive-face) |
| 421 | (overlay-put overlay 'evaporate 't) | 442 | (overlay-put overlay 'evaporate t) |
| 443 | (overlay-put overlay 'priority 100) | ||
| 422 | (overlay-put overlay (if (string-match "XEmacs" emacs-version) | 444 | (overlay-put overlay (if (string-match "XEmacs" emacs-version) |
| 423 | 'read-only | 445 | 'read-only |
| 424 | 'modification-hooks) '(widget-overlay-inactive)) | 446 | 'modification-hooks) '(widget-overlay-inactive)) |
| @@ -503,7 +525,7 @@ ARGS are passed as extra arguments to the function." | |||
| 503 | (if (widget-apply widget :active) | 525 | (if (widget-apply widget :active) |
| 504 | (widget-apply widget :action event) | 526 | (widget-apply widget :action event) |
| 505 | (error "Attempt to perform action on inactive widget"))) | 527 | (error "Attempt to perform action on inactive widget"))) |
| 506 | 528 | ||
| 507 | ;;; Glyphs. | 529 | ;;; Glyphs. |
| 508 | 530 | ||
| 509 | (defcustom widget-glyph-directory (concat data-directory "custom/") | 531 | (defcustom widget-glyph-directory (concat data-directory "custom/") |
| @@ -800,8 +822,9 @@ ARG may be negative to move backward." | |||
| 800 | (t | 822 | (t |
| 801 | (error "No buttons or fields found")))))) | 823 | (error "No buttons or fields found")))))) |
| 802 | (setq button (widget-at (point))) | 824 | (setq button (widget-at (point))) |
| 803 | (if (and button (widget-get button :tab-order) | 825 | (if (or (and button (widget-get button :tab-order) |
| 804 | (< (widget-get button :tab-order) 0)) | 826 | (< (widget-get button :tab-order) 0)) |
| 827 | (and button (not (widget-apply button :active)))) | ||
| 805 | (setq arg (1+ arg)))))) | 828 | (setq arg (1+ arg)))))) |
| 806 | (while (< arg 0) | 829 | (while (< arg 0) |
| 807 | (if (= (point-min) (point)) | 830 | (if (= (point-min) (point)) |
| @@ -838,8 +861,9 @@ ARG may be negative to move backward." | |||
| 838 | (button (goto-char button)) | 861 | (button (goto-char button)) |
| 839 | (field (goto-char field))) | 862 | (field (goto-char field))) |
| 840 | (setq button (widget-at (point))) | 863 | (setq button (widget-at (point))) |
| 841 | (if (and button (widget-get button :tab-order) | 864 | (if (or (and button (widget-get button :tab-order) |
| 842 | (< (widget-get button :tab-order) 0)) | 865 | (< (widget-get button :tab-order) 0)) |
| 866 | (and button (not (widget-apply button :active)))) | ||
| 843 | (setq arg (1- arg))))) | 867 | (setq arg (1- arg))))) |
| 844 | (widget-echo-help (point)) | 868 | (widget-echo-help (point)) |
| 845 | (run-hooks 'widget-move-hook)) | 869 | (run-hooks 'widget-move-hook)) |
| @@ -1016,7 +1040,8 @@ With optional ARG, move across that many fields." | |||
| 1016 | :activate 'widget-specify-active | 1040 | :activate 'widget-specify-active |
| 1017 | :deactivate 'widget-default-deactivate | 1041 | :deactivate 'widget-default-deactivate |
| 1018 | :action 'widget-default-action | 1042 | :action 'widget-default-action |
| 1019 | :notify 'widget-default-notify) | 1043 | :notify 'widget-default-notify |
| 1044 | :prompt-value 'widget-default-prompt-value) | ||
| 1020 | 1045 | ||
| 1021 | (defun widget-default-create (widget) | 1046 | (defun widget-default-create (widget) |
| 1022 | "Create WIDGET at point in the current buffer." | 1047 | "Create WIDGET at point in the current buffer." |
| @@ -1087,7 +1112,8 @@ With optional ARG, move across that many fields." | |||
| 1087 | (set-marker-insertion-type from t) | 1112 | (set-marker-insertion-type from t) |
| 1088 | (set-marker-insertion-type to nil) | 1113 | (set-marker-insertion-type to nil) |
| 1089 | (widget-put widget :from from) | 1114 | (widget-put widget :from from) |
| 1090 | (widget-put widget :to to)))) | 1115 | (widget-put widget :to to))) |
| 1116 | (widget-clear-undo)) | ||
| 1091 | 1117 | ||
| 1092 | (defun widget-default-format-handler (widget escape) | 1118 | (defun widget-default-format-handler (widget escape) |
| 1093 | ;; We recognize the %h escape by default. | 1119 | ;; We recognize the %h escape by default. |
| @@ -1149,7 +1175,8 @@ With optional ARG, move across that many fields." | |||
| 1149 | ;; Kludge: this doesn't need to be true for empty formats. | 1175 | ;; Kludge: this doesn't need to be true for empty formats. |
| 1150 | (delete-region from to)) | 1176 | (delete-region from to)) |
| 1151 | (set-marker from nil) | 1177 | (set-marker from nil) |
| 1152 | (set-marker to nil))) | 1178 | (set-marker to nil)) |
| 1179 | (widget-clear-undo)) | ||
| 1153 | 1180 | ||
| 1154 | (defun widget-default-value-set (widget value) | 1181 | (defun widget-default-value-set (widget value) |
| 1155 | ;; Recreate widget with new value. | 1182 | ;; Recreate widget with new value. |
| @@ -1194,6 +1221,14 @@ With optional ARG, move across that many fields." | |||
| 1194 | ;; Pass notification to parent. | 1221 | ;; Pass notification to parent. |
| 1195 | (widget-default-action widget event)) | 1222 | (widget-default-action widget event)) |
| 1196 | 1223 | ||
| 1224 | (defun widget-default-prompt-value (widget prompt value unbound) | ||
| 1225 | ;; Read an arbitrary value. Stolen from `set-variable'. | ||
| 1226 | ;; (let ((initial (if unbound | ||
| 1227 | ;; nil | ||
| 1228 | ;; ;; It would be nice if we could do a `(cons val 1)' here. | ||
| 1229 | ;; (prin1-to-string (custom-quote value)))))) | ||
| 1230 | (eval-minibuffer prompt )) | ||
| 1231 | |||
| 1197 | ;;; The `item' Widget. | 1232 | ;;; The `item' Widget. |
| 1198 | 1233 | ||
| 1199 | (define-widget 'item 'default | 1234 | (define-widget 'item 'default |
| @@ -1297,7 +1332,17 @@ With optional ARG, move across that many fields." | |||
| 1297 | 1332 | ||
| 1298 | (defun widget-info-link-action (widget &optional event) | 1333 | (defun widget-info-link-action (widget &optional event) |
| 1299 | "Open the info node specified by WIDGET." | 1334 | "Open the info node specified by WIDGET." |
| 1300 | (Info-goto-node (widget-value widget))) | 1335 | (Info-goto-node (widget-value widget)) |
| 1336 | ;; Steal button release event. | ||
| 1337 | (if (and (fboundp 'button-press-event-p) | ||
| 1338 | (fboundp 'next-command-event)) | ||
| 1339 | ;; XEmacs | ||
| 1340 | (and event | ||
| 1341 | (button-press-event-p event) | ||
| 1342 | (next-command-event)) | ||
| 1343 | ;; Emacs | ||
| 1344 | (when (memq 'down (event-modifiers event)) | ||
| 1345 | (read-event)))) | ||
| 1301 | 1346 | ||
| 1302 | ;;; The `url-link' Widget. | 1347 | ;;; The `url-link' Widget. |
| 1303 | 1348 | ||
| @@ -1507,11 +1552,8 @@ With optional ARG, move across that many fields." | |||
| 1507 | (widget-value-set widget | 1552 | (widget-value-set widget |
| 1508 | (widget-apply current :value-to-external | 1553 | (widget-apply current :value-to-external |
| 1509 | (widget-get current :value))) | 1554 | (widget-get current :value))) |
| 1510 | (widget-apply widget :notify widget event) | 1555 | (widget-apply widget :notify widget event) |
| 1511 | (widget-setup))) | 1556 | (widget-setup)))) |
| 1512 | ;; Notify parent. | ||
| 1513 | (widget-apply widget :notify widget event) | ||
| 1514 | (widget-clear-undo)) | ||
| 1515 | 1557 | ||
| 1516 | (defun widget-choice-validate (widget) | 1558 | (defun widget-choice-validate (widget) |
| 1517 | ;; Valid if we have made a valid choice. | 1559 | ;; Valid if we have made a valid choice. |
| @@ -1567,7 +1609,7 @@ With optional ARG, move across that many fields." | |||
| 1567 | ;; Toggle value. | 1609 | ;; Toggle value. |
| 1568 | (widget-value-set widget (not (widget-value widget))) | 1610 | (widget-value-set widget (not (widget-value widget))) |
| 1569 | (widget-apply widget :notify widget event)) | 1611 | (widget-apply widget :notify widget event)) |
| 1570 | 1612 | ||
| 1571 | ;;; The `checkbox' Widget. | 1613 | ;;; The `checkbox' Widget. |
| 1572 | 1614 | ||
| 1573 | (define-widget 'checkbox 'toggle | 1615 | (define-widget 'checkbox 'toggle |
| @@ -2222,9 +2264,14 @@ With optional ARG, move across that many fields." | |||
| 2222 | 2264 | ||
| 2223 | (define-widget 'const 'item | 2265 | (define-widget 'const 'item |
| 2224 | "An immutable sexp." | 2266 | "An immutable sexp." |
| 2267 | :prompt-value 'widget-const-prompt-value | ||
| 2225 | :format "%t\n%d") | 2268 | :format "%t\n%d") |
| 2226 | 2269 | ||
| 2227 | (define-widget 'function-item 'item | 2270 | (defun widget-const-prompt-value (widget prompt value unbound) |
| 2271 | ;; Return the value of the const. | ||
| 2272 | (widget-value widget)) | ||
| 2273 | |||
| 2274 | (define-widget 'function-item 'const | ||
| 2228 | "An immutable function name." | 2275 | "An immutable function name." |
| 2229 | :format "%v\n%h" | 2276 | :format "%v\n%h" |
| 2230 | :documentation-property (lambda (symbol) | 2277 | :documentation-property (lambda (symbol) |
| @@ -2232,28 +2279,67 @@ With optional ARG, move across that many fields." | |||
| 2232 | (documentation symbol t) | 2279 | (documentation symbol t) |
| 2233 | (error nil)))) | 2280 | (error nil)))) |
| 2234 | 2281 | ||
| 2235 | (define-widget 'variable-item 'item | 2282 | (define-widget 'variable-item 'const |
| 2236 | "An immutable variable name." | 2283 | "An immutable variable name." |
| 2237 | :format "%v\n%h" | 2284 | :format "%v\n%h" |
| 2238 | :documentation-property 'variable-documentation) | 2285 | :documentation-property 'variable-documentation) |
| 2239 | 2286 | ||
| 2240 | (define-widget 'string 'editable-field | 2287 | (define-widget 'string 'editable-field |
| 2241 | "A string" | 2288 | "A string" |
| 2289 | :prompt-value 'widget-string-prompt-value | ||
| 2242 | :tag "String" | 2290 | :tag "String" |
| 2243 | :format "%[%t%]: %v") | 2291 | :format "%[%t%]: %v") |
| 2244 | 2292 | ||
| 2293 | (defvar widget-string-prompt-value-history nil | ||
| 2294 | "History of input to `widget-string-prompt-value'.") | ||
| 2295 | |||
| 2296 | (defun widget-string-prompt-value (widget prompt value unbound) | ||
| 2297 | ;; Read a string. | ||
| 2298 | (read-string prompt (if unbound nil (cons value 1)) | ||
| 2299 | 'widget-string-prompt-value-history)) | ||
| 2300 | |||
| 2245 | (define-widget 'regexp 'string | 2301 | (define-widget 'regexp 'string |
| 2246 | "A regular expression." | 2302 | "A regular expression." |
| 2247 | ;; Should do validation. | 2303 | :match 'widget-regexp-match |
| 2304 | :validate 'widget-regexp-validate | ||
| 2248 | :tag "Regexp") | 2305 | :tag "Regexp") |
| 2249 | 2306 | ||
| 2307 | (defun widget-regexp-match (widget value) | ||
| 2308 | ;; Match valid regexps. | ||
| 2309 | (and (stringp value) | ||
| 2310 | (condition-case data | ||
| 2311 | (prog1 t | ||
| 2312 | (string-match value "")) | ||
| 2313 | (error nil)))) | ||
| 2314 | |||
| 2315 | (defun widget-regexp-validate (widget) | ||
| 2316 | "Check that the value of WIDGET is a valid regexp." | ||
| 2317 | (let ((val (widget-value widget))) | ||
| 2318 | (condition-case data | ||
| 2319 | (prog1 nil | ||
| 2320 | (string-match val "")) | ||
| 2321 | (error (widget-put widget :error (error-message-string data)) | ||
| 2322 | widget)))) | ||
| 2323 | |||
| 2250 | (define-widget 'file 'string | 2324 | (define-widget 'file 'string |
| 2251 | "A file widget. | 2325 | "A file widget. |
| 2252 | It will read a file name from the minibuffer when activated." | 2326 | It will read a file name from the minibuffer when activated." |
| 2327 | :prompt-value 'widget-file-prompt-value | ||
| 2253 | :format "%[%t%]: %v" | 2328 | :format "%[%t%]: %v" |
| 2254 | :tag "File" | 2329 | :tag "File" |
| 2255 | :action 'widget-file-action) | 2330 | :action 'widget-file-action) |
| 2256 | 2331 | ||
| 2332 | (defun widget-file-prompt-value (widget prompt value unbound) | ||
| 2333 | ;; Read file from minibuffer. | ||
| 2334 | (abbreviate-file-name | ||
| 2335 | (if unbound | ||
| 2336 | (read-file-name prompt) | ||
| 2337 | (let ((prompt2 (concat prompt "(default `" value "') ")) | ||
| 2338 | (dir (file-name-directory value)) | ||
| 2339 | (file (file-name-nondirectory value)) | ||
| 2340 | (must-match (widget-get widget :must-match))) | ||
| 2341 | (read-file-name prompt2 dir nil must-match file))))) | ||
| 2342 | |||
| 2257 | (defun widget-file-action (widget &optional event) | 2343 | (defun widget-file-action (widget &optional event) |
| 2258 | ;; Read a file name from the minibuffer. | 2344 | ;; Read a file name from the minibuffer. |
| 2259 | (let* ((value (widget-value widget)) | 2345 | (let* ((value (widget-value widget)) |
| @@ -2303,7 +2389,8 @@ It will read a directory name from the minibuffer when activated." | |||
| 2303 | :validate 'widget-sexp-validate | 2389 | :validate 'widget-sexp-validate |
| 2304 | :match (lambda (widget value) t) | 2390 | :match (lambda (widget value) t) |
| 2305 | :value-to-internal 'widget-sexp-value-to-internal | 2391 | :value-to-internal 'widget-sexp-value-to-internal |
| 2306 | :value-to-external (lambda (widget value) (read value))) | 2392 | :value-to-external (lambda (widget value) (read value)) |
| 2393 | :prompt-value 'widget-sexp-prompt-value) | ||
| 2307 | 2394 | ||
| 2308 | (defun widget-sexp-value-to-internal (widget value) | 2395 | (defun widget-sexp-value-to-internal (widget value) |
| 2309 | ;; Use pp for printer representation. | 2396 | ;; Use pp for printer representation. |
| @@ -2337,6 +2424,24 @@ It will read a directory name from the minibuffer when activated." | |||
| 2337 | (error (widget-put widget :error (error-message-string data)) | 2424 | (error (widget-put widget :error (error-message-string data)) |
| 2338 | widget))))) | 2425 | widget))))) |
| 2339 | 2426 | ||
| 2427 | (defvar widget-sexp-prompt-value-history nil | ||
| 2428 | "History of input to `widget-sexp-prompt-value'.") | ||
| 2429 | |||
| 2430 | (defun widget-sexp-prompt-value (widget prompt value unbound) | ||
| 2431 | ;; Read an arbitrary sexp. | ||
| 2432 | (let ((found (read-string prompt | ||
| 2433 | (if unbound nil (cons (prin1-to-string value) 1)) | ||
| 2434 | 'widget-sexp-prompt-value))) | ||
| 2435 | (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*")))) | ||
| 2436 | (erase-buffer) | ||
| 2437 | (insert found) | ||
| 2438 | (goto-char (point-min)) | ||
| 2439 | (let ((answer (read buffer))) | ||
| 2440 | (unless (eobp) | ||
| 2441 | (error "Junk at end of expression: %s" | ||
| 2442 | (buffer-substring (point) (point-max)))) | ||
| 2443 | answer)))) | ||
| 2444 | |||
| 2340 | (define-widget 'integer 'sexp | 2445 | (define-widget 'integer 'sexp |
| 2341 | "An integer." | 2446 | "An integer." |
| 2342 | :tag "Integer" | 2447 | :tag "Integer" |
| @@ -2354,7 +2459,8 @@ It will read a directory name from the minibuffer when activated." | |||
| 2354 | :value 0 | 2459 | :value 0 |
| 2355 | :size 1 | 2460 | :size 1 |
| 2356 | :format "%{%t%}: %v\n" | 2461 | :format "%{%t%}: %v\n" |
| 2357 | :type-error "This field should contain a character" | 2462 | :valid-regexp "\\`.\\'" |
| 2463 | :error "This field should contain a single character" | ||
| 2358 | :value-to-internal (lambda (widget value) | 2464 | :value-to-internal (lambda (widget value) |
| 2359 | (if (integerp value) | 2465 | (if (integerp value) |
| 2360 | (char-to-string value) | 2466 | (char-to-string value) |
| @@ -2432,8 +2538,20 @@ It will read a directory name from the minibuffer when activated." | |||
| 2432 | (define-widget 'boolean 'toggle | 2538 | (define-widget 'boolean 'toggle |
| 2433 | "To be nil or non-nil, that is the question." | 2539 | "To be nil or non-nil, that is the question." |
| 2434 | :tag "Boolean" | 2540 | :tag "Boolean" |
| 2541 | :prompt-value 'widget-boolean-prompt-value | ||
| 2435 | :format "%{%t%}: %[%v%]\n") | 2542 | :format "%{%t%}: %[%v%]\n") |
| 2436 | 2543 | ||
| 2544 | (defun widget-boolean-prompt-value (widget prompt value unbound) | ||
| 2545 | ;; Toggle a boolean. | ||
| 2546 | (cond (unbound | ||
| 2547 | (y-or-n-p prompt)) | ||
| 2548 | (value | ||
| 2549 | (message "Off") | ||
| 2550 | nil) | ||
| 2551 | (t | ||
| 2552 | (message "On") | ||
| 2553 | t))) | ||
| 2554 | |||
| 2437 | ;;; The `color' Widget. | 2555 | ;;; The `color' Widget. |
| 2438 | 2556 | ||
| 2439 | (define-widget 'color-item 'choice-item | 2557 | (define-widget 'color-item 'choice-item |
diff --git a/lisp/widget.el b/lisp/widget.el index e4ee2ffd584..4905c06b70a 100644 --- a/lisp/widget.el +++ b/lisp/widget.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | ;; | 4 | ;; |
| 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> | 5 | ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> |
| 6 | ;; Keywords: help, extensions, faces, hypermedia | 6 | ;; Keywords: help, extensions, faces, hypermedia |
| 7 | ;; Version: 1.84 | 7 | ;; Version: 1.90 |
| 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. |
| @@ -44,8 +44,8 @@ | |||
| 44 | (set (car keywords) (car keywords))) | 44 | (set (car keywords) (car keywords))) |
| 45 | (setq keywords (cdr keywords))))))) | 45 | (setq keywords (cdr keywords))))))) |
| 46 | 46 | ||
| 47 | (define-widget-keywords :text-format :deactivate :active :inactive | 47 | (define-widget-keywords :prompt-value :text-format :deactivate :active |
| 48 | :activate :sibling-args :delete-button-args | 48 | :inactive :activate :sibling-args :delete-button-args |
| 49 | :insert-button-args :append-button-args :button-args | 49 | :insert-button-args :append-button-args :button-args |
| 50 | :tag-glyph :off-glyph :on-glyph :valid-regexp | 50 | :tag-glyph :off-glyph :on-glyph :valid-regexp |
| 51 | :secret :sample-face :sample-face-get :case-fold :widget-doc | 51 | :secret :sample-face :sample-face-get :case-fold :widget-doc |
| @@ -66,9 +66,11 @@ | |||
| 66 | (autoload 'widget-apply "wid-edit") | 66 | (autoload 'widget-apply "wid-edit") |
| 67 | (autoload 'widget-create "wid-edit") | 67 | (autoload 'widget-create "wid-edit") |
| 68 | (autoload 'widget-insert "wid-edit") | 68 | (autoload 'widget-insert "wid-edit") |
| 69 | (autoload 'widget-prompt-value "wid-edit") | ||
| 69 | (autoload 'widget-browse "wid-browse" nil t) | 70 | (autoload 'widget-browse "wid-browse" nil t) |
| 70 | (autoload 'widget-browse-other-window "wid-browse" nil t) | 71 | (autoload 'widget-browse-other-window "wid-browse" nil t) |
| 71 | (autoload 'widget-browse-at "wid-browse" nil t)) | 72 | (autoload 'widget-browse-at "wid-browse" nil t) |
| 73 | (autoload 'widget-minor-mode "wid-browse" nil t)) | ||
| 72 | 74 | ||
| 73 | (defun define-widget (name class doc &rest args) | 75 | (defun define-widget (name class doc &rest args) |
| 74 | "Define a new widget type named NAME from CLASS. | 76 | "Define a new widget type named NAME from CLASS. |
| @@ -85,7 +87,8 @@ create identical widgets: | |||
| 85 | 87 | ||
| 86 | The third argument DOC is a documentation string for the widget." | 88 | The third argument DOC is a documentation string for the widget." |
| 87 | (put name 'widget-type (cons class args)) | 89 | (put name 'widget-type (cons class args)) |
| 88 | (put name 'widget-documentation doc)) | 90 | (put name 'widget-documentation doc) |
| 91 | name) | ||
| 89 | 92 | ||
| 90 | ;;; The End. | 93 | ;;; The End. |
| 91 | 94 | ||