-;;; 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 <abraham@dina.kvl.dk>
;; Keywords: help, faces
-;; Version: 1.9929
+;; Version: 1.9954
;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
;; This file is part of GNU Emacs.
: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)
(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-"
:group 'customize
:group 'faces)
+(defgroup custom-browse nil
+ "Control customize browser."
+ :prefix "custom-"
+ :group 'customize)
+
(defgroup custom-buffer nil
- "Control the customize buffers."
+ "Control customize buffers."
:prefix "custom-"
:group 'customize)
(defgroup custom-menu nil
- "Control how the customize menus."
+ "Control customize menus."
:prefix "custom-"
:group 'customize)
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)))))
: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)
(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
;;; Sorting.
+(defcustom custom-browse-sort-alphabetically nil
+ "If non-nil, sort members of each customization group alphabetically."
+ :type 'boolean
+ :group 'custom-browse)
+
+(defcustom custom-browse-order-groups nil
+ "If non-nil, order group members within each customization group.
+If `first', order groups before non-groups.
+If `last', order groups after non-groups."
+ :type '(choice (const first)
+ (const last)
+ (const :tag "none" nil))
+ :group 'custom-browse)
+
+(defcustom custom-browse-only-groups nil
+ "If non-nil, show group members only within each customization group."
+ :type 'boolean
+ :group 'custom-browse)
+
(defcustom custom-buffer-sort-alphabetically nil
- "If non-nil, sort the members of each customization group alphabetically."
+ "If non-nil, sort members of each customization group alphabetically."
:type 'boolean
:group 'custom-buffer)
-(defcustom custom-buffer-groups-last nil
- "If non-nil, put subgroups after all ordinary options within a group."
- :type 'boolean
+(defcustom custom-buffer-order-groups 'last
+ "If non-nil, order group members within each customization group.
+If `first', order groups before non-groups.
+If `last', order groups after non-groups."
+ :type '(choice (const first)
+ (const last)
+ (const :tag "none" nil))
:group 'custom-buffer)
(defcustom custom-menu-sort-alphabetically nil
- "If non-nil, sort the members of each customization group alphabetically."
+ "If non-nil, sort members of each customization group alphabetically."
:type 'boolean
:group 'custom-menu)
-(defcustom custom-menu-groups-first t
- "If non-nil, put subgroups before all ordinary options within a group."
- :type 'boolean
+(defcustom custom-menu-order-groups 'first
+ "If non-nil, order group members within each customization group.
+If `first', order groups before non-groups.
+If `last', order groups after non-groups."
+ :type '(choice (const first)
+ (const last)
+ (const :tag "none" nil))
:group 'custom-menu)
-(defun custom-buffer-sort-predicate (a b)
- "Return t iff A should come before B in a customization buffer.
-A and B should be members of a `custom-group' property."
- (cond ((and (not custom-buffer-groups-last)
- (not custom-buffer-sort-alphabetically))
- nil)
- ((or (eq (eq (nth 1 a) 'custom-group) (eq (nth 1 b) 'custom-group))
- (not custom-buffer-groups-last))
- (if custom-buffer-sort-alphabetically
- (string-lessp (symbol-name (nth 0 a)) (symbol-name (nth 0 b)))
- nil))
- (t
- (not (eq (nth 1 a) 'custom-group) ))))
-
-(defun custom-menu-sort-predicate (a b)
- "Return t iff A should come before B in a customization menu.
-A and B should be members of a `custom-group' property."
- (cond ((and (not custom-menu-groups-first)
- (not custom-menu-sort-alphabetically))
- nil)
- ((or (eq (eq (nth 1 a) 'custom-group) (eq (nth 1 b) 'custom-group))
- (not custom-menu-groups-first))
- (if custom-menu-sort-alphabetically
- (string-lessp (symbol-name (nth 0 a)) (symbol-name (nth 0 b)))
- nil))
- (t
- (eq (nth 1 a) 'custom-group) )))
+;;;###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.
+If SORT-ALPHABETICALLY non-nil, sort alphabetically.
+If ORDER-GROUPS is `first' order groups before non-groups, if `last' order
+groups after non-groups, if nil do not order groups at all."
+ (sort (copy-sequence items)
+ (lambda (a b)
+ (let ((typea (nth 1 a)) (typeb (nth 1 b))
+ (namea (symbol-name (nth 0 a))) (nameb (symbol-name (nth 0 b))))
+ (cond ((not order-groups)
+ ;; Since we don't care about A and B order, maybe sort.
+ (when sort-alphabetically
+ (string-lessp namea nameb)))
+ ((eq typea 'custom-group)
+ ;; If B is also a group, maybe sort. Otherwise, order A and B.
+ (if (eq typeb 'custom-group)
+ (when sort-alphabetically
+ (string-lessp namea nameb))
+ (eq order-groups 'first)))
+ ((eq typeb 'custom-group)
+ ;; Since A cannot be a group, order A and B.
+ (eq order-groups 'last))
+ (sort-alphabetically
+ ;; Since A and B cannot be groups, sort.
+ (string-lessp namea nameb)))))))
;;; Custom Mode Commands.
(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))
"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
(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.
(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)
(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)
(interactive (list (completing-read "Customize face: (default all) "
obarray 'custom-facep)))
(if (or (null symbol) (and (stringp symbol) (zerop (length symbol))))
- (let ((found nil))
- (message "Looking for faces...")
- (mapcar (lambda (symbol)
- (push (list symbol 'custom-face) found))
- (nreverse (mapcar 'intern
- (sort (mapcar 'symbol-name (face-list))
- 'string-lessp))))
-
- (custom-buffer-create found "*Customize Faces*"))
- (if (stringp symbol)
- (setq symbol (intern symbol)))
+ (custom-buffer-create (custom-sort-items
+ (mapcar (lambda (symbol)
+ (list symbol 'custom-face))
+ (face-list))
+ t nil)
+ "*Customize Faces*")
+ (when (stringp symbol)
+ (setq symbol (intern symbol)))
(unless (symbolp symbol)
(error "Should be a symbol %S" symbol))
(custom-buffer-create (list (list symbol 'custom-face))
(and (get symbol 'customized-value)
(boundp symbol)
(push (list symbol 'custom-variable) found))))
- (if found
- (custom-buffer-create found "*Customize Customized*")
- (error "No customized user options"))))
+ (if (not found)
+ (error "No customized user options")
+ (custom-buffer-create (custom-sort-items found t nil)
+ "*Customize Customized*"))))
;;;###autoload
(defun customize-saved ()
(and (get symbol 'saved-value)
(boundp symbol)
(push (list symbol 'custom-variable) found))))
- (if found
- (custom-buffer-create found "*Customize Saved*")
- (error "No saved user options"))))
+ (if (not found )
+ (error "No saved user options")
+ (custom-buffer-create (custom-sort-items found t nil)
+ "*Customize Saved*"))))
;;;###autoload
(defun customize-apropos (regexp &optional all)
(push (list symbol 'custom-variable) found)))))
(if (not found)
(error "No matches")
- (let ((custom-buffer-sort-alphabetically t))
- (custom-buffer-create (sort found 'custom-buffer-sort-predicate)
- "*Customize Apropos*")))))
+ (custom-buffer-create (custom-sort-items found t
+ custom-buffer-order-groups)
+ "*Customize Apropos*"))))
;;;###autoload
(defun customize-apropos-options (regexp &optional arg)
: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
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
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
: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.
-Square brackets show active fields; type RET or click mouse-2
-on an active field to invoke its action. Invoke ")
+ (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. 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."
(message "Creating customization buttons...")
(widget-insert "Operate on everything in this buffer:\n ")
(widget-create 'push-button
- :tag "Set"
- :help-echo "Set all modifications for this session."
+ :tag "Set for Current Session"
+ :help-echo "\
+Make your editing in this buffer take effect for this session."
:action (lambda (widget &optional event)
(Custom-set)))
(widget-insert " ")
(widget-create 'push-button
- :tag "Save"
+ :tag "Save for Future Sessions"
:help-echo "\
-Make the modifications default for future sessions."
+Make your editing in this buffer take effect for future Emacs sessions."
:action (lambda (widget &optional event)
(Custom-save)))
- (widget-insert " ")
(if custom-reset-button-menu
- (widget-create 'push-button
- :tag "Reset"
- :help-echo "Show a menu with reset operations."
- :mouse-down-action (lambda (&rest junk) t)
- :action (lambda (widget &optional event)
- (custom-reset event)))
+ (progn
+ (widget-insert " ")
+ (widget-create 'push-button
+ :tag "Reset"
+ :help-echo "Show a menu with reset operations."
+ :mouse-down-action (lambda (&rest junk) t)
+ :action (lambda (widget &optional event)
+ (custom-reset event))))
+ (widget-insert "\n ")
(widget-create 'push-button
:tag "Reset"
:help-echo "\
-Reset all visible items in this buffer to their current settings."
+Reset all edited text in this buffer to reflect current values."
:action 'Custom-reset-current)
(widget-insert " ")
(widget-create 'push-button
:tag "Reset to Saved"
:help-echo "\
-Reset all visible items in this buffer to their saved settings."
+Reset all values in this buffer to their saved settings."
:action 'Custom-reset-saved)
(widget-insert " ")
(widget-create 'push-button
:tag "Reset to Standard"
:help-echo "\
-Reset all visible items in this buffer to their standard settings."
+Reset all values in this buffer to their standard settings."
:action 'Custom-reset-standard))
(widget-insert " ")
(widget-create 'push-button
(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
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...")
;;; The Tree Browser.
;;;###autoload
-(defun customize-browse ()
+(defun customize-browse (&optional group)
"Create a tree browser for the customize hierarchy."
(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 [+] below to expand items, and [-] to collapse items.
-Invoke the [Group], [Face], and [Option] buttons below to edit that
-item in another window.\n\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")
+ (widget-insert "Invoke the ")
+ (widget-create 'item
+ :format "%t"
+ :tag "[Group]"
+ :tag-glyph "folder")
+ (widget-insert ", ")
+ (widget-create 'item
+ :format "%t"
+ :tag "[Face]"
+ :tag-glyph "face")
+ (widget-insert ", and ")
+ (widget-create 'item
+ :format "%t"
+ :tag "[Option]"
+ :tag-glyph "option")
+ (widget-insert " buttons below to edit that
+item in another window.\n\n"))
(let ((custom-buffer-style 'tree))
(widget-create 'custom-group
:custom-last t
:custom-state 'unknown
- :tag (custom-unlispify-tag-name 'emacs)
- :value 'emacs))
+ :tag (custom-unlispify-tag-name group)
+ :value group))
(goto-char (point-min)))
-(define-widget 'custom-tree-visibility 'item
- "Control visibility of of items in the customize tree browser."
- :button-prefix "["
- :button-suffix "]"
- :format "%[%t%]"
- :action 'custom-tree-visibility-action)
+(define-widget 'custom-browse-visibility 'item
+ "Control visibility of items in the customize tree browser."
+ :format "%[[%t]%]"
+ :action 'custom-browse-visibility-action)
-(defun custom-tree-visibility-action (widget &rest ignore)
+(defun custom-browse-visibility-action (widget &rest ignore)
(let ((custom-buffer-style 'tree))
(custom-toggle-parent widget)))
-(define-widget 'custom-tree-group-tag 'push-button
+(define-widget 'custom-browse-group-tag 'push-button
"Show parent in other window when activated."
:tag "Group"
- :action 'custom-tree-group-tag-action)
+ :tag-glyph "folder"
+ :action 'custom-browse-group-tag-action)
-(defun custom-tree-group-tag-action (widget &rest ignore)
+(defun custom-browse-group-tag-action (widget &rest ignore)
(let ((parent (widget-get widget :parent)))
(customize-group-other-window (widget-value parent))))
-(define-widget 'custom-tree-variable-tag 'push-button
+(define-widget 'custom-browse-variable-tag 'push-button
"Show parent in other window when activated."
:tag "Option"
- :action 'custom-tree-variable-tag-action)
+ :tag-glyph "option"
+ :action 'custom-browse-variable-tag-action)
-(defun custom-tree-variable-tag-action (widget &rest ignore)
+(defun custom-browse-variable-tag-action (widget &rest ignore)
(let ((parent (widget-get widget :parent)))
(customize-variable-other-window (widget-value parent))))
-(define-widget 'custom-tree-face-tag 'push-button
+(define-widget 'custom-browse-face-tag 'push-button
"Show parent in other window when activated."
:tag "Face"
- :action 'custom-tree-face-tag-action)
+ :tag-glyph "face"
+ :action 'custom-browse-face-tag-action)
-(defun custom-tree-face-tag-action (widget &rest ignore)
+(defun custom-browse-face-tag-action (widget &rest ignore)
(let ((parent (widget-get widget :parent)))
(customize-face-other-window (widget-value parent))))
+(defconst custom-browse-alist '((" " "space")
+ (" | " "vertical")
+ ("-\\ " "top")
+ (" |-" "middle")
+ (" `-" "bottom")))
+
+(defun custom-browse-insert-prefix (prefix)
+ "Insert PREFIX. On XEmacs convert it to line graphics."
+ (if nil ; (string-match "XEmacs" emacs-version)
+ (progn
+ (insert "*")
+ (while (not (string-equal prefix ""))
+ (let ((entry (substring prefix 0 3)))
+ (setq prefix (substring prefix 3))
+ (let ((overlay (make-overlay (1- (point)) (point) nil t nil))
+ (name (nth 1 (assoc entry custom-browse-alist))))
+ (overlay-put overlay 'end-glyph (widget-glyph-find name entry))
+ (overlay-put overlay 'start-open t)
+ (overlay-put overlay 'end-open t)))))
+ (insert prefix)))
+
;;; Modification of Basic Widgets.
;;
;; We add extra properties to the basic widgets needed here. This is
(invalid "x" custom-invalid-face "\
the value displayed for this %c is invalid and cannot be set.")
(modified "*" custom-modified-face "\
-you have edited the value, and can now set the %c." "\
-you have edited something in this group, and can now set it.")
+you have edited the value as text, but you have not set the %c." "\
+you have edited something in this group, but not set it.")
(set "+" custom-set-face "\
-you have set this %c, but not saved it." "\
-something in this group has been set, but not yet saved.")
+you have set this %c, but not saved it for future sessions." "\
+something in this group has been set, but not saved.")
(changed ":" custom-changed-face "\
this %c has been changed outside the customize buffer." "\
something in this group has been changed outside customize.")
(defcustom custom-magic-show 'long
"If non-nil, show textual description of the state.
-If non-nil and not the symbol `long', only show first word."
+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)
- "Control whether the state button is shown for hidden items.
-The value should be a list with the custom categories where the state
+ "Control whether the State button is shown for hidden items.
+The value should be a list with the custom categories where the State
button should be visible. Possible categories are `group', `option',
and `face'."
:type '(set (const group) (const option) (const face))
:group 'custom-buffer)
(defcustom custom-magic-show-button nil
- "Show a magic button indicating the state of each customization option."
+ "Show a \"magic\" button indicating the state of each customization option."
:type 'boolean
:group 'custom-buffer)
(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)
:tag "State")
children)
(insert ": ")
- (if (eq custom-magic-show 'long)
- (insert text)
- (insert (symbol-name state)))
- (when lisp
- (insert " (lisp)"))
+ (let ((start (point)))
+ (if (eq custom-magic-show 'long)
+ (insert text)
+ (insert (symbol-name state)))
+ (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)
(not (and (eq custom-buffer-style 'links)
: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)
;;; The `custom' Widget.
+(defface custom-button-face nil
+ "Face used for buttons in customization buffers."
+ :group 'custom-faces)
+
+(defface custom-documentation-face nil
+ "Face used for documentation strings in customization buffers."
+ :group 'custom-faces)
+
+(defface custom-state-face '((((class color)
+ (background dark))
+ (:foreground "lime green"))
+ (((class color)
+ (background light))
+ (:foreground "dark green"))
+ (t nil))
+ "Face used for State descriptions in the customize buffer."
+ :group 'custom-faces)
+
(define-widget 'custom 'default
"Customize a user option."
:format "%v"
(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
"Load all dependencies for WIDGET."
(custom-load-symbol (widget-value widget)))
+(defun custom-unloaded-symbol-p (symbol)
+ "Return non-nil if the dependencies of SYMBOL has not yet been loaded."
+ (let ((found nil)
+ (loads (get symbol 'custom-loads))
+ load)
+ (while loads
+ (setq load (car loads)
+ loads (cdr loads))
+ (cond ((symbolp load)
+ (unless (featurep load)
+ (setq found t)))
+ ((assoc load load-history))
+ ((assoc (locate-library load) load-history)
+ (message nil))
+ (t
+ (setq found t))))
+ found))
+
+(defun custom-unloaded-widget-p (widget)
+ "Return non-nil if the dependencies of WIDGET has not yet been loaded."
+ (custom-unloaded-symbol-p (widget-value widget)))
+
(defun custom-toggle-hide (widget)
"Toggle visibility of WIDGET."
+ (custom-load-widget widget)
(let ((state (widget-get widget :custom-state)))
(cond ((memq state '(invalid modified))
(error "There are unset changes"))
(widget-setup)))
(defun custom-toggle-parent (widget &rest ignore)
- "Toggle visibility of parent to WIDGET."
+ "Toggle visibility of parent of WIDGET."
(custom-toggle-hide (widget-get widget :parent)))
(defun custom-add-see-also (widget &optional prefix)
found)
(insert (or initial-string "Parent groups:"))
(mapatoms (lambda (symbol)
- (let ((group (get symbol 'custom-group)))
- (when (assq name group)
- (when (eq type (nth 1 (assq name group)))
- (insert " ")
- (push (widget-create-child-and-convert
- widget 'custom-group-link
- :tag (custom-unlispify-tag-name symbol)
- symbol)
- buttons)
- (setq found t))))))
+ (let ((entry (assq name (get symbol 'custom-group))))
+ (when (eq (nth 1 entry) type)
+ (insert " ")
+ (push (widget-create-child-and-convert
+ widget 'custom-group-link
+ :tag (custom-unlispify-tag-name symbol)
+ symbol)
+ buttons)
+ (setq found t)))))
(widget-put widget :buttons buttons)
(if found
(insert "\n")
;;; The `custom-variable' Widget.
-(defface custom-variable-sample-face '((t (:underline t)))
+(defface custom-variable-tag-face '((((class color)
+ (background dark))
+ (:foreground "light blue" :underline t))
+ (((class color)
+ (background light))
+ (:foreground "blue" :underline t))
+ (t (:underline t)))
"Face used for unpushable variable tags."
:group 'custom-faces)
"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"
: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
(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))
(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 " +--- " " |--- "))
+ (insert prefix (if last " `--- " " |--- "))
(push (widget-create-child-and-convert
- widget 'custom-tree-variable-tag)
+ widget 'custom-browse-variable-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons))
(push (widget-create-child-and-convert
widget 'item
:format "%{%t%}: "
- :sample-face 'custom-variable-sample-face
+ :sample-face 'custom-variable-tag-face
:tag tag
:parent widget)
buttons)
: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)))
(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
:help-echo "Change value of this option."
:mouse-down-action 'custom-tag-mouse-down-action
:button-face 'custom-variable-button-face
- :sample-face 'custom-variable-sample-face
+ :sample-face 'custom-variable-tag-face
tag)
buttons)
(insert " ")
(widget-put widget :custom-state state)))
(defvar custom-variable-menu
- '(("Set" custom-variable-set
+ '(("Set for Current Session" custom-variable-set
(lambda (widget)
(eq (widget-get widget :custom-state) 'modified)))
- ("Save" custom-variable-save
+ ("Save for Future Sessions" custom-variable-save
(lambda (widget)
(memq (widget-get widget :custom-state) '(modified set changed rogue))))
("Reset to Current" custom-redraw
("---" 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
(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
(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)))
(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
: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.")
"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
: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
(unless tag
(setq tag (prin1-to-string symbol)))
(cond ((eq custom-buffer-style 'tree)
- (insert prefix (if is-last " +--- " " |--- "))
+ (insert prefix (if is-last " `--- " " |--- "))
(push (widget-create-child-and-convert
- widget 'custom-tree-face-tag)
+ widget 'custom-browse-face-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons))
(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)
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
(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)))
(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)))
(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")
(define-widget 'custom-group-link 'link
"Show parent in other window when activated."
- :help-echo "Create customize buffer for this group group."
+ :help-echo "Create customization buffer for this group."
:action 'custom-group-link-action)
(defun custom-group-link-action (widget &rest ignore)
;;; The `custom-group' Widget.
-(defcustom custom-group-tag-faces '(custom-group-tag-face-1)
+(defcustom custom-group-tag-faces nil
;; In XEmacs, this ought to play games with font size.
"Face used for group tags.
The first member is used for level 1 groups, the second for level 2,
(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))
- (insert prefix)
+ (eq state 'hidden)
+ (or members (custom-unloaded-widget-p widget)))
+ (custom-browse-insert-prefix prefix)
(push (widget-create-child-and-convert
- widget 'custom-tree-visibility :tag "+")
+ widget 'custom-browse-visibility
+ ;; :tag-glyph "plus"
+ :tag "+")
buttons)
(insert "-- ")
+ ;; (widget-glyph-insert nil "-- " "horizontal")
(push (widget-create-child-and-convert
- widget 'custom-tree-group-tag)
+ widget 'custom-browse-group-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons))
((and (eq custom-buffer-style 'tree)
- (zerop (length (get symbol 'custom-group))))
- (insert prefix "[ ]-- ")
+ (zerop (length members)))
+ (custom-browse-insert-prefix prefix)
+ (insert "[ ]-- ")
+ ;; (widget-glyph-insert nil "[ ]" "empty")
+ ;; (widget-glyph-insert nil "-- " "horizontal")
(push (widget-create-child-and-convert
- widget 'custom-tree-group-tag)
+ widget 'custom-browse-group-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons))
((eq custom-buffer-style 'tree)
- (insert prefix)
+ (custom-browse-insert-prefix prefix)
(custom-load-widget widget)
- (if (zerop (length (get symbol 'custom-group)))
+ (if (zerop (length members))
(progn
- (insert prefix "[ ]-- ")
+ (custom-browse-insert-prefix prefix)
+ (insert "[ ]-- ")
+ ;; (widget-glyph-insert nil "[ ]" "empty")
+ ;; (widget-glyph-insert nil "-- " "horizontal")
(push (widget-create-child-and-convert
- widget 'custom-tree-group-tag)
+ widget 'custom-browse-group-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons))
(push (widget-create-child-and-convert
- widget 'custom-tree-visibility :tag "-")
+ widget 'custom-browse-visibility
+ ;; :tag-glyph "minus"
+ :tag "-")
buttons)
- (insert "-+ ")
+ (insert "-\\ ")
+ ;; (widget-glyph-insert nil "-\\ " "top")
(push (widget-create-child-and-convert
- widget 'custom-tree-group-tag)
+ widget 'custom-browse-group-tag)
buttons)
(insert " " tag "\n")
(widget-put widget :buttons buttons)
(message "Creating group...")
- (let* ((members (copy-sequence (get symbol 'custom-group)))
+ (let* ((members (custom-sort-items members
+ custom-browse-sort-alphabetically
+ custom-browse-order-groups))
(prefixes (widget-get widget :custom-prefixes))
(custom-prefix-list (custom-prefix-add symbol prefixes))
- (length (length members))
(extra-prefix (if (widget-get widget :custom-last)
" "
" | "))
(push (widget-create-child-and-convert
widget (nth 1 entry)
:group widget
- :tag (custom-unlispify-tag-name
- (nth 0 entry))
+ :tag (custom-unlispify-tag-name (nth 0 entry))
:custom-prefixes custom-prefix-list
:custom-level (1+ level)
:custom-last (null members)
(if (eq custom-buffer-style 'links)
(push (widget-create-child-and-convert
widget 'custom-group-link
- :tag "Show"
+ :tag "Go to Group"
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)))
;; Members.
(message "Creating group...")
(custom-load-widget widget)
- (let* ((members (sort (copy-sequence (get symbol 'custom-group))
- 'custom-buffer-sort-predicate))
+ (let* ((members (custom-sort-items members
+ custom-buffer-sort-alphabetically
+ custom-buffer-order-groups))
(prefixes (widget-get widget :custom-prefixes))
(custom-prefix-list (custom-prefix-add symbol prefixes))
(length (length members))
(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
;;; 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
(princ "\n")))))
;;;###autoload
-(defun custom-save-customized ()
+(defun customize-save-customized ()
"Save all user options which have been set in this session."
(interactive)
(mapatoms (lambda (symbol)
;;;###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]
- ["Group..." customize-group t]
- ["Variable..." customize-variable t]
- ["Face..." customize-face t]
- ["Saved..." customize-saved t]
- ["Set..." customize-customized t]
- ["--" custom-menu-sep t]
- ["Apropos..." customize-apropos t]
- ["Group apropos..." customize-apropos-groups t]
- ["Variable 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
(< (length (get symbol 'custom-group)) widget-menu-max-size))
(let ((custom-prefix-list (custom-prefix-add symbol
custom-prefix-list))
- (members (sort (copy-sequence (get symbol 'custom-group))
- 'custom-menu-sort-predicate)))
+ (members (custom-sort-items (get symbol 'custom-group)
+ custom-menu-sort-alphabetically
+ custom-menu-order-groups)))
(custom-load-symbol symbol)
`(,(custom-unlispify-menu-entry symbol t)
,item
(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)
(suppress-keymap custom-mode-map)
- (define-key custom-mode-map "q" 'bury-buffer))
+ (define-key custom-mode-map " " 'scroll-up)
+ (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)
+ "Move to where you click, and if it is an active field, invoke it."
+ (interactive "e")
+ (mouse-set-point event)
+ (if (widget-event-point event)
+ (let* ((pos (widget-event-point event))
+ (button (get-char-property pos 'button)))
+ (if button
+ (widget-button-click event)))))
(easy-menu-define Custom-mode-menu
custom-mode-map
["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.
+If several parents are listed, go to the first of them."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "\nGo to parent group: " nil t)
+ (let* ((button (get-char-property (point) 'button))
+ (parent (downcase (widget-get button :tag))))
+ (customize-group parent)))))
(defcustom custom-mode-hook nil
"Hook called when entering custom-mode."
:type 'hook
:group 'custom-buffer )
-(defun custom-state-buffer-message ()
- (message "To set the value, invoke [State] and choose the Set operation"))
+(defun custom-state-buffer-message (widget)
+ (if (eq (widget-get (widget-get widget :parent) :custom-state) 'modified)
+ (message "To install your edits, invoke [State] and choose the Set operation")))
(defun custom-mode ()
"Major mode for editing customization buffers.
Move to next button or editable field. \\[widget-forward]
Move to previous button or editable field. \\[widget-backward]
-Invoke button under the mouse pointer. \\[widget-button-click]
+\\<widget-field-keymap>\
+Complete content of editable text field. \\[widget-complete]
+\\<custom-mode-map>\
+Invoke button under the mouse pointer. \\[Custom-move-and-invoke]
Invoke button under point. \\[widget-button-press]
Set all modifications. \\[Custom-set]
Make all modifications default. \\[Custom-save]
(use-local-map custom-mode-map)
(easy-menu-add Custom-mode-menu)
(make-local-variable 'custom-options)
- (make-local-hook 'widget-edit-hook)
- (add-hook 'widget-edit-hook 'custom-state-buffer-message nil t)
+ (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))
;;; The End.