;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: help, faces
-;; Version: 1.71
+;; Version: 1.90
;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
;;; Commentary:
;;
+;; This file implements the code to create and edit customize buffers.
+;;
;; See `custom.el'.
;;; Code:
(require 'cus-face)
(require 'wid-edit)
(require 'easymenu)
+(eval-when-compile (require 'cl))
+
+(condition-case nil
+ (require 'cus-load)
+ (error nil))
+
+(defun custom-face-display-set (face spec &optional frame)
+ (face-spec-set face spec frame))
+
+(defun custom-display-match-frame (display frame)
+ (face-spec-set-match-display display frame))
(define-widget-keywords :custom-prefixes :custom-menu :custom-show
:custom-magic :custom-state :custom-level :custom-form
:custom-set :custom-save :custom-reset-current :custom-reset-saved
:custom-reset-factory)
+(put 'custom-define-hook 'custom-type 'hook)
+(put 'custom-define-hook 'factory-value '(nil))
+(custom-add-to-group 'customize 'custom-define-hook 'custom-variable)
+
;;; Customization Groups.
(defgroup emacs nil
:link '(url-link :tag "Development Page"
"http://www.dina.kvl.dk/~abraham/custom/")
:prefix "custom-"
- :group 'help
+ :group 'help)
+
+(defgroup custom-faces nil
+ "Faces used by customize."
+ :group 'customize
:group 'faces)
+(defgroup abbrev-mode nil
+ "Word abbreviations mode."
+ :group 'abbrev)
+
+(defgroup alloc nil
+ "Storage allocation and gc for GNU Emacs Lisp interpreter."
+ :tag "Storage Allocation"
+ :group 'internal)
+
+(defgroup undo nil
+ "Undoing changes in buffers."
+ :group 'editing)
+
+(defgroup modeline nil
+ "Content of the modeline."
+ :group 'environment)
+
+(defgroup fill nil
+ "Indenting and filling text."
+ :group 'editing)
+
+(defgroup editing-basics nil
+ "Most basic editing facilities."
+ :group 'editing)
+
+(defgroup display nil
+ "How characters are displayed in buffers."
+ :group 'environment)
+
+(defgroup execute nil
+ "Executing external commands."
+ :group 'processes)
+
+(defgroup installation nil
+ "The Emacs installation."
+ :group 'environment)
+
+(defgroup dired nil
+ "Directory editing."
+ :group 'environment)
+
+(defgroup limits nil
+ "Internal Emacs limits."
+ :group 'internal)
+
+(defgroup debug nil
+ "Debugging Emacs itself."
+ :group 'development)
+
+(defgroup minibuffer nil
+ "Controling the behaviour of the minibuffer."
+ :group 'environment)
+
+(defgroup keyboard nil
+ "Input from the keyboard."
+ :group 'environment)
+
+(defgroup mouse nil
+ "Input from the mouse."
+ :group 'environment)
+
+(defgroup menu nil
+ "Input from the menus."
+ :group 'environment)
+
+(defgroup auto-save nil
+ "Preventing accidential loss of data."
+ :group 'data)
+
+(defgroup processes-basics nil
+ "Basic stuff dealing with processes."
+ :group 'processes)
+
+(defgroup windows nil
+ "Windows within a frame."
+ :group 'processes)
+
;;; Utilities.
(defun custom-quote (sexp)
(nreverse (cons (substring regexp start) all)))
regexp))
+(defun custom-variable-prompt ()
+ ;; Code stolen from `help.el'.
+ "Prompt for a variable, defaulting to the variable at point.
+Return a list suitable for use in `interactive'."
+ (let ((v (variable-at-point))
+ (enable-recursive-minibuffers t)
+ val)
+ (setq val (completing-read
+ (if v
+ (format "Customize variable (default %s): " v)
+ "Customize variable: ")
+ obarray (lambda (symbol)
+ (and (boundp symbol)
+ (or (get symbol 'custom-type)
+ (user-variable-p symbol))))))
+ (list (if (equal val "")
+ v (intern val)))))
+
+(defun custom-menu-filter (menu widget)
+ "Convert MENU to the form used by `widget-choose'.
+MENU should be in the same format as `custom-variable-menu'.
+WIDGET is the widget to apply the filter entries of MENU on."
+ (let ((result nil)
+ current name action filter)
+ (while menu
+ (setq current (car menu)
+ name (nth 0 current)
+ action (nth 1 current)
+ filter (nth 2 current)
+ menu (cdr menu))
+ (if (or (null filter) (funcall filter widget))
+ (push (cons name action) result)
+ (push name result)))
+ (nreverse result)))
+
+;;; Unlispify.
+
(defvar custom-prefix-list nil
"List of prefixes that should be ignored by `custom-unlispify'")
(erase-buffer)
(princ symbol (current-buffer))
(goto-char (point-min))
+ (when (and (eq (get symbol 'custom-type) 'boolean)
+ (re-search-forward "-p\\'" nil t))
+ (replace-match "" t t)
+ (goto-char (point-min)))
(let ((prefixes custom-prefix-list)
prefix)
(while prefixes
(concat (symbol-name symbol) "-"))
prefixes))
-;;; The Custom Mode.
-
-(defvar custom-options nil
- "Customization widgets in the current buffer.")
-
-(defvar custom-mode-map nil
- "Keymap for `custom-mode'.")
-
-(unless custom-mode-map
- (setq custom-mode-map (make-sparse-keymap))
- (set-keymap-parent custom-mode-map widget-keymap)
- (define-key custom-mode-map "q" 'bury-buffer))
-
-(easy-menu-define custom-mode-menu
- custom-mode-map
- "Menu used in customization buffers."
- '("Custom"
- ["Set" custom-set t]
- ["Save" custom-save t]
- ["Reset to Current" custom-reset-current t]
- ["Reset to Saved" custom-reset-saved t]
- ["Reset to Factory Settings" custom-reset-factory t]
- ["Info" (Info-goto-node "(custom)The Customization Buffer") t]))
-
-(defcustom custom-mode-hook nil
- "Hook called when entering custom-mode."
- :type 'hook
+;;; Guess.
+
+(defcustom custom-guess-name-alist
+ '(("-p\\'" boolean)
+ ("-hook\\'" hook)
+ ("-face\\'" face)
+ ("-file\\'" file)
+ ("-function\\'" function)
+ ("-functions\\'" (repeat function))
+ ("-list\\'" (repeat sexp))
+ ("-alist\\'" (repeat (cons sexp sexp))))
+ "Alist of (MATCH TYPE).
+
+MATCH should be a regexp matching the name of a symbol, and TYPE should
+be a widget suitable for editing the value of that symbol. The TYPE
+of the first entry where MATCH matches the name of the symbol will be
+used.
+
+This is used for guessing the type of variables not declared with
+customize."
+ :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type")))
:group 'customize)
-(defun custom-mode ()
- "Major mode for editing customization buffers.
+(defcustom custom-guess-doc-alist
+ '(("\\`\\*?Non-nil " boolean))
+ "Alist of (MATCH TYPE).
-The following commands are available:
+MATCH should be a regexp matching a documentation string, and TYPE
+should be a widget suitable for editing the value of a variable with
+that documentation string. The TYPE of the first entry where MATCH
+matches the name of the symbol will be used.
-\\[widget-forward] Move to next button or editable field.
-\\[widget-backward] Move to previous button or editable field.
-\\[widget-button-click] Activate button under the mouse pointer.
-\\[widget-button-press] Activate button under point.
-\\[custom-set] Set all modifications.
-\\[custom-save] Make all modifications default.
-\\[custom-reset-current] Reset all modified options.
-\\[custom-reset-saved] Reset all modified or set options.
-\\[custom-reset-factory] Reset all options.
+This is used for guessing the type of variables not declared with
+customize."
+ :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type")))
+ :group 'customize)
-Entry to this mode calls the value of `custom-mode-hook'
-if that value is non-nil."
- (kill-all-local-variables)
- (setq major-mode 'custom-mode
- mode-name "Custom")
- (use-local-map custom-mode-map)
- (easy-menu-add custom-mode-menu)
- (make-local-variable 'custom-options)
- (run-hooks 'custom-mode-hook))
+(defun custom-guess-type (symbol)
+ "Guess a widget suitable for editing the value of SYMBOL.
+This is done by matching SYMBOL with `custom-guess-name-alist' and
+if that fails, the doc string with `custom-guess-doc-alist'."
+ (let ((name (symbol-name symbol))
+ (names custom-guess-name-alist)
+ current found)
+ (while names
+ (setq current (car names)
+ names (cdr names))
+ (when (string-match (nth 0 current) name)
+ (setq found (nth 1 current)
+ names nil)))
+ (unless found
+ (let ((doc (documentation-property symbol 'variable-documentation))
+ (docs custom-guess-doc-alist))
+ (when doc
+ (while docs
+ (setq current (car docs)
+ docs (cdr docs))
+ (when (string-match (nth 0 current) doc)
+ (setq found (nth 1 current)
+ docs nil))))))
+ found))
;;; Custom Mode Commands.
+(defvar custom-options nil
+ "Customization widgets in the current buffer.")
+
(defun custom-set ()
"Set changes in all modified options."
(interactive)
children)))
(defun custom-reset-factory ()
- "Reset all modified, set, or saved group members to their factory settings."
+ "Reset all modified, set, or saved group members to their standard settings."
(interactive)
(let ((children custom-options))
(mapcar (lambda (child)
;;; The Customize Commands
+(defun custom-prompt-variable (prompt-var prompt-val)
+ "Prompt for a variable and a value and return them as a list.
+PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the
+prompt for the value. The %s escape in PROMPT-VAL is replaced with
+the name of the variable.
+
+If the 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 the 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."
+ (let* ((var (read-variable prompt-var))
+ (minibuffer-help-form '(describe-variable var)))
+ (list var
+ (let ((prop (get var 'variable-interactive))
+ (type (get var 'custom-type))
+ (prompt (format prompt-val var)))
+ (unless (listp type)
+ (setq type (list type)))
+ (cond (prop
+ ;; Use VAR's `variable-interactive' property
+ ;; as an interactive spec for prompting.
+ (call-interactively (list 'lambda '(arg)
+ (list 'interactive prop)
+ 'arg)))
+ (type
+ (widget-prompt-value type
+ prompt
+ (if (boundp var)
+ (symbol-value var))
+ (not (boundp var))))
+ (t
+ (eval-minibuffer prompt)))))))
+
+;;;###autoload
+(defun custom-set-value (var val)
+ "Set VARIABLE to VALUE. VALUE is a Lisp object.
+
+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 variable: "
+ "Set %s to value: "))
+
+ (set var val))
+
+;;;###autoload
+(defun custom-set-variable (var val)
+ "Set the default for VARIABLE to VALUE. VALUE is a Lisp object.
+
+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 variable: "
+ "Set customized value for %s to: "))
+ (funcall (or (get var 'custom-set) 'set-default) var val)
+ (put var 'customized-value (list (custom-quote val))))
+
+;;;###autoload
+(defun customize ()
+ "Select a customization buffer which you can use to set user options.
+User options are structured into \"groups\".
+Initially the top-level group `Emacs' and its immediate subgroups
+are shown; the contents of those subgroups are initially hidden."
+ (interactive)
+ (customize-group 'emacs))
+
;;;###autoload
-(defun customize (symbol)
+(defun customize-group (group)
+ "Customize GROUP, which must be a customization group."
+ (interactive (list (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))))
+ (custom-buffer-create (list (list group 'custom-group))))
+
+;;;###autoload
+(defun customize-other-window (symbol)
"Customize SYMBOL, which must be a customization group."
(interactive (list (completing-read "Customize group: (default emacs) "
obarray
(if (string-equal "" symbol)
(setq symbol 'emacs)
(setq symbol (intern symbol))))
- (custom-buffer-create (list (list symbol 'custom-group))))
+ (custom-buffer-create-other-window (list (list symbol 'custom-group))))
;;;###autoload
(defun customize-variable (symbol)
"Customize SYMBOL, which must be a variable."
- (interactive
- ;; Code stolen from `help.el'.
- (let ((v (variable-at-point))
- (enable-recursive-minibuffers t)
- val)
- (setq val (completing-read
- (if v
- (format "Customize variable (default %s): " v)
- "Customize variable: ")
- obarray 'boundp t))
- (list (if (equal val "")
- v (intern val)))))
+ (interactive (custom-variable-prompt))
(custom-buffer-create (list (list symbol 'custom-variable))))
+;;;###autoload
+(defun customize-variable-other-window (symbol)
+ "Customize SYMBOL, which must be a variable.
+Show the buffer in another window, but don't select it."
+ (interactive (custom-variable-prompt))
+ (custom-buffer-create-other-window (list (list symbol 'custom-variable))))
+
;;;###autoload
(defun customize-face (&optional symbol)
"Customize SYMBOL, which should be a face name or nil.
(message "Looking for faces...")
(mapcar (lambda (symbol)
(setq found (cons (list symbol 'custom-face) found)))
- (face-list))
+ (nreverse (mapcar 'intern
+ (sort (mapcar 'symbol-name (face-list))
+ 'string<))))
+
(custom-buffer-create found))
(if (stringp symbol)
(setq symbol (intern symbol)))
(error "Should be a symbol %S" symbol))
(custom-buffer-create (list (list symbol 'custom-face)))))
+;;;###autoload
+(defun customize-face-other-window (&optional symbol)
+ "Show customization buffer for FACE in other window."
+ (interactive (list (completing-read "Customize face: "
+ obarray 'custom-facep)))
+ (if (or (null symbol) (and (stringp symbol) (zerop (length symbol))))
+ ()
+ (if (stringp symbol)
+ (setq symbol (intern symbol)))
+ (unless (symbolp symbol)
+ (error "Should be a symbol %S" symbol))
+ (custom-buffer-create-other-window (list (list symbol 'custom-face)))))
+
;;;###autoload
(defun customize-customized ()
- "Customize all already customized user options."
+ "Customize all user options set since the last save in this session."
+ (interactive)
+ (let ((found nil))
+ (mapatoms (lambda (symbol)
+ (and (get symbol 'customized-face)
+ (custom-facep symbol)
+ (setq found (cons (list symbol 'custom-face) found)))
+ (and (get symbol 'customized-value)
+ (boundp symbol)
+ (setq found
+ (cons (list symbol 'custom-variable) found)))))
+ (if found
+ (custom-buffer-create found)
+ (error "No customized user options"))))
+
+;;;###autoload
+(defun customize-saved ()
+ "Customize all already saved user options."
(interactive)
(let ((found nil))
(mapatoms (lambda (symbol)
(cons (list symbol 'custom-variable) found)))))
(if found
(custom-buffer-create found)
- (error "No customized user options"))))
+ (error "No saved user options"))))
;;;###autoload
(defun customize-apropos (regexp &optional all)
(custom-buffer-create found)
(error "No matches"))))
+;;; Buffer.
+
;;;###autoload
(defun custom-buffer-create (options)
"Create a buffer containing OPTIONS.
OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
SYMBOL is a customization option, and WIDGET is a widget for editing
that option."
- (message "Creating customization buffer...")
(kill-buffer (get-buffer-create "*Customization*"))
(switch-to-buffer (get-buffer-create "*Customization*"))
+ (custom-buffer-create-internal options))
+
+;;;###autoload
+(defun custom-buffer-create-other-window (options)
+ "Create a buffer containing OPTIONS.
+OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
+SYMBOL is a customization option, and WIDGET is a widget for editing
+that option."
+ (kill-buffer (get-buffer-create "*Customization*"))
+ (let ((window (selected-window)))
+ (switch-to-buffer-other-window (get-buffer-create "*Customization*"))
+ (custom-buffer-create-internal options)
+ (select-window window)))
+
+
+(defun custom-buffer-create-internal (options)
+ (message "Creating customization buffer...")
(custom-mode)
(widget-insert "This is a customization buffer.
Push RET or click mouse-2 on the word ")
(message "Creating customization setup...")
(widget-setup)
(goto-char (point-min))
+ (forward-line 3) ;Kludge: bob is writable in XEmacs.
(message "Creating customization buffer...done"))
;;; Modification of Basic Widgets.
(rogue "@" custom-rogue-face "\
this item is not prepared for customization.")
(factory " " nil "\
-this item is unchanged from its factory setting."))
+this item is unchanged from its standard setting."))
"Alist of customize option states.
Each entry is of the form (STATE MAGIC FACE DESCRIPTION), where
`rogue'
This item has no customization information.
`factory'
- This item is unchanged from the factory default.
+ This item is unchanged from the standard setting.
MAGIC is a string used to present that state.
(string :tag "Magic")
face
(string :tag "Description"))))
- :group 'customize)
+ :group 'customize
+ :group 'custom-faces)
+
+(defcustom custom-group-magic-alist '((nil "#" underline "\
+uninitialized, you should not see this.")
+ (unknown "?" italic "\
+unknown, you should not see this.")
+ (hidden "-" default "\
+group now hidden; click on the asterisks above to show contents.")
+ (invalid "x" custom-invalid-face "\
+the value displayed for this item is invalid and cannot be set.")
+ (modified "*" custom-modified-face "\
+you have edited something in this group, and can now set it.")
+ (set "+" custom-set-face "\
+something in this group has been set, but not yet saved.")
+ (changed ":" custom-changed-face "\
+this item has been changed outside customize.")
+ (saved "!" custom-saved-face "\
+something in this group has been set and saved.")
+ (rogue "@" custom-rogue-face "\
+this item is not prepared for customization.")
+ (factory " " nil "\
+nothing in this group has been changed."))
+ "Alist of customize option states.
+Each entry is of the form (STATE MAGIC FACE DESCRIPTION), where
+
+STATE is one of the following symbols:
+
+`nil'
+ For internal use, should never occur.
+`unknown'
+ For internal use, should never occur.
+`hidden'
+ This item is not being displayed.
+`invalid'
+ This item is modified, but has an invalid form.
+`modified'
+ This item is modified, and has a valid form.
+`set'
+ This item has been set but not saved.
+`changed'
+ The current value of this item has been changed temporarily.
+`saved'
+ This item is marked for saving.
+`rogue'
+ This item has no customization information.
+`factory'
+ This item is unchanged from the standard setting.
+
+MAGIC is a string used to present that state.
+
+FACE is a face used to present the state.
+
+DESCRIPTION is a string describing the state.
+
+The list should be sorted most significant first."
+ :type '(list (checklist :inline t
+ (group (const nil)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const unknown)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const hidden)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const invalid)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const modified)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const set)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const changed)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const saved)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const rogue)
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))
+ (group (const factory)
+ (string :tag "Magic")
+ face
+ (string :tag "Description")))
+ (editable-list :inline t
+ (group symbol
+ (string :tag "Magic")
+ face
+ (string :tag "Description"))))
+ :group 'customize
+ :group 'custom-faces)
(defcustom custom-magic-show 'long
"Show long description of the state of each customization option."
"Show and manipulate state for a customization option."
:format "%v"
:action 'widget-choice-item-action
+ :notify 'ignore
:value-get 'ignore
:value-create 'custom-magic-value-create
:value-delete 'widget-children-value-delete)
;; Create compact status report for WIDGET.
(let* ((parent (widget-get widget :parent))
(state (widget-get parent :custom-state))
- (entry (assq state custom-magic-alist))
+ (entry (assq state (if (eq (car parent) 'custom-group)
+ custom-group-magic-alist
+ custom-magic-alist)))
(magic (nth 1 entry))
(face (nth 2 entry))
(text (nth 3 entry))
(defun custom-level-action (widget &optional event)
"Toggle visibility for parent to WIDGET."
- (let* ((parent (widget-get widget :parent))
- (state (widget-get parent :custom-state)))
- (cond ((memq state '(invalid modified))
- (error "There are unset changes"))
- ((eq state 'hidden)
- (widget-put parent :custom-state 'unknown))
- (t
- (widget-put parent :custom-state 'hidden)))
- (custom-redraw parent)))
+ (custom-toggle-hide (widget-get widget :parent)))
;;; The `custom' Widget.
(defun custom-redraw (widget)
"Redraw WIDGET with current settings."
- (let ((pos (point))
+ (let ((line (count-lines (point-min) (point)))
+ (column (current-column))
+ (pos (point))
(from (marker-position (widget-get widget :from)))
(to (marker-position (widget-get widget :to))))
(save-excursion
(widget-value-set widget (widget-value widget))
(custom-redraw-magic widget))
(when (and (>= pos from) (<= pos to))
- (goto-char pos))))
+ (condition-case nil
+ (progn
+ (goto-line line)
+ (move-to-column column))
+ (error nil)))))
(defun custom-redraw-magic (widget)
"Redraw WIDGET state with current settings."
(t
(funcall show widget value)))))
+(defvar custom-load-recursion nil
+ "Hack to avoid recursive dependencies.")
+
(defun custom-load-symbol (symbol)
"Load all dependencies for SYMBOL."
- (let ((loads (get symbol 'custom-loads))
- load)
- (while loads
- (setq load (car loads)
- loads (cdr loads))
- (cond ((symbolp load)
- (condition-case nil
- (require load)
- (error nil)))
- ((assoc load load-history))
- (t
- (condition-case nil
- (load-library load)
- (error nil)))))))
+ (unless custom-load-recursion
+ (let ((custom-load-recursion t)
+ (loads (get symbol 'custom-loads))
+ load)
+ (while loads
+ (setq load (car loads)
+ loads (cdr loads))
+ (cond ((symbolp load)
+ (condition-case nil
+ (require load)
+ (error nil)))
+ ((assoc load load-history))
+ (t
+ (condition-case nil
+ (load-library load)
+ (error nil))))))))
(defun custom-load-widget (widget)
"Load all dependencies for WIDGET."
(custom-load-symbol (widget-value widget)))
+(defun custom-toggle-hide (widget)
+ "Toggle visibility of WIDGET."
+ (let ((state (widget-get widget :custom-state)))
+ (cond ((memq state '(invalid modified))
+ (error "There are unset changes"))
+ ((eq state 'hidden)
+ (widget-put widget :custom-state 'unknown))
+ (t
+ (widget-put widget :custom-state 'hidden)))
+ (custom-redraw widget)))
+
;;; The `custom-variable' Widget.
(defface custom-variable-sample-face '((t (:underline t)))
"Face used for unpushable variable tags."
- :group 'customize)
+ :group 'custom-faces)
(defface custom-variable-button-face '((t (:underline t :bold t)))
"Face used for pushable variable tags."
- :group 'customize)
+ :group 'custom-faces)
(define-widget 'custom-variable 'custom
"Customize variable."
:custom-reset-saved 'custom-variable-reset-saved
:custom-reset-factory 'custom-variable-reset-factory)
+(defun custom-variable-type (symbol)
+ "Return a widget suitable for editing the value of SYMBOL.
+If SYMBOL has a `custom-type' property, use that.
+Otherwise, look up symbol in `custom-guess-type-alist'."
+ (let* ((type (or (get symbol 'custom-type)
+ (and (not (get symbol 'factory-value))
+ (custom-guess-type symbol))
+ 'sexp))
+ (options (get symbol 'custom-options))
+ (tmp (if (listp type)
+ (copy-sequence type)
+ (list type))))
+ (when options
+ (widget-put tmp :options options))
+ tmp))
+
(defun custom-variable-value-create (widget)
"Here is where you edit the variables value."
(custom-load-widget widget)
(form (widget-get widget :custom-form))
(state (widget-get widget :custom-state))
(symbol (widget-get widget :value))
- (options (get symbol 'custom-options))
- (child-type (or (get symbol 'custom-type) 'sexp))
(tag (widget-get widget :tag))
- (type (let ((tmp (if (listp child-type)
- (copy-list child-type)
- (list child-type))))
- (when options
- (widget-put tmp :options options))
- tmp))
+ (type (custom-variable-type symbol))
(conv (widget-convert type))
+ (get (or (get symbol 'custom-get) 'default-value))
+ (set (or (get symbol 'custom-set) 'set-default))
(value (if (default-boundp symbol)
- (default-value symbol)
+ (funcall get symbol)
(widget-get conv :value))))
;; If the widget is new, the child determine whether it is hidden.
(cond (state)
((get symbol 'factory-value)
(car (get symbol 'factory-value)))
((default-boundp symbol)
- (custom-quote (default-value symbol)))
+ (custom-quote (funcall get symbol)))
(t
(custom-quote (widget-get conv :value))))))
(push (widget-create-child-and-convert
(defun custom-variable-state-set (widget)
"Set the state of WIDGET."
(let* ((symbol (widget-value widget))
+ (get (or (get symbol 'custom-get) 'default-value))
(value (if (default-boundp symbol)
- (default-value symbol)
+ (funcall get symbol)
(widget-get widget :value)))
tmp
(state (cond ((setq tmp (get symbol 'customized-value))
(widget-put widget :custom-state state)))
(defvar custom-variable-menu
- '(("Edit" . custom-variable-edit)
- ("Edit Lisp" . custom-variable-edit-lisp)
- ("Set" . custom-variable-set)
- ("Save" . custom-variable-save)
- ("Reset to Current" . custom-redraw)
- ("Reset to Saved" . custom-variable-reset-saved)
- ("Reset to Factory Settings" . custom-variable-reset-factory))
+ '(("Hide" custom-toggle-hide
+ (lambda (widget)
+ (not (memq (widget-get widget :custom-state) '(modified invalid)))))
+ ("Edit" custom-variable-edit
+ (lambda (widget)
+ (not (eq (widget-get widget :custom-form) 'edit))))
+ ("Edit Lisp" custom-variable-edit-lisp
+ (lambda (widget)
+ (not (eq (widget-get widget :custom-form) 'lisp))))
+ ("Set" custom-variable-set
+ (lambda (widget)
+ (eq (widget-get widget :custom-state) 'modified)))
+ ("Save" custom-variable-save
+ (lambda (widget)
+ (memq (widget-get widget :custom-state) '(modified set changed rogue))))
+ ("Reset to Current" custom-redraw
+ (lambda (widget)
+ (and (default-boundp (widget-value widget))
+ (memq (widget-get widget :custom-state) '(modified)))))
+ ("Reset to Saved" custom-variable-reset-saved
+ (lambda (widget)
+ (and (get (widget-value widget) 'saved-value)
+ (memq (widget-get widget :custom-state)
+ '(modified set changed rogue)))))
+ ("Reset to Standard Settings" custom-variable-reset-factory
+ (lambda (widget)
+ (and (get (widget-value widget) 'factory-value)
+ (memq (widget-get widget :custom-state)
+ '(modified set changed saved rogue))))))
"Alist of actions for the `custom-variable' widget.
-The key is a string containing the name of the action, the value is a
-lisp function taking the widget as an element which will be called
-when the action is chosen.")
+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
+menu is selected, and FILTER is a predicate which takes a `custom-variable'
+widget as an argument, and returns non-nil if ACTION is valid on that
+widget. If FILTER is nil, ACTION is always valid.")
(defun custom-variable-action (widget &optional event)
"Show the menu for `custom-variable' WIDGET.
Optional EVENT is the location for the menu."
(if (eq (widget-get widget :custom-state) 'hidden)
- (progn
- (widget-put widget :custom-state 'unknown)
- (custom-redraw widget))
+ (custom-toggle-hide widget)
(let* ((completion-ignore-case t)
(answer (widget-choose (custom-unlispify-tag-name
(widget-get widget :value))
- custom-variable-menu
+ (custom-menu-filter custom-variable-menu
+ widget)
event)))
(if answer
(funcall answer widget)))))
(defun custom-variable-set (widget)
"Set the current 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)))
- (symbol (widget-value widget))
- val)
+ (let* ((form (widget-get widget :custom-form))
+ (state (widget-get widget :custom-state))
+ (child (car (widget-get widget :children)))
+ (symbol (widget-value widget))
+ (set (or (get symbol 'custom-set) 'set-default))
+ val)
(cond ((eq state 'hidden)
(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)
- (set symbol (eval (setq val (widget-value child))))
+ (funcall set symbol (eval (setq val (widget-value child))))
(put symbol 'customized-value (list val)))
(t
- (set symbol (setq val (widget-value child)))
+ (funcall set symbol (setq val (widget-value child)))
(put symbol 'customized-value (list (custom-quote val)))))
(custom-variable-state-set widget)
(custom-redraw-magic widget)))
(defun custom-variable-save (widget)
"Set the default 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)))
- (symbol (widget-value widget))
- val)
+ (let* ((form (widget-get widget :custom-form))
+ (state (widget-get widget :custom-state))
+ (child (car (widget-get widget :children)))
+ (symbol (widget-value widget))
+ (set (or (get symbol 'custom-set) 'set-default))
+ val)
(cond ((eq state 'hidden)
(error "Cannot set hidden variable."))
((setq val (widget-apply child :validate))
(error "%s" (widget-get val :error)))
((eq form 'lisp)
(put symbol 'saved-value (list (widget-value child)))
- (set symbol (eval (widget-value child))))
+ (funcall set symbol (eval (widget-value child))))
(t
(put symbol
'saved-value (list (custom-quote (widget-value
child))))
- (set symbol (widget-value child))))
+ (funcall set symbol (widget-value child))))
(put symbol 'customized-value nil)
(custom-save-all)
(custom-variable-state-set widget)
(defun custom-variable-reset-saved (widget)
"Restore the saved value for the variable being edited by WIDGET."
- (let ((symbol (widget-value widget)))
+ (let* ((symbol (widget-value widget))
+ (set (or (get symbol 'custom-set) 'set-default)))
(if (get symbol 'saved-value)
(condition-case nil
- (set symbol (eval (car (get symbol 'saved-value))))
+ (funcall set symbol (eval (car (get symbol 'saved-value))))
(error nil))
(error "No saved value for %s" symbol))
(put symbol 'customized-value nil)
(custom-redraw widget)))
(defun custom-variable-reset-factory (widget)
- "Restore the factory setting for the variable being edited by WIDGET."
- (let ((symbol (widget-value widget)))
+ "Restore the standard setting for the variable being edited by WIDGET."
+ (let* ((symbol (widget-value widget))
+ (set (or (get symbol 'custom-set) 'set-default)))
(if (get symbol 'factory-value)
- (set symbol (eval (car (get symbol 'factory-value))))
- (error "No factory default for %S" symbol))
+ (funcall set symbol (eval (car (get symbol 'factory-value))))
+ (error "No standard setting known for %S" symbol))
(put symbol 'customized-value nil)
(when (get symbol 'saved-value)
(put symbol 'saved-value nil)
(defface custom-face-tag-face '((t (:underline t)))
"Face used for face tags."
- :group 'customize)
+ :group 'custom-faces)
(define-widget 'custom-face 'custom
"Customize face."
(defun custom-display-unselected-match (widget value)
"Non-nil if VALUE is an unselected display specification."
- (and (listp value)
- (eq (length value) 2)
- (not (custom-display-match-frame value (selected-frame)))))
+ (not (custom-display-match-frame value (selected-frame))))
(define-widget 'custom-face-selected 'group
"Edit the attributes of the selected display in a face specification."
(message "Creating face editor...done")))
(defvar custom-face-menu
- '(("Edit Selected" . custom-face-edit-selected)
- ("Edit All" . custom-face-edit-all)
- ("Edit Lisp" . custom-face-edit-lisp)
- ("Set" . custom-face-set)
- ("Save" . custom-face-save)
- ("Reset to Saved" . custom-face-reset-saved)
- ("Reset to Factory Setting" . custom-face-reset-factory))
+ '(("Hide" custom-toggle-hide
+ (lambda (widget)
+ (not (memq (widget-get widget :custom-state) '(modified invalid)))))
+ ("Edit Selected" custom-face-edit-selected
+ (lambda (widget)
+ (not (eq (widget-get widget :custom-form) 'selected))))
+ ("Edit All" custom-face-edit-all
+ (lambda (widget)
+ (not (eq (widget-get widget :custom-form) 'all))))
+ ("Edit Lisp" custom-face-edit-lisp
+ (lambda (widget)
+ (not (eq (widget-get widget :custom-form) 'lisp))))
+ ("Set" custom-face-set)
+ ("Save" custom-face-save)
+ ("Reset to Saved" custom-face-reset-saved
+ (lambda (widget)
+ (get (widget-value widget) 'saved-face)))
+ ("Reset to Standard Setting" custom-face-reset-factory
+ (lambda (widget)
+ (get (widget-value widget) 'factory-face))))
"Alist of actions for the `custom-face' widget.
-The key is a string containing the name of the action, the value is a
-lisp function taking the widget as an element which will be called
-when the action is chosen.")
+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
+menu is selected, and FILTER is a predicate which takes a `custom-face'
+widget as an argument, and returns non-nil if ACTION is valid on that
+widget. If FILTER is nil, ACTION is always valid.")
(defun custom-face-edit-selected (widget)
"Edit selected attributes of the value of WIDGET."
"Show the menu for `custom-face' WIDGET.
Optional EVENT is the location for the menu."
(if (eq (widget-get widget :custom-state) 'hidden)
- (progn
- (widget-put widget :custom-state 'unknown)
- (custom-redraw widget))
+ (custom-toggle-hide widget)
(let* ((completion-ignore-case t)
(symbol (widget-get widget :value))
(answer (widget-choose (custom-unlispify-tag-name symbol)
- custom-face-menu event)))
+ (custom-menu-filter custom-face-menu
+ widget)
+ event)))
(if answer
(funcall answer widget)))))
(child (car (widget-get widget :children)))
(value (widget-value child)))
(put symbol 'customized-face value)
- (when (fboundp 'copy-face)
- (copy-face 'custom-face-empty symbol))
(custom-face-display-set symbol value)
(custom-face-state-set widget)
(custom-redraw-magic widget)))
(let* ((symbol (widget-value widget))
(child (car (widget-get widget :children)))
(value (widget-value child)))
- (when (fboundp 'copy-face)
- (copy-face 'custom-face-empty symbol))
(custom-face-display-set symbol value)
(put symbol 'saved-face value)
(put symbol 'customized-face nil)
(unless value
(error "No saved value for this face"))
(put symbol 'customized-face nil)
- (when (fboundp 'copy-face)
- (copy-face 'custom-face-empty symbol))
(custom-face-display-set symbol value)
(widget-value-set child value)
(custom-face-state-set widget)
(custom-redraw-magic widget)))
(defun custom-face-reset-factory (widget)
- "Restore WIDGET to the face's factory settings."
+ "Restore WIDGET to the face's standard settings."
(let* ((symbol (widget-value widget))
(child (car (widget-get widget :children)))
(value (get symbol 'factory-face)))
(unless value
- (error "No factory default for this face"))
+ (error "No standard setting for this face"))
(put symbol 'customized-face nil)
(when (get symbol 'saved-face)
(put symbol 'saved-face nil)
(custom-save-all))
- (when (fboundp 'copy-face)
- (copy-face 'custom-face-empty symbol))
(custom-face-display-set symbol value)
(widget-value-set child value)
(custom-face-state-set widget)
and so forth. The remaining group tags are shown with
`custom-group-tag-face'."
:type '(repeat face)
- :group 'customize)
+ :group 'custom-faces)
(defface custom-group-tag-face-1 '((((class color)
(background dark))
(:foreground "blue" :underline t))
(t (:underline t)))
"Face used for low level group tags."
- :group 'customize)
+ :group 'custom-faces)
(define-widget 'custom-group 'custom
"Customize group."
(message "Creating group... done")))))
(defvar custom-group-menu
- '(("Set" . custom-group-set)
- ("Save" . custom-group-save)
- ("Reset to Current" . custom-group-reset-current)
- ("Reset to Saved" . custom-group-reset-saved)
- ("Reset to Factory" . custom-group-reset-factory))
+ '(("Hide" custom-toggle-hide
+ (lambda (widget)
+ (not (memq (widget-get widget :custom-state) '(modified invalid)))))
+ ("Set" custom-group-set
+ (lambda (widget)
+ (eq (widget-get widget :custom-state) 'modified)))
+ ("Save" custom-group-save
+ (lambda (widget)
+ (memq (widget-get widget :custom-state) '(modified set))))
+ ("Reset to Current" custom-group-reset-current
+ (lambda (widget)
+ (and (default-boundp (widget-value widget))
+ (memq (widget-get widget :custom-state) '(modified)))))
+ ("Reset to Saved" custom-group-reset-saved
+ (lambda (widget)
+ (and (get (widget-value widget) 'saved-value)
+ (memq (widget-get widget :custom-state) '(modified set)))))
+ ("Reset to Standard Settings" custom-group-reset-factory
+ (lambda (widget)
+ (and (get (widget-value widget) 'factory-value)
+ (memq (widget-get widget :custom-state) '(modified set saved))))))
"Alist of actions for the `custom-group' widget.
-The key is a string containing the name of the action, the value is a
-lisp function taking the widget as an element which will be called
-when the action is chosen.")
+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
+menu is selected, and FILTER is a predicate which takes a `custom-group'
+widget as an argument, and returns non-nil if ACTION is valid on that
+widget. If FILTER is nil, ACTION is always valid.")
(defun custom-group-action (widget &optional event)
"Show the menu for `custom-group' WIDGET.
Optional EVENT is the location for the menu."
(if (eq (widget-get widget :custom-state) 'hidden)
- (progn
- (widget-put widget :custom-state 'unknown)
- (custom-redraw widget))
+ (custom-toggle-hide widget)
(let* ((completion-ignore-case t)
(answer (widget-choose (custom-unlispify-tag-name
(widget-get widget :value))
- custom-group-menu
+ (custom-menu-filter custom-group-menu
+ widget)
event)))
(if answer
(funcall answer widget)))))
(states (mapcar (lambda (child)
(widget-get child :custom-state))
children))
- (magics custom-magic-alist)
+ (magics custom-group-magic-alist)
(found 'factory))
(while magics
(let ((magic (car (car magics))))
(princ "\n"))
(princ "(custom-set-variables")
(mapatoms (lambda (symbol)
- (let ((value (get symbol 'saved-value)))
+ (let ((value (get symbol 'saved-value))
+ (requests (get symbol 'custom-requests))
+ (now (not (or (get symbol 'factory-value)
+ (and (not (boundp symbol))
+ (not (get symbol 'force-value)))))))
(when value
(princ "\n '(")
(princ symbol)
(princ " ")
(prin1 (car value))
- (if (or (get symbol 'factory-value)
- (and (not (boundp symbol))
- (not (get symbol 'force-value))))
- (princ ")")
- (princ " t)"))))))
+ (cond (requests
+ (if now
+ (princ " t ")
+ (princ " nil "))
+ (prin1 requests)
+ (princ ")"))
+ (now
+ (princ " t)"))
+ (t
+ (princ ")")))))))
(princ ")")
(unless (looking-at "\n")
(princ "\n")))))
(unless (bolp)
(princ "\n"))
(princ "(custom-set-faces")
+ (let ((value (get 'default 'saved-face)))
+ ;; The default face must be first, since it affects the others.
+ (when value
+ (princ "\n '(default ")
+ (prin1 value)
+ (if (or (get 'default 'factory-face)
+ (and (not (custom-facep 'default))
+ (not (get 'default 'force-face))))
+ (princ ")")
+ (princ " t)"))))
(mapatoms (lambda (symbol)
(let ((value (get symbol 'saved-face)))
- (when value
+ (when (and (not (eq symbol 'default))
+ ;; Don't print default face here.
+ value)
(princ "\n '(")
(princ symbol)
(princ " ")
(unless (looking-at "\n")
(princ "\n")))))
+;;;###autoload
+(defun custom-save-customized ()
+ "Save all user options which have been set in this session."
+ (interactive)
+ (mapatoms (lambda (symbol)
+ (let ((face (get symbol 'customized-face))
+ (value (get symbol 'customized-value)))
+ (when face
+ (put symbol 'saved-face face)
+ (put symbol 'customized-face nil))
+ (when value
+ (put symbol 'saved-value value)
+ (put symbol 'customized-value nil)))))
+ ;; We really should update all custom buffers here.
+ (custom-save-all))
+
;;;###autoload
(defun custom-save-all ()
"Save all customizations in `custom-file'."
;;; The Customize Menu.
-(defcustom custom-menu-nesting 2
- "Maximum nesting in custom menus."
- :type 'integer
- :group 'customize)
+;;; Menu support
+
+(unless (string-match "XEmacs" emacs-version)
+ (defconst custom-help-menu '("Customize"
+ ["Update menu..." custom-menu-update t]
+ ["Group..." customize t]
+ ["Variable..." customize-variable t]
+ ["Face..." customize-face t]
+ ["Saved..." customize-customized t]
+ ["Apropos..." customize-apropos 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
+ :group 'customize))
(defun custom-face-menu-create (widget symbol)
"Ignoring WIDGET, create a menu entry for customization face SYMBOL."
`(custom-buffer-create '((,symbol custom-variable)))
t))))
+;; Add checkboxes to boolean variable entries.
(widget-put (get 'boolean 'widget-type)
:custom-menu (lambda (widget symbol)
(vector (custom-unlispify-menu-entry symbol)
(let ((custom-menu-nesting (1- custom-menu-nesting)))
(custom-menu-create symbol))))
-(defun custom-menu-create (symbol &optional name)
+;;;###autoload
+(defun custom-menu-create (symbol)
"Create menu for customization group SYMBOL.
-If optional NAME is given, use that as the name of the menu.
-Otherwise make up a name from SYMBOL.
The menu is in a format applicable to `easy-menu-define'."
- (unless name
- (setq name (custom-unlispify-menu-entry symbol)))
- (let ((item (vector name
- `(custom-buffer-create '((,symbol custom-group)))
- t)))
- (if (and (>= custom-menu-nesting 0)
+ (let* ((item (vector (custom-unlispify-menu-entry symbol)
+ `(custom-buffer-create '((,symbol custom-group)))
+ t)))
+ (if (and (or (not (boundp 'custom-menu-nesting))
+ (>= custom-menu-nesting 0))
(< (length (get symbol 'custom-group)) widget-menu-max-size))
(let ((custom-prefix-list (custom-prefix-add symbol
custom-prefix-list)))
item)))
;;;###autoload
-(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)))))
-
-;;; Dependencies.
+(defun customize-menu-create (symbol &optional name)
+ "Return a customize menu for customization group SYMBOL.
+If optional NAME is given, use that as the name of the menu.
+Otherwise the menu will be named `Customize'.
+The format is suitable for use with `easy-menu-define'."
+ (unless name
+ (setq name "Customize"))
+ (if (string-match "XEmacs" emacs-version)
+ ;; We can delay it under XEmacs.
+ `(,name
+ :filter (lambda (&rest junk)
+ (cdr (custom-menu-create ',symbol))))
+ ;; But we must create it now under Emacs.
+ (cons name (cdr (custom-menu-create symbol)))))
-;;;###autoload
-(defun custom-make-dependencies ()
- "Batch function to extract custom dependencies from .el files.
-Usage: emacs -batch *.el -f custom-make-dependencies > deps.el"
- (let ((buffers (buffer-list)))
- (while buffers
- (set-buffer (car buffers))
- (setq buffers (cdr buffers))
- (let ((file (buffer-file-name)))
- (when (and file (string-match "\\`\\(.*\\)\\.el\\'" file))
- (goto-char (point-min))
- (condition-case nil
- (let ((name (file-name-nondirectory (match-string 1 file))))
- (while t
- (let ((expr (read (current-buffer))))
- (when (and (listp expr)
- (memq (car expr) '(defcustom defface defgroup)))
- (eval expr)
- (put (nth 1 expr) 'custom-where name)))))
- (error nil))))))
- (mapatoms (lambda (symbol)
- (let ((members (get symbol 'custom-group))
- item where found)
- (when members
- (princ "(put '")
- (princ symbol)
- (princ " 'custom-loads '(")
- (while members
- (setq item (car (car members))
- members (cdr members)
- where (get item 'custom-where))
- (unless (or (null where)
- (member where found))
- (when found
- (princ " "))
- (prin1 where)
- (push where found)))
- (princ "))\n"))))))
+;;; The Custom Mode.
+
+(defvar custom-mode-map nil
+ "Keymap for `custom-mode'.")
+
+(unless custom-mode-map
+ (setq custom-mode-map (make-sparse-keymap))
+ (set-keymap-parent custom-mode-map widget-keymap)
+ (define-key custom-mode-map "q" 'bury-buffer))
+
+(easy-menu-define custom-mode-customize-menu
+ custom-mode-map
+ "Menu used to customize customization buffers."
+ (customize-menu-create 'customize))
+
+(easy-menu-define custom-mode-menu
+ custom-mode-map
+ "Menu used in customization buffers."
+ `("Custom"
+ ["Set" custom-set t]
+ ["Save" custom-save t]
+ ["Reset to Current" custom-reset-current t]
+ ["Reset to Saved" custom-reset-saved t]
+ ["Reset to Standard Settings" custom-reset-factory t]
+ ["Info" (Info-goto-node "(custom)The Customization Buffer") t]))
+
+(defcustom custom-mode-hook nil
+ "Hook called when entering custom-mode."
+ :type 'hook
+ :group 'customize)
+
+(defun custom-mode ()
+ "Major mode for editing customization buffers.
+
+The following commands are available:
+
+Move to next button or editable field. \\[widget-forward]
+Move to previous button or editable field. \\[widget-backward]
+Activate button under the mouse pointer. \\[widget-button-click]
+Activate button under point. \\[widget-button-press]
+Set all modifications. \\[custom-set]
+Make all modifications default. \\[custom-save]
+Reset all modified options. \\[custom-reset-current]
+Reset all modified or set options. \\[custom-reset-saved]
+Reset all options. \\[custom-reset-factory]
+
+Entry to this mode calls the value of `custom-mode-hook'
+if that value is non-nil."
+ (kill-all-local-variables)
+ (setq major-mode 'custom-mode
+ mode-name "Custom")
+ (use-local-map custom-mode-map)
+ (easy-menu-add custom-mode-customize-menu)
+ (easy-menu-add custom-mode-menu)
+ (make-local-variable 'custom-options)
+ (run-hooks 'custom-mode-hook))
;;; The End.