;;; cus-edit.el --- tools for customizing Emacs and Lisp packages
;;
-;; Copyright (C) 1996,97,1999,2000,01,02,03,2004 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+;; Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Maintainer: FSF
;; that interferes with completion. Use `customize-' for commands
;; that the user will run with M-x, and `Custom-' for interactive commands.
+;; The identity of a customize option is represented by a Lisp symbol.
+;; The following values are associated with an option.
+
+;; 0. The current value.
+
+;; This is the value of the option as seen by "the rest of Emacs".
+
+;; Usually extracted by 'default-value', but can be extracted with
+;; different means if the option symbol has the 'custom-get'
+;; property. Similarly, set-default (or the 'custom-set' property)
+;; can set it.
+
+;; 1. The widget value.
+
+;; This is the value shown in the widget in a customize buffer.
+
+;; 2. The customized value.
+
+;; This is the last value given to the option through customize.
+
+;; It is stored in the 'customized-value' property of the option, in a
+;; cons-cell whose car evaluates to the customized value.
+
+;; 3. The saved value.
+
+;; This is last value saved from customize.
+
+;; It is stored in the 'saved-value' property of the option, in a
+;; cons-cell whose car evaluates to the saved value.
+
+;; 4. The standard value.
+
+;; This is the value given in the 'defcustom' declaration.
+
+;; It is stored in the 'standard-value' property of the option, in a
+;; cons-cell whose car evaluates to the standard value.
+
+;; 5. The "think" value.
+
+;; This is what customize thinks the current value should be.
+
+;; This is the customized value, if any such value exists, otherwise
+;; the saved value, if that exists, and as a last resort the standard
+;; value.
+
+;; The reason for storing values unevaluated: This is so you can have
+;; values that depend on the environment. For example, you can have a
+;; variable that has one value when Emacs is running under a window
+;; system, and another value on a tty. Since the evaluation is only done
+;; when the variable is first initialized, this is only relevant for the
+;; saved (and standard) values, but affect others values for
+;; compatibility.
+
+;; You can see (and modify and save) this unevaluated value by selecting
+;; "Show initial Lisp expression" from the Lisp interface. This will
+;; give you the unevaluated saved value, if any, otherwise the
+;; unevaluated standard value.
+
+;; The possible states for a customize widget are:
+
+;; 0. unknown
+
+;; The state has not been determined yet.
+
+;; 1. modified
+
+;; The widget value is different from the current value.
+
+;; 2. changed
+
+;; The current value is different from the "think" value.
+
+;; 3. set
+
+;; The "think" value is the customized value.
+
+;; 4. saved
+
+;; The "think" value is the saved value.
+
+;; 5. standard
+
+;; The "think" value is the standard value.
+
+;; 6. rogue
+
+;; There is no standard value. This means that the variable was
+;; not defined with defcustom, nor handled in cus-start.el. You
+;; can not create a Custom buffer for such variables using the
+;; normal interactive Custom commands. However, such Custom
+;; buffers can be created in other ways, for instance, by calling
+;; `customize-option' non-interactively.
+
+;; 7. hidden
+
+;; There is no widget value.
+
+;; 8. mismatch
+
+;; The widget value is not valid member of the :type specified for the
+;; option.
+
;;; Code:
(require 'cus-face)
(defgroup customize '((widgets custom-group))
"Customization of the Customization support."
- :link '(custom-manual "(elisp)Customization")
:prefix "custom-"
:group 'help)
"Input from the menus."
:group 'environment)
+(defgroup dnd nil
+ "Handling data from drag and drop."
+ :group 'environment)
+
(defgroup auto-save nil
"Preventing accidential loss of data."
:group 'files)
(let ((name (format "*Customize Group: %s*"
(custom-unlispify-tag-name group))))
(if (get-buffer name)
- (let ((window (selected-window))
+ (let (
;; Copied from `custom-buffer-create-other-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 name)
- (select-window window))
+ (pop-to-buffer name))
(custom-buffer-create-other-window
(list (list group 'custom-group))
name
(const links))
:group 'custom-buffer)
-;; If we pass BUFFER to `bury-buffer', the buffer isn't removed from
-;; the window.
-(defun custom-bury-buffer (buffer)
- (with-current-buffer buffer
- (bury-buffer)))
-
-(defcustom custom-buffer-done-function 'custom-bury-buffer
- "*Function called to remove a Custom buffer when the user is done with it.
-Called with one argument, the buffer to remove."
- :type '(choice (function-item :tag "Bury buffer" custom-bury-buffer)
- (function-item :tag "Kill buffer" kill-buffer)
- (function :tag "Other"))
- :version "21.1"
+(defcustom custom-buffer-done-kill nil
+ "*Non-nil means exiting a Custom buffer should kill it."
+ :type 'boolean
+ :version "22.1"
:group 'custom-buffer)
(defcustom custom-buffer-indent 3
;;;###autoload
(defun custom-buffer-create-other-window (options &optional name description)
- "Create a buffer containing OPTIONS.
+ "Create a buffer containing OPTIONS, and display it in another window.
+The result includes selecting that window.
Optional NAME is the name of the buffer.
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."
(unless name (setq name "*Customization*"))
- (let ((window (selected-window))
- (pop-up-windows t)
- (special-display-buffer-names nil)
- (special-display-regexps nil)
+ (let ((pop-up-windows t)
(same-window-buffer-names nil)
(same-window-regexps nil))
(pop-to-buffer (custom-get-fresh-buffer name))
- (custom-buffer-create-internal options description)
- (select-window window)))
+ (custom-buffer-create-internal options description)))
(defcustom custom-reset-button-menu nil
"If non-nil, only show a single reset button in customize buffers.
:group 'custom-buffer)
(defun Custom-buffer-done (&rest ignore)
- "Remove current buffer by calling `custom-buffer-done-function'."
+ "Exit current Custom buffer according to `custom-buffer-done-kill'."
(interactive)
- (funcall custom-buffer-done-function (current-buffer)))
+ (quit-window custom-buffer-done-kill))
(defcustom custom-raised-buttons (not (equal (face-valid-attribute-values :box)
'(("unspecified" . unspecified))))
:group 'custom-buffer)
(defun custom-buffer-create-internal (options &optional description)
- (message "Creating customization buffer...")
(custom-mode)
(if custom-buffer-verbose-help
(progn
(widget-insert (format ".
%s 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 " (if custom-raised-buttons
- "`Raised' buttons"
- "Square brackets")))
+changes only the text in the buffer. Invoke the State button to set or
+save the option value. Saving an option normally edits your init file.
+Invoke "
+ (if custom-raised-buttons
+ "`Raised' buttons"
+ "Square brackets")))
+ (widget-create 'info-link
+ :tag "Custom file"
+ "(emacs)Saving Customizations")
+ (widget-insert
+ " for information on how to save in a different file.
+Invoke ")
(widget-create 'info-link
:tag "Help"
:help-echo "Read the online help."
"(emacs)Easy Customization")
- (widget-insert " for more information.\n\n")
- (message "Creating customization buttons...")
+ (widget-insert " for general information.\n\n")
(widget-insert "Operate on everything in this buffer:\n "))
(widget-insert " "))
(widget-create 'push-button
(widget-create 'push-button
:tag "Save for Future Sessions"
:help-echo "\
-Make your editing in this buffer take effect for future Emacs sessions."
+Make your editing in this buffer take effect for future Emacs sessions.
+This updates your Emacs initialization file or creates a new one."
:action (lambda (widget &optional event)
(Custom-save)))
(if custom-reset-button-menu
:tag "Finish"
:help-echo
(lambda (&rest ignore)
- (cond
- ((eq custom-buffer-done-function
- 'custom-bury-buffer)
- "Bury this buffer")
- ((eq custom-buffer-done-function 'kill-buffer)
- "Kill this buffer")
- (t "Finish with this buffer")))
+ (if custom-buffer-done-kill
+ "Kill this buffer"
+ "Bury this buffer"))
:action #'Custom-buffer-done)
(widget-insert "\n\n")
(message "Creating customization items...")
(unless (eq (preceding-char) ?\n)
(widget-insert "\n"))
(message "Creating customization items ...done")
+ (message "Resetting customization items...")
(unless (eq custom-buffer-style 'tree)
(mapc 'custom-magic-reset custom-options))
+ (message "Resetting customization items...done")
(message "Creating customization setup...")
(widget-setup)
(buffer-enable-undo)
(goto-char (point-min))
- (message "Creating customization buffer...done"))
+ (message "Creating customization setup...done"))
;;; The Tree Browser.
:group 'custom-buffer)
(defface custom-invalid-face '((((class color))
- (:foreground "yellow" :background "red"))
+ (:foreground "yellow1" :background "red1"))
(t
(:weight bold :slant italic :underline t)))
"Face used when the customize item is invalid."
"Face used when the customize item is not defined for customization."
:group 'custom-magic-faces)
-(defface custom-modified-face '((((class color))
+(defface custom-modified-face '((((min-colors 88) (class color))
+ (:foreground "white" :background "blue1"))
+ (((class color))
(:foreground "white" :background "blue"))
(t
(:slant italic :bold)))
"Face used when the customize item has been modified."
:group 'custom-magic-faces)
-(defface custom-set-face '((((class color))
- (:foreground "blue" :background "white"))
- (t
- (:slant italic)))
+(defface custom-set-face '((((min-colors 88) (class color))
+ (:foreground "blue1" :background "white"))
+ (((class color))
+ (:foreground "blue" :background "white"))
+ (t
+ (:slant italic)))
"Face used when the customize item has been set."
:group 'custom-magic-faces)
-(defface custom-changed-face '((((class color))
+(defface custom-changed-face '((((min-colors 88) (class color))
+ (:foreground "white" :background "blue1"))
+ (((class color))
(:foreground "white" :background "blue"))
(t
(:slant italic)))
"Face used when the customize item has been saved."
:group 'custom-magic-faces)
-(defconst custom-magic-alist '((nil "#" underline "\
-uninitialized, you should not see this.")
- (unknown "?" italic "\
-unknown, you should not see this.")
- (hidden "-" default "\
-hidden, invoke \"Show\" in the previous line to show." "\
+(defconst custom-magic-alist
+ '((nil "#" underline "\
+UNINITIALIZED, you should not see this.")
+ (unknown "?" italic "\
+UNKNOWN, you should not see this.")
+ (hidden "-" default "\
+HIDDEN, invoke \"Show\" in the previous line to show." "\
group now hidden, invoke \"Show\", above, to show contents.")
- (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 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 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." "\
+ (invalid "x" custom-invalid-face "\
+INVALID, the displayed value cannot be set.")
+ (modified "*" custom-modified-face "\
+EDITED, shown value does not take effect until you set or save it." "\
+something in this group has been edited but not set.")
+ (set "+" custom-set-face "\
+SET for current session only." "\
+something in this group has been set but not saved.")
+ (changed ":" custom-changed-face "\
+CHANGED outside Customize; operating on it here may be unreliable." "\
something in this group has been changed outside customize.")
- (saved "!" custom-saved-face "\
-this %c has been set and saved." "\
+ (saved "!" custom-saved-face "\
+SAVED and set." "\
something in this group has been set and saved.")
- (rogue "@" custom-rogue-face "\
-this %c has not been changed with customize." "\
+ (rogue "@" custom-rogue-face "\
+NO CUSTOMIZATION DATA; you should not see this." "\
something in this group is not prepared for customization.")
- (standard " " nil "\
-this %c is unchanged from its standard setting." "\
+ (standard " " nil "\
+STANDARD." "\
visible group members are all at standard settings."))
"Alist of customize option states.
Each entry is of the form (STATE MAGIC FACE ITEM-DESC [ GROUP-DESC ]), where
`set'
This item has been set but not saved.
`changed'
- The current value of this item has been changed temporarily.
+ The current value of this item has been changed outside Customize.
`saved'
This item is marked for saving.
`rogue'
`((((class color)
(background dark))
(:foreground "light blue" :weight bold :height 1.2 :inherit variable-pitch))
+ (((min-colors 88) (class color)
+ (background light))
+ (:foreground "blue1" :weight bold :height 1.2 :inherit variable-pitch))
(((class color)
(background light))
- (:foreground "blue" :weight bold :height 1.2 :inherit variable-pitch))
+ (:foreground "blue" :weight bold :height 1.2 :inherit variable-pitch))
(t (:weight bold)))
"Face used for unpushable variable tags."
:group 'custom-faces)
:group 'custom-buffer
:version "20.3")
+(defun custom-variable-documentation (variable)
+ "Return documentation of VARIABLE for use in Custom buffer.
+Normally just return the docstring. But if VARIABLE automatically
+becomes buffer local when set, append a message to that effect."
+ (if (and (local-variable-if-set-p variable)
+ (or (not (local-variable-p variable))
+ (with-temp-buffer
+ (local-variable-if-set-p variable))))
+ (concat (documentation-property variable 'variable-documentation)
+ "\n
+This variable automatically becomes buffer-local when set outside Custom.
+However, setting it through Custom sets the default value.")
+ (documentation-property variable 'variable-documentation)))
+
(define-widget 'custom-variable 'custom
"Customize variable."
:format "%v"
:help-echo "Set or reset this variable."
- :documentation-property 'variable-documentation
+ :documentation-property #'custom-variable-documentation
:custom-category 'option
:custom-state nil
:custom-menu 'custom-variable-menu-create
"Edit face attributes."
:format "%t: %v"
:tag "Attributes"
- :extra-offset 12
+ :extra-offset 13
:button-args '(:help-echo "Control whether this attribute has any effect.")
:value-to-internal 'custom-face-edit-fix-value
:match (lambda (widget value)
:value t
:help-echo "Specify frames where the face attributes should be used."
:args '((const :tag "all" t)
+ (const :tag "defaults" default)
(checklist
:offset 0
:extra-offset 9
(define-widget 'custom-face-selected 'group
"Edit the attributes of the selected display in a face specification."
- :args '((repeat :format ""
- :inline t
- (group custom-display-unselected sexp))
- (group (sexp :format "") custom-face-edit)
- (repeat :format ""
- :inline t
- sexp)))
+ :args '((choice :inline t
+ (group :tag "With Defaults" :inline t
+ (group (const :tag "" default)
+ (custom-face-edit :tag " Default\n Attributes"))
+ (repeat :format ""
+ :inline t
+ (group custom-display-unselected sexp))
+ (group (sexp :format "")
+ (custom-face-edit :tag " Overriding\n Attributes"))
+ (repeat :format ""
+ :inline t
+ sexp))
+ (group :tag "No Defaults" :inline t
+ (repeat :format ""
+ :inline t
+ (group custom-display-unselected sexp))
+ (group (sexp :format "")
+ (custom-face-edit :tag "\n Attributes"))
+ (repeat :format ""
+ :inline t
+ sexp)))))
+
+
(defconst custom-face-selected (widget-convert 'custom-face-selected)
"Converted version of the `custom-face-selected' widget.")
;;; The `face' Widget.
-(define-widget 'face 'default
- "Select and customize a face."
- :convert-widget 'widget-value-convert-widget
- :button-prefix 'widget-push-button-prefix
- :button-suffix 'widget-push-button-suffix
- :format "%{%t%}: %[select face%] %v"
+(defvar widget-face-prompt-value-history nil
+ "History of input to `widget-face-prompt-value'.")
+
+(define-widget 'face 'symbol
+ "A Lisp face name (with sample)."
+ :format "%t: (%{sample%}) %v"
:tag "Face"
:value 'default
- :value-create 'widget-face-value-create
- :value-delete 'widget-face-value-delete
- :value-get 'widget-value-value-get
- :validate 'widget-children-validate
- :action 'widget-face-action
- :match (lambda (widget value) (symbolp value)))
+ :sample-face-get 'widget-face-sample-face-get
+ :notify 'widget-face-notify
+ :match (lambda (widget value) (facep value))
+ :complete-function (lambda ()
+ (interactive)
+ (lisp-complete-symbol 'facep))
+ :prompt-match 'facep
+ :prompt-history 'widget-face-prompt-value-history
+ :validate (lambda (widget)
+ (unless (facep (widget-value widget))
+ (widget-put widget
+ :error (format "Invalid face: %S"
+ (widget-value widget)))
+ widget)))
+
+(defun widget-face-sample-face-get (widget)
+ (let ((value (widget-value widget)))
+ (if (facep value)
+ value
+ 'default)))
+
+(defun widget-face-notify (widget child &optional event)
+ "Update the sample, and notify the parent."
+ (overlay-put (widget-get widget :sample-overlay)
+ 'face (widget-apply widget :sample-face-get))
+ (widget-default-notify widget child event))
-(defun widget-face-value-create (widget)
- "Create a `custom-face' child."
- (let* ((symbol (widget-value widget))
- (custom-buffer-style 'face)
- (child (widget-create-child-and-convert
- widget 'custom-face
- :custom-level nil
- :value symbol)))
- (custom-magic-reset child)
- (setq custom-options (cons child custom-options))
- (widget-put widget :children (list child))))
-
-(defun widget-face-value-delete (widget)
- "Remove the child from the options."
- (let ((child (car (widget-get widget :children))))
- (setq custom-options (delq child custom-options))
- (widget-children-value-delete widget)))
-
-(defvar face-history nil
- "History of entered face names.")
-
-(defun widget-face-action (widget &optional event)
- "Prompt for a face."
- (let ((answer (completing-read "Face: "
- (mapcar (lambda (face)
- (list (symbol-name face)))
- (face-list))
- nil nil nil
- 'face-history)))
- (unless (zerop (length answer))
- (widget-value-set widget (intern answer))
- (widget-apply widget :notify widget event)
- (widget-setup))))
;;; The `hook' Widget.
`((((class color)
(background dark))
(:foreground "pink" :weight bold :height 1.2 :inherit variable-pitch))
+ (((min-colors 88) (class color)
+ (background light))
+ (:foreground "red1" :weight bold :height 1.2 :inherit variable-pitch))
(((class color)
(background light))
(:foreground "red" :weight bold :height 1.2 :inherit variable-pitch))
`((((class color)
(background dark))
(:foreground "light blue" :weight bold :height 1.2))
+ (((min-colors 88) (class color)
+ (background light))
+ (:foreground "blue1" :weight bold :height 1.2))
(((class color)
(background light))
(:foreground "blue" :weight bold :height 1.2))
(defcustom custom-file nil
"File used for storing customization information.
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.
-
-When you change this variable, look in the previous custom file
-\(usually your init file) for the forms `(custom-set-variables ...)'
-and `(custom-set-faces ...)', and copy them (whichever ones you find)
-to the new custom file. This will preserve your existing customizations."
- :type '(choice (const :tag "Your Emacs init file" nil) file)
+as specified by `user-init-file'. If the value is not nil,
+it should be an absolute file name.
+
+You can set this option through Custom, if you carefully read the
+last paragraph below. However, usually it is simpler to write
+something like the following in your init file:
+
+\(setq custom-file \"~/.emacs-custom.el\")
+\(load custom-file)
+
+Note that both lines are necessary: the first line tells Custom to
+save all customizations in this file, but does not load it.
+
+When you change this variable outside Custom, look in the
+previous custom file \(usually your init file) for the
+forms `(custom-set-variables ...)' and `(custom-set-faces ...)',
+and copy them (whichever ones you find) to the new custom file.
+This will preserve your existing customizations.
+
+If you save this option using Custom, Custom will write all
+currently saved customizations, including the new one for this
+option itself, into the file you specify, overwriting any
+`custom-set-variables' and `custom-set-faces' forms already
+present in that file. It will not delete any customizations from
+the old custom file. You should do that manually if that is what you
+want. You also have to put something like `\(load \"CUSTOM-FILE\")
+in your init file, where CUSTOM-FILE is the actual name of the
+file. Otherwise, Emacs will not load the file when it starts up,
+and hence will not set `custom-file' to that file either."
+ :type '(choice (const :tag "Your Emacs init file" nil)
+ (file :format "%t:%v%d"
+ :doc
+ "Please read entire docstring below before setting \
+this through Custom.
+Click om \"More\" \(or position point there and press RETURN)
+if only the first line of the docstring is shown."))
:group 'customize)
(defun custom-file ()
"Return the file name for saving customizations."
- (setq custom-file
- (or custom-file
- (let ((user-init-file user-init-file)
- (default-init-file
- (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs")))
- (when (null user-init-file)
- (if (or (file-exists-p default-init-file)
- (and (eq system-type 'windows-nt)
- (file-exists-p "~/_emacs")))
- ;; Started with -q, i.e. the file containing
- ;; Custom settings hasn't been read. Saving
- ;; settings there would overwrite other settings.
- (error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
- (setq user-init-file default-init-file))
- user-init-file))))
+ (file-chase-links
+ (or custom-file
+ (let ((user-init-file user-init-file)
+ (default-init-file
+ (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs")))
+ (when (null user-init-file)
+ (if (or (file-exists-p default-init-file)
+ (and (eq system-type 'windows-nt)
+ (file-exists-p "~/_emacs")))
+ ;; Started with -q, i.e. the file containing
+ ;; Custom settings hasn't been read. Saving
+ ;; settings there would overwrite other settings.
+ (error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
+ (setq user-init-file default-init-file))
+ user-init-file))))
(defun custom-save-delete (symbol)
"Visit `custom-file' and delete all calls to SYMBOL from it.
;;; The Custom Mode.
-(defvar custom-mode-map nil
- "Keymap for `custom-mode'.")
-
-(unless custom-mode-map
+(defvar custom-mode-map
;; This keymap should be dense, but a dense keymap would prevent inheriting
;; "\r" bindings from the parent 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 " " 'scroll-up)
- (define-key custom-mode-map "\177" 'scroll-down)
- (define-key custom-mode-map "\C-x\C-s" 'Custom-save)
- (define-key custom-mode-map "q" 'Custom-buffer-done)
- (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))
+ ;; Actually, this misfeature of dense keymaps was fixed on 2001-11-26.
+ (let ((map (make-keymap)))
+ (set-keymap-parent map widget-keymap)
+ (suppress-keymap map)
+ (define-key map " " 'scroll-up)
+ (define-key map "\177" 'scroll-down)
+ (define-key map "\C-x\C-s" 'Custom-save)
+ (define-key map "q" 'Custom-buffer-done)
+ (define-key map "u" 'Custom-goto-parent)
+ (define-key map "n" 'widget-forward)
+ (define-key map "p" 'widget-backward)
+ (define-key map [mouse-1] 'Custom-move-and-invoke)
+ map)
+ "Keymap for `custom-mode'.")
(defun Custom-move-and-invoke (event)
"Move to where you click, and if it is an active field, invoke it."
(provide 'cus-edit)
-;;; arch-tag: 64533aa4-1b1a-48c3-8812-f9dc718e8a6f
+;; arch-tag: 64533aa4-1b1a-48c3-8812-f9dc718e8a6f
;;; cus-edit.el ends here