X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c953515ea36cb7aab77986bb701a9b7f880b97ea..1b33e237605724471fa486643252702feca7a6e1:/lisp/cus-edit.el diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 156b78b793..b6c60a4129 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1,10 +1,10 @@ -;;; cus-edit.el --- Tools for customization Emacs. +;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages. ;; ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. ;; ;; Author: Per Abrahamsen ;; Keywords: help, faces -;; Version: 1.9942 +;; Version: 1.9954 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ ;; This file is part of GNU Emacs. @@ -106,6 +106,10 @@ :group 'external :group 'development) +(defgroup convenience nil + "Convenience features for faster editing." + :group 'emacs) + (defgroup programming nil "Support for programming in other languages." :group 'emacs) @@ -244,7 +248,7 @@ (defgroup customize '((widgets custom-group)) "Customization of the Customization support." - :link '(custom-manual "(custom)Top") + :link '(custom-manual "(elisp)Customization") :link '(url-link :tag "Development Page" "http://www.dina.kvl.dk/~abraham/custom/") :prefix "custom-" @@ -408,7 +412,7 @@ Return a list suitable for use in `interactive'." obarray (lambda (symbol) (and (boundp symbol) (or (get symbol 'custom-type) - (user-variable-p symbol)))))) + (user-variable-p symbol)))) t)) (list (if (equal val "") (if (symbolp v) v nil) (intern val))))) @@ -440,6 +444,11 @@ WIDGET is the widget to apply the filter entries of MENU on." :group 'custom-menu :type 'boolean) +(defcustom custom-unlispify-remove-prefixes nil + "Non-nil means remove group prefixes from option names in buffer." + :group 'custom-menu + :type 'boolean) + (defun custom-unlispify-menu-entry (symbol &optional no-suffix) "Convert symbol into a menu entry." (cond ((not custom-unlispify-menu-entries) @@ -458,15 +467,16 @@ WIDGET is the widget to apply the filter entries of MENU on." (re-search-forward "-p\\'" nil t)) (replace-match "" t t) (goto-char (point-min))) - (let ((prefixes custom-prefix-list) - prefix) - (while prefixes - (setq prefix (car prefixes)) - (if (search-forward prefix (+ (point) (length prefix)) t) - (progn - (setq prefixes nil) - (delete-region (point-min) (point))) - (setq prefixes (cdr prefixes))))) + (if custom-unlispify-remove-prefixes + (let ((prefixes custom-prefix-list) + prefix) + (while prefixes + (setq prefix (car prefixes)) + (if (search-forward prefix (+ (point) (length prefix)) t) + (progn + (setq prefixes nil) + (delete-region (point-min) (point))) + (setq prefixes (cdr prefixes)))))) (subst-char-in-region (point-min) (point-max) ?- ?\ t) (capitalize-region (point-min) (point-max)) (unless no-suffix @@ -601,6 +611,8 @@ If `last', order groups after non-groups." (const :tag "none" nil)) :group 'custom-menu) +;;;###autoload (add-hook 'same-window-regexps "\\`\\*Customiz.*\\*\\'") + (defun custom-sort-items (items sort-alphabetically order-groups) "Return a sorted copy of ITEMS. ITEMS should be a `custom-group' property. @@ -647,7 +659,8 @@ groups after non-groups, if nil do not order groups at all." (interactive) (let ((children custom-options)) (mapcar (lambda (child) - (when (memq (widget-get child :custom-state) '(modified set)) + (when (memq (widget-get child :custom-state) + '(modified set changed rogue)) (widget-apply child :custom-save))) children)) (custom-save-all)) @@ -674,27 +687,33 @@ when the action is chosen.") "Reset all modified group members to their current value." (interactive) (let ((children custom-options)) - (mapcar (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-current))) + (mapcar (lambda (widget) + (and (default-boundp (widget-value widget)) + (if (memq (widget-get widget :custom-state) + '(modified changed)) + (widget-apply widget :custom-reset-current)))) children))) (defun Custom-reset-saved (&rest ignore) "Reset all modified or set group members to their saved value." (interactive) (let ((children custom-options)) - (mapcar (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-saved))) + (mapcar (lambda (widget) + (and (get (widget-value widget) 'saved-value) + (if (memq (widget-get widget :custom-state) + '(modified set changed rogue)) + (widget-apply widget :custom-reset-saved)))) children))) (defun Custom-reset-standard (&rest ignore) "Reset all modified, set, or saved group members to their standard settings." (interactive) (let ((children custom-options)) - (mapcar (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-standard))) + (mapcar (lambda (widget) + (and (get (widget-value widget) 'standard-value) + (if (memq (widget-get widget :custom-state) + '(modified set changed saved rogue)) + (widget-apply widget :custom-reset-standard)))) children))) ;;; The Customize Commands @@ -767,6 +786,26 @@ If VARIABLE has a `custom-type' property, it must be a widget and the (funcall (or (get var 'custom-set) 'set-default) var val) (put var 'customized-value (list (custom-quote val)))) +;;;###autoload +(defun customize-save-variable (var val) + "Set the default for VARIABLE to VALUE, and save it for future sessions. +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +The `customized-value' property of the VARIABLE will be set to a list +with a quoted VALUE as its sole list member. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. " + (interactive (custom-prompt-variable "Set and ave variable: " + "Set and save value for %s as: ")) + (funcall (or (get var 'custom-set) 'set-default) var val) + (put var 'saved-value (list (custom-quote val))) + (custom-save-all)) + ;;;###autoload (defun customize () "Select a customization buffer which you can use to set user options. @@ -783,36 +822,51 @@ are shown; the contents of those subgroups are initially hidden." (completing-read "Customize group: (default emacs) " obarray (lambda (symbol) - (get symbol 'custom-group)) + (or (get symbol 'custom-loads) + (get symbol 'custom-group))) t)))) - (when (stringp group) (if (string-equal "" group) (setq group 'emacs) (setq group (intern group)))) + (or (get group 'custom-group) + (custom-load-symbol group)) (let ((name (format "*Customize Group: %s*" (custom-unlispify-tag-name group)))) (if (get-buffer name) - (switch-to-buffer name) + (pop-to-buffer name) (custom-buffer-create (list (list group 'custom-group)) - name)))) + name + (concat " for group " + (custom-unlispify-tag-name group)))))) ;;;###autoload -(defun customize-group-other-window (symbol) - "Customize SYMBOL, which must be a customization group." - (interactive (list (completing-read "Customize group: (default emacs) " - obarray - (lambda (symbol) - (get symbol 'custom-group)) - t))) - - (when (stringp symbol) - (if (string-equal "" symbol) - (setq symbol 'emacs) - (setq symbol (intern symbol)))) - (custom-buffer-create-other-window - (list (list symbol 'custom-group)) - (format "*Customize Group: %s*" (custom-unlispify-tag-name symbol)))) +(defun customize-group-other-window (group) + "Customize GROUP, which must be a customization group." + (interactive (list (let ((completion-ignore-case t)) + (completing-read "Customize group: (default emacs) " + obarray + (lambda (symbol) + (or (get symbol 'custom-loads) + (get symbol 'custom-group))) + t)))) + (when (stringp group) + (if (string-equal "" group) + (setq group 'emacs) + (setq group (intern group)))) + (or (get group 'custom-group) + (custom-load-symbol group)) + (let ((name (format "*Customize Group: %s*" + (custom-unlispify-tag-name group)))) + (if (get-buffer name) + (let ((window (selected-window))) + (pop-to-buffer name) + (select-window window)) + (custom-buffer-create-other-window + (list (list group 'custom-group)) + name + (concat " for group " + (custom-unlispify-tag-name group)))))) ;;;###autoload (defalias 'customize-variable 'customize-option) @@ -821,10 +875,114 @@ are shown; the contents of those subgroups are initially hidden." (defun customize-option (symbol) "Customize SYMBOL, which must be a user option variable." (interactive (custom-variable-prompt)) + ;; If we don't have SYMBOL's real definition loaded, + ;; try to load it. + (unless (get symbol 'custom-type) + (let ((loaddefs-file (locate-library "loaddefs.el" t)) + file) + ;; See if it is autoloaded from some library. + (when loaddefs-file + (with-temp-buffer + (insert-file-contents loaddefs-file) + (when (re-search-forward (concat "^(defvar " (symbol-name symbol)) + nil t) + (search-backward "\n;;; Generated autoloads from ") + (goto-char (match-end 0)) + (setq file (buffer-substring (point) + (progn (end-of-line) (point))))))) + ;; If it is, load that library. + (when file + (when (string-match "\\.el\\'" file) + (setq file (substring file 0 (match-beginning 0)))) + (load file)))) + (unless (get symbol 'custom-type) + (error "Variable %s cannot be customized" symbol)) (custom-buffer-create (list (list symbol 'custom-variable)) (format "*Customize Option: %s*" (custom-unlispify-tag-name symbol)))) +(defvar customize-changed-options-previous-release "20.2" + "Version for `customize-changed-options' to refer back to by default.") + +;;;###autoload +(defun customize-changed-options (since-version) + "Customize all user option variables changed in Emacs itself. +This includes new user option variables and faces, and new +customization groups, as well as older options and faces whose default +values have changed since the previous major Emacs release. + +With argument SINCE-VERSION (a string), customize all user option +variables that were added (or their meanings were changed) since that +version." + + (interactive "sCustomize options changed, since version (default all versions): ") + (if (equal since-version "") + (setq since-version nil)) + (unless since-version + (setq since-version customize-changed-options-previous-release)) + (let ((found nil) + (versions nil)) + (mapatoms (lambda (symbol) + (and (or (boundp symbol) + ;; For variables not yet loaded. + (get symbol 'standard-value) + ;; For groups the previous test fails, this one + ;; could be used to determine if symbol is a + ;; group. Is there a better way for this? + (get symbol 'group-documentation)) + (let ((version (get symbol 'custom-version))) + (and version + (or (null since-version) + (customize-version-lessp since-version version)) + (if (member version versions) + t + ;;; Collect all versions that we use. + (push version versions)))) + (setq found + ;; We have to set the right thing here, + ;; depending if we have a group or a + ;; variable. + (if (get symbol 'group-documentation) + (cons (list symbol 'custom-group) found) + (cons (list symbol 'custom-variable) found)))))) + (if (not found) + (error "No user option defaults have been changed since Emacs %s" + since-version) + (let ((flist nil)) + (while versions + (push (copy-sequence + (cdr (assoc (car versions) custom-versions-load-alist))) + flist) + (setq versions (cdr versions))) + (put 'custom-versions-load-alist 'custom-loads + ;; Get all the files that correspond to element from the + ;; VERSIONS list. This could use some simplification. + (apply 'nconc flist))) + ;; Because we set all the files needed to be loaded as a + ;; `custom-loads' property to `custom-versions-load-alist' this + ;; call will actually load them. + (custom-load-symbol 'custom-versions-load-alist) + ;; Clean up + (put 'custom-versions-load-alist 'custom-loads nil) + (custom-buffer-create (custom-sort-items found t 'first) + "*Customize Changed Options*")))) + +(defun customize-version-lessp (version1 version2) + ;; In case someone made a mistake and left out the quotes + ;; in the :version value. + (if (numberp version2) + (setq version2 (prin1-to-string version2))) + (let (major1 major2 minor1 minor2) + (string-match "\\([0-9]+\\)[.]\\([0-9]+\\)" version1) + (setq major1 (read (match-string 1 version1))) + (setq minor1 (read (match-string 2 version1))) + (string-match "\\([0-9]+\\)[.]\\([0-9]+\\)" version2) + (setq major2 (read (match-string 1 version2))) + (setq minor2 (read (match-string 2 version2))) + (or (< major1 major2) + (and (= major1 major2) + (< minor1 minor2))))) + ;;;###autoload (defalias 'customize-variable-other-window 'customize-option-other-window) @@ -976,7 +1134,7 @@ links: groups have links to subgroups." :group 'custom-buffer) ;;;###autoload -(defun custom-buffer-create (options &optional name) +(defun custom-buffer-create (options &optional name description) "Create a buffer containing OPTIONS. Optional NAME is the name of the buffer. OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where @@ -984,11 +1142,11 @@ SYMBOL is a customization option, and WIDGET is a widget for editing that option." (unless name (setq name "*Customization*")) (kill-buffer (get-buffer-create name)) - (switch-to-buffer (get-buffer-create name)) - (custom-buffer-create-internal options)) + (pop-to-buffer (get-buffer-create name)) + (custom-buffer-create-internal options description)) ;;;###autoload -(defun custom-buffer-create-other-window (options &optional name) +(defun custom-buffer-create-other-window (options &optional name description) "Create a buffer containing OPTIONS. Optional NAME is the name of the buffer. OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where @@ -996,9 +1154,14 @@ SYMBOL is a customization option, and WIDGET is a widget for editing that option." (unless name (setq name "*Customization*")) (kill-buffer (get-buffer-create name)) - (let ((window (selected-window))) - (switch-to-buffer-other-window (get-buffer-create name)) - (custom-buffer-create-internal options) + (let ((window (selected-window)) + (pop-up-windows t) + (special-display-buffer-names nil) + (special-display-regexps nil) + (same-window-buffer-names nil) + (same-window-regexps nil)) + (pop-to-buffer (get-buffer-create name)) + (custom-buffer-create-internal options description) (select-window window))) (defcustom custom-reset-button-menu nil @@ -1007,12 +1170,18 @@ This button will have a menu with all three reset operations." :type 'boolean :group 'custom-buffer) -(defun custom-buffer-create-internal (options) +(defun custom-buffer-create-internal (options &optional description) (message "Creating customization buffer...") (custom-mode) - (widget-insert "This is a customization buffer. + (widget-insert "This is a customization buffer") + (if description + (widget-insert description)) + (widget-insert ". Square brackets show active fields; type RET or click mouse-1 -on an active field to invoke its action. Invoke ") +on an active field to invoke its action. Editing an option value +changes the text in the buffer; invoke the State button and +choose the Set operation to set the option value. +Invoke ") (widget-create 'info-link :tag "Help" :help-echo "Read the online help." @@ -1082,7 +1251,7 @@ Reset all values in this buffer to their standard settings." (length (length options))) (mapcar (lambda (entry) (prog2 - (message "Creating customization items %2d%%..." + (message "Creating customization items ...%2d%%" (/ (* 100.0 count) length)) (widget-create (nth 1 entry) :tag (custom-unlispify-tag-name @@ -1095,6 +1264,7 @@ Reset all values in this buffer to their standard settings." options)))) (unless (eq (preceding-char) ?\n) (widget-insert "\n")) + (message "Creating customization items ...%2d%%done" 100) (unless (eq custom-buffer-style 'tree) (mapcar 'custom-magic-reset custom-options)) (message "Creating customization setup...") @@ -1105,25 +1275,19 @@ Reset all values in this buffer to their standard settings." ;;; The Tree Browser. ;;;###autoload -(defun customize-browse (group) +(defun customize-browse (&optional group) "Create a tree browser for the customize hierarchy." - (interactive (list (let ((completion-ignore-case t)) - (completing-read "Customize group: (default emacs) " - obarray - (lambda (symbol) - (get symbol 'custom-group)) - t)))) - - (when (stringp group) - (if (string-equal "" group) - (setq group 'emacs) - (setq group (intern group)))) + (interactive) + (unless group + (setq group 'emacs)) (let ((name "*Customize Browser*")) (kill-buffer (get-buffer-create name)) - (switch-to-buffer (get-buffer-create name))) + (pop-to-buffer (get-buffer-create name))) (custom-mode) (widget-insert "\ -Invoke [+] or [?] below to expand items, and [-] to collapse items.\n") +Square brackets show active fields; type RET or click mouse-1 +on an active field to invoke its action. +Invoke [+] below to expand a group, and [-] to collapse an expanded group.\n") (if custom-browse-only-groups (widget-insert "\ Invoke the [Group] button below to edit that item in another window.\n\n") @@ -1153,7 +1317,7 @@ item in another window.\n\n")) (goto-char (point-min))) (define-widget 'custom-browse-visibility 'item - "Control visibility of of items in the customize tree browser." + "Control visibility of items in the customize tree browser." :format "%[[%t]%]" :action 'custom-browse-visibility-action) @@ -1355,8 +1519,8 @@ The list should be sorted most significant first.") "If non-nil, show textual description of the state. If `long', show a full-line description, not just one word." :type '(choice (const :tag "no" nil) - (const short) - (const long)) + (const long) + (other :tag "short" short)) :group 'custom-buffer) (defcustom custom-magic-show-hidden '(option face) @@ -1399,7 +1563,7 @@ and `face'." (text (or (and (eq category 'group) (nth 4 entry)) (nth 3 entry))) - (lisp (eq (widget-get parent :custom-form) 'lisp)) + (form (widget-get parent :custom-form)) children) (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text) (setq text (concat (match-string 1 text) @@ -1428,8 +1592,10 @@ and `face'." (if (eq custom-magic-show 'long) (insert text) (insert (symbol-name state))) - (when lisp - (insert " (lisp)")) + (cond ((eq form 'lisp) + (insert " (lisp)")) + ((eq form 'mismatch) + (insert " (mismatch)"))) (put-text-property start (point) 'face 'custom-state-face)) (insert "\n")) (when (and (eq category 'group) @@ -1450,7 +1616,7 @@ and `face'." :button-suffix "" :help-echo "Change the state." :format (if hidden "%t" "%[%t%]") - :tag (if lisp + :tag (if (memq form '(lisp mismatch)) (concat "(" magic ")") (concat "[" magic "]"))) children) @@ -1495,7 +1661,6 @@ and `face'." :value-delete 'widget-children-value-delete :value-get 'widget-value-value-get :validate 'widget-children-validate - :button-face 'custom-button-face :match (lambda (widget value) (symbolp value))) (defun custom-convert-widget (widget) @@ -1575,6 +1740,8 @@ and `face'." (require load) (error nil))) ;; Don't reload a file already loaded. + ((and (boundp 'preloaded-file-list) + (member load preloaded-file-list))) ((assoc load load-history)) ((assoc (locate-library load) load-history)) (t @@ -1700,6 +1867,13 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." "Face used for pushable variable tags." :group 'custom-faces) +(defcustom custom-variable-default-form 'edit + "Default form of displaying variable values." + :type '(choice (const edit) + (const lisp)) + :group 'custom-buffer + :version "20.3") + (define-widget 'custom-variable 'custom "Customize variable." :format "%v" @@ -1708,7 +1882,7 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." :custom-category 'option :custom-state nil :custom-menu 'custom-variable-menu-create - :custom-form 'edit + :custom-form nil ; defaults to value of `custom-variable-default-form' :value-create 'custom-variable-value-create :action 'custom-variable-action :custom-set 'custom-variable-set @@ -1736,6 +1910,8 @@ Otherwise, look up symbol in `custom-guess-type-alist'." (defun custom-variable-value-create (widget) "Here is where you edit the variables value." (custom-load-widget widget) + (unless (widget-get widget :custom-form) + (widget-put widget :custom-form custom-variable-default-form)) (let* ((buttons (widget-get widget :buttons)) (children (widget-get widget :children)) (form (widget-get widget :custom-form)) @@ -1760,7 +1936,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'." (when (eq state 'unknown) (unless (widget-apply conv :match value) ;; (widget-apply (widget-convert type) :match value) - (setq form 'lisp))) + (setq form 'mismatch))) ;; Now we can create the child widget. (cond ((eq custom-buffer-style 'tree) (insert prefix (if last " `--- " " |--- ")) @@ -1784,7 +1960,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'." :action 'custom-toggle-parent nil) buttons)) - ((eq form 'lisp) + ((memq form '(lisp mismatch)) ;; In lisp mode edit the saved value when possible. (let* ((value (cond ((get symbol 'saved-value) (car (get symbol 'saved-value))) @@ -1815,7 +1991,7 @@ Otherwise, look up symbol in `custom-guess-type-alist'." (let* ((format (widget-get type :format)) tag-format value-format) (unless (string-match ":" format) - (error "Bad format.")) + (error "Bad format")) (setq tag-format (substring format 0 (match-end 0))) (setq value-format (substring format (match-end 0))) (push (widget-create-child-and-convert @@ -1927,10 +2103,10 @@ Otherwise, look up symbol in `custom-guess-type-alist'." ("---" ignore ignore) ("Don't show as Lisp expression" custom-variable-edit (lambda (widget) - (not (eq (widget-get widget :custom-form) 'edit)))) - ("Show as Lisp expression" custom-variable-edit-lisp + (eq (widget-get widget :custom-form) 'lisp))) + ("Show initial Lisp expression" custom-variable-edit-lisp (lambda (widget) - (not (eq (widget-get widget :custom-form) 'lisp))))) + (eq (widget-get widget :custom-form) 'edit)))) "Alist of actions for the `custom-variable' widget. Each entry has the form (NAME ACTION FILTER) where NAME is the name of the menu entry, ACTION is the function to call on the widget when the @@ -1977,11 +2153,11 @@ Optional EVENT is the location for the menu." (set (or (get symbol 'custom-set) 'set-default)) val) (cond ((eq state 'hidden) - (error "Cannot set hidden variable.")) + (error "Cannot set hidden variable")) ((setq val (widget-apply child :validate)) (goto-char (widget-get val :from)) (error "%s" (widget-get val :error))) - ((eq form 'lisp) + ((memq form '(lisp mismatch)) (funcall set symbol (eval (setq val (widget-value child)))) (put symbol 'customized-value (list val))) (t @@ -1991,7 +2167,7 @@ Optional EVENT is the location for the menu." (custom-redraw-magic widget))) (defun custom-variable-save (widget) - "Set the default value for the variable being edited by WIDGET." + "Set and save the value for the variable being edited by WIDGET." (let* ((form (widget-get widget :custom-form)) (state (widget-get widget :custom-state)) (child (car (widget-get widget :children))) @@ -1999,11 +2175,11 @@ Optional EVENT is the location for the menu." (set (or (get symbol 'custom-set) 'set-default)) val) (cond ((eq state 'hidden) - (error "Cannot set hidden variable.")) + (error "Cannot set hidden variable")) ((setq val (widget-apply child :validate)) (goto-char (widget-get val :from)) (error "%s" (widget-get val :error))) - ((eq form 'lisp) + ((memq form '(lisp mismatch)) (put symbol 'saved-value (list (widget-value child))) (funcall set symbol (eval (widget-value child)))) (t @@ -2084,10 +2260,10 @@ The X11 Window System.") :sibling-args (:help-echo "\ OS/2 Presentation Manager.") pm) - (const :format "Win32 " + (const :format "W32 " :sibling-args (:help-echo "\ -Windows NT/95/97.") - win32) +Windows NT/9X.") + w32) (const :format "DOS " :sibling-args (:help-echo "\ Plain MS-DOS.") @@ -2136,6 +2312,14 @@ Match frames with dark backgrounds.") "Face used for face tags." :group 'custom-faces) +(defcustom custom-face-default-form 'selected + "Default form of displaying face definition." + :type '(choice (const all) + (const selected) + (const lisp)) + :group 'custom-buffer + :version "20.3") + (define-widget 'custom-face 'custom "Customize face." :sample-face 'custom-face-tag-face @@ -2145,7 +2329,7 @@ Match frames with dark backgrounds.") :value-create 'custom-face-value-create :action 'custom-face-action :custom-category 'face - :custom-form 'selected + :custom-form nil ; defaults to value of `custom-face-default-form' :custom-set 'custom-face-set :custom-save 'custom-face-save :custom-reset-current 'custom-redraw @@ -2249,6 +2433,8 @@ Match frames with dark backgrounds.") (unless (eq state 'hidden) (message "Creating face editor...") (custom-load-widget widget) + (unless (widget-get widget :custom-form) + (widget-put widget :custom-form custom-face-default-form)) (let* ((symbol (widget-value widget)) (spec (or (get symbol 'saved-face) (get symbol 'face-defface-spec) @@ -2257,7 +2443,12 @@ Match frames with dark backgrounds.") symbol (selected-frame)))))) (form (widget-get widget :custom-form)) (indent (widget-get widget :indent)) - (edit (widget-create-child-and-convert + edit) + ;; If the user has changed this face in some other way, + ;; edit it as the user has specified it. + (if (not (face-spec-match-p symbol spec (selected-frame))) + (setq spec (list (list t (face-attr-construct symbol (selected-frame)))))) + (setq edit (widget-create-child-and-convert widget (cond ((and (eq form 'selected) (widget-apply custom-face-selected @@ -2271,14 +2462,14 @@ Match frames with dark backgrounds.") (t (when indent (insert-char ?\ indent)) 'sexp)) - :value spec))) + :value spec)) (custom-face-state-set widget) (widget-put widget :children (list edit))) (message "Creating face editor...done")))))) (defvar custom-face-menu - '(("Set" custom-face-set) - ("Save" custom-face-save) + '(("Set for Current Session" custom-face-set) + ("Save for Future Sessions" custom-face-save-command) ("Reset to Saved" custom-face-reset-saved (lambda (widget) (get (widget-value widget) 'saved-face))) @@ -2357,14 +2548,20 @@ Optional EVENT is the location for the menu." (custom-face-state-set widget) (custom-redraw-magic widget))) +(defun custom-face-save-command (widget) + "Save in `.emacs' the face attributes in WIDGET." + (custom-face-save widget) + (custom-save-all)) + (defun custom-face-save (widget) - "Make the face attributes in WIDGET default." + "Prepare for saving WIDGET's face attributes, but don't write `.emacs'." (let* ((symbol (widget-value widget)) (child (car (widget-get widget :children))) (value (widget-value child))) (face-spec-set symbol value) (put symbol 'saved-face value) (put symbol 'customized-face nil) + (custom-save-all) (custom-face-state-set widget) (custom-redraw-magic widget))) @@ -2452,6 +2649,13 @@ Optional EVENT is the location for the menu." (define-widget 'hook 'list "A emacs lisp hook" + :value-to-internal (lambda (widget value) + (if (and value (symbolp value)) + (list value) + value)) + :match (lambda (widget value) + (or (symbolp value) + (widget-group-match widget value))) :convert-widget 'custom-hook-convert-widget :tag "Hook") @@ -2542,24 +2746,37 @@ and so forth. The remaining group tags are shown with (insert "--------"))) (widget-default-create widget)) +(defun custom-group-members (symbol groups-only) + "Return SYMBOL's custom group members. +If GROUPS-ONLY non-nil, return only those members that are groups." + (if (not groups-only) + (get symbol 'custom-group) + (let (members) + (dolist (entry (get symbol 'custom-group)) + (when (eq (nth 1 entry) 'custom-group) + (push entry members))) + (nreverse members)))) + (defun custom-group-value-create (widget) "Insert a customize group for WIDGET in the current buffer." - (let ((state (widget-get widget :custom-state)) - (level (widget-get widget :custom-level)) - (indent (widget-get widget :indent)) - (prefix (widget-get widget :custom-prefix)) - (buttons (widget-get widget :buttons)) - (tag (widget-get widget :tag)) - (symbol (widget-value widget))) + (let* ((state (widget-get widget :custom-state)) + (level (widget-get widget :custom-level)) + ;; (indent (widget-get widget :indent)) + (prefix (widget-get widget :custom-prefix)) + (buttons (widget-get widget :buttons)) + (tag (widget-get widget :tag)) + (symbol (widget-value widget)) + (members (custom-group-members symbol + (and (eq custom-buffer-style 'tree) + custom-browse-only-groups)))) (cond ((and (eq custom-buffer-style 'tree) (eq state 'hidden) - (or (get symbol 'custom-group) - (custom-unloaded-widget-p widget))) + (or members (custom-unloaded-widget-p widget))) (custom-browse-insert-prefix prefix) (push (widget-create-child-and-convert widget 'custom-browse-visibility ;; :tag-glyph "plus" - :tag (if (custom-unloaded-widget-p widget) "?" "+")) + :tag "+") buttons) (insert "-- ") ;; (widget-glyph-insert nil "-- " "horizontal") @@ -2569,7 +2786,7 @@ and so forth. The remaining group tags are shown with (insert " " tag "\n") (widget-put widget :buttons buttons)) ((and (eq custom-buffer-style 'tree) - (zerop (length (get symbol 'custom-group)))) + (zerop (length members))) (custom-browse-insert-prefix prefix) (insert "[ ]-- ") ;; (widget-glyph-insert nil "[ ]" "empty") @@ -2582,7 +2799,7 @@ and so forth. The remaining group tags are shown with ((eq custom-buffer-style 'tree) (custom-browse-insert-prefix prefix) (custom-load-widget widget) - (if (zerop (length (get symbol 'custom-group))) + (if (zerop (length members)) (progn (custom-browse-insert-prefix prefix) (insert "[ ]-- ") @@ -2606,7 +2823,7 @@ and so forth. The remaining group tags are shown with (insert " " tag "\n") (widget-put widget :buttons buttons) (message "Creating group...") - (let* ((members (custom-sort-items (get symbol 'custom-group) + (let* ((members (custom-sort-items members custom-browse-sort-alphabetically custom-browse-order-groups)) (prefixes (widget-get widget :custom-prefixes)) @@ -2619,18 +2836,16 @@ and so forth. The remaining group tags are shown with (while members (setq entry (car members) members (cdr members)) - (when (or (not custom-browse-only-groups) - (eq (nth 1 entry) 'custom-group)) - (push (widget-create-child-and-convert - widget (nth 1 entry) - :group widget - :tag (custom-unlispify-tag-name (nth 0 entry)) - :custom-prefixes custom-prefix-list - :custom-level (1+ level) - :custom-last (null members) - :value (nth 0 entry) - :custom-prefix prefix) - children))) + (push (widget-create-child-and-convert + widget (nth 1 entry) + :group widget + :tag (custom-unlispify-tag-name (nth 0 entry)) + :custom-prefixes custom-prefix-list + :custom-level (1+ level) + :custom-last (null members) + :value (nth 0 entry) + :custom-prefix prefix) + children)) (widget-put widget :children (reverse children))) (message "Creating group...done"))) ;; Nested style. @@ -2652,7 +2867,7 @@ and so forth. The remaining group tags are shown with symbol) buttons) (push (widget-create-child-and-convert - widget 'group-visibility + widget 'custom-group-visibility :help-echo "Show members of this group." :action 'custom-toggle-parent (not (eq state 'hidden))) @@ -2725,7 +2940,7 @@ and so forth. The remaining group tags are shown with ;; Members. (message "Creating group...") (custom-load-widget widget) - (let* ((members (custom-sort-items (get symbol 'custom-group) + (let* ((members (custom-sort-items members custom-buffer-sort-alphabetically custom-buffer-order-groups)) (prefixes (widget-get widget :custom-prefixes)) @@ -2764,10 +2979,10 @@ Creating group members... %2d%%" (insert "/\n"))))) (defvar custom-group-menu - '(("Set" custom-group-set + '(("Set for Current Session" custom-group-set (lambda (widget) (eq (widget-get widget :custom-state) 'modified))) - ("Save" custom-group-save + ("Save for Future Sessions" custom-group-save (lambda (widget) (memq (widget-get widget :custom-state) '(modified set)))) ("Reset to Current" custom-group-reset-current @@ -2863,19 +3078,27 @@ Optional EVENT is the location for the menu." ;;; The `custom-save-all' Function. ;;;###autoload -(defcustom custom-file (if (featurep 'xemacs) - "~/.xemacs-custom" - "~/.emacs") +(defcustom custom-file nil "File used for storing customization information. -If you change this from the default \"~/.emacs\" you need to -explicitly load that file for the settings to take effect." - :type 'file +The default is nil, which means to use your init file +as specified by `user-init-file'. If you specify some other file, +you need to explicitly load that file for the settings to take effect." + :type '(choice (const :tag "Your Emacs init file" nil) file) :group 'customize) +(defun custom-file () + "Return the file name for saving customizations." + (setq custom-file + (or custom-file + user-init-file + (read-file-name "File for customizations: " + "~/" nil nil ".emacs")))) + (defun custom-save-delete (symbol) - "Delete the call to SYMBOL form `custom-file'. + "Delete the call to SYMBOL from `custom-file'. Leave point at the location of the call, or after the last expression." - (set-buffer (find-file-noselect custom-file)) + (let ((default-major-mode)) + (set-buffer (find-file-noselect (custom-file)))) (goto-char (point-min)) (catch 'found (while t @@ -2978,54 +3201,18 @@ Leave point at the location of the call, or after the last expression." ;;;###autoload (defun custom-save-all () "Save all customizations in `custom-file'." - (custom-save-variables) - (custom-save-faces) - (save-excursion - (set-buffer (find-file-noselect custom-file)) - (save-buffer))) + (let ((inhibit-read-only t)) + (custom-save-variables) + (custom-save-faces) + (save-excursion + (let ((default-major-mode nil)) + (set-buffer (find-file-noselect (custom-file)))) + (save-buffer)))) ;;; The Customize Menu. ;;; Menu support -(unless (string-match "XEmacs" emacs-version) - (defconst custom-help-menu - '("Customize" - ["Update menu" Custom-menu-update t] - ["Browse" (customize-browse 'emacs) t] - ["Group..." customize-group t] - ["Option..." customize-option t] - ["Face..." customize-face t] - ["Saved..." customize-saved t] - ["Set..." customize-customized t] - "--" - ["Apropos..." customize-apropos t] - ["Group apropos..." customize-apropos-groups t] - ["Option apropos..." customize-apropos-options t] - ["Face apropos..." customize-apropos-faces t]) - ;; This menu should be identical to the one defined in `menu-bar.el'. - "Customize menu") - - (defun custom-menu-reset () - "Reset customize menu." - (remove-hook 'custom-define-hook 'custom-menu-reset) - (define-key global-map [menu-bar help-menu customize-menu] - (cons (car custom-help-menu) - (easy-menu-create-keymaps (car custom-help-menu) - (cdr custom-help-menu))))) - - (defun Custom-menu-update (event) - "Update customize menu." - (interactive "e") - (add-hook 'custom-define-hook 'custom-menu-reset) - (let* ((emacs (widget-apply '(custom-group) :custom-menu 'emacs)) - (menu `(,(car custom-help-menu) - ,emacs - ,@(cdr (cdr custom-help-menu))))) - (let ((map (easy-menu-create-keymaps (car menu) (cdr menu)))) - (define-key global-map [menu-bar help-menu customize-menu] - (cons (car menu) map)))))) - (defcustom custom-menu-nesting 2 "Maximum nesting in custom menus." :type 'integer @@ -3126,6 +3313,8 @@ The format is suitable for use with `easy-menu-define'." (define-key custom-mode-map "\177" 'scroll-down) (define-key custom-mode-map "q" 'bury-buffer) (define-key custom-mode-map "u" 'Custom-goto-parent) + (define-key custom-mode-map "n" 'widget-forward) + (define-key custom-mode-map "p" 'widget-backward) (define-key custom-mode-map [mouse-1] 'Custom-move-and-invoke)) (defun Custom-move-and-invoke (event) @@ -3148,7 +3337,7 @@ The format is suitable for use with `easy-menu-define'." ["Reset to Current" Custom-reset-current t] ["Reset to Saved" Custom-reset-saved t] ["Reset to Standard Settings" Custom-reset-standard t] - ["Info" (Info-goto-node "(custom)The Customization Buffer") t])) + ["Info" (Info-goto-node "(emacs)Easy Customization") t])) (defun Custom-goto-parent () "Go to the parent group listed at the top of this buffer. @@ -3177,6 +3366,9 @@ The following commands are available: Move to next button or editable field. \\[widget-forward] Move to previous button or editable field. \\[widget-backward] +\\\ +Complete content of editable text field. \\[widget-complete] +\\\ Invoke button under the mouse pointer. \\[Custom-move-and-invoke] Invoke button under point. \\[widget-button-press] Set all modifications. \\[Custom-set] @@ -3195,6 +3387,8 @@ if that value is non-nil." (make-local-variable 'custom-options) (make-local-variable 'widget-documentation-face) (setq widget-documentation-face 'custom-documentation-face) + (make-local-variable 'widget-button-face) + (setq widget-button-face 'custom-button-face) (make-local-hook 'widget-edit-functions) (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t) (run-hooks 'custom-mode-hook))