-;;; cus-edit.el --- Tools for customizing Emacs and Lisp packages.
+;;; cus-edit.el --- tools for customizing Emacs and Lisp packages
;;
-;; Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: help, faces
(defcustom custom-unlispify-remove-prefixes nil
"Non-nil means remove group prefixes from option names in buffer."
:group 'custom-menu
+ :group 'custom-buffer
:type 'boolean)
(defun custom-unlispify-menu-entry (symbol &optional no-suffix)
;;;###autoload
(defun customize-set-value (var val &optional comment)
- "Set VARIABLE to VALUE. VALUE is a Lisp object.
+ "Set VARIABLE to VALUE, and return 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.
"Set %s to value: "
current-prefix-arg))
- (set var val)
(cond ((string= comment "")
(put var 'variable-comment nil))
(comment
- (put var 'variable-comment comment))))
+ (put var 'variable-comment comment)))
+ (set var val))
;;;###autoload
(defun customize-set-variable (variable value &optional comment)
- "Set the default for VARIABLE to VALUE. VALUE is a Lisp object.
+ "Set the default for VARIABLE to VALUE, and return VALUE.
+VALUE is a Lisp object.
If VARIABLE has a `custom-set' property, that is used for setting
VARIABLE, otherwise `set-default' is used.
(interactive (custom-prompt-variable "Set variable: "
"Set customized value for %s to: "
current-prefix-arg))
+ (custom-load-symbol variable)
(funcall (or (get variable 'custom-set) 'set-default) variable value)
(put variable 'customized-value (list (custom-quote value)))
(cond ((string= comment "")
(put variable 'customized-variable-comment nil))
(comment
(put variable 'variable-comment comment)
- (put variable 'customized-variable-comment comment))))
+ (put variable 'customized-variable-comment comment)))
+ value)
;;;###autoload
(defun customize-save-variable (var value &optional comment)
"Set the default for VARIABLE to VALUE, and save it for future sessions.
+Return VALUE.
+
If VARIABLE has a `custom-set' property, that is used for setting
VARIABLE, otherwise `set-default' is used.
`:prompt-value' property of that widget will be used for reading the value.
If given a prefix (or a COMMENT argument), also prompt for a comment."
- (interactive (custom-prompt-variable "Set and ave variable: "
+ (interactive (custom-prompt-variable "Set and save variable: "
"Set and save value for %s as: "
current-prefix-arg))
(funcall (or (get var 'custom-set) 'set-default) var value)
(comment
(put var 'variable-comment comment)
(put var 'saved-variable-comment comment)))
- (custom-save-all))
+ (custom-save-all)
+ value)
;;;###autoload
(defun customize ()
options))))
(unless (eq (preceding-char) ?\n)
(widget-insert "\n"))
- (message "Creating customization items ...%2d%%done" 100)
+ (message "Creating customization items ...done")
(unless (eq custom-buffer-style 'tree)
(mapc 'custom-magic-reset custom-options))
(message "Creating customization setup...")
(defface custom-invalid-face '((((class color))
(:foreground "yellow" :background "red"))
(t
- (:bold t :italic t :underline t)))
+ (:weight bold :slant italic :underline t)))
"Face used when the customize item is invalid."
:group 'custom-magic-faces)
(defface custom-modified-face '((((class color))
(:foreground "white" :background "blue"))
(t
- (:italic t :bold)))
+ (: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
- (:italic t)))
+ (:slant italic)))
"Face used when the customize item has been set."
:group 'custom-magic-faces)
(defface custom-changed-face '((((class color))
(:foreground "white" :background "blue"))
(t
- (:italic t)))
+ (:slant italic)))
"Face used when the customize item has been changed."
:group 'custom-magic-faces)
(defvar custom-load-recursion nil
"Hack to avoid recursive dependencies.")
+;;;###autoload
(defun custom-load-symbol (symbol)
"Load all dependencies for SYMBOL."
(unless custom-load-recursion
((and (boundp 'preloaded-file-list)
(member load preloaded-file-list)))
((assoc load load-history))
- ((assoc (locate-library load) load-history))
+ ;; This was just (assoc (locate-library load) load-history)
+ ;; but has been optimized not to load locate-library
+ ;; if not necessary.
+ ((let (found (regexp (regexp-quote load)))
+ (dolist (loaded load-history)
+ (and (string-match regexp (car loaded))
+ (eq (locate-library load) (car loaded))
+ (setq found t)))
+ found))
+ ;; Without this, we would load cus-edit recursively.
+ ;; We are still loading it when we call this,
+ ;; and it is not in load-history yet.
+ ((equal load "cus-edit"))
(t
(condition-case nil
- ;; Without this, we would load cus-edit recursively.
- ;; We are still loading it when we call this,
- ;; and it is not in load-history yet.
- (or (equal load "cus-edit")
- (load-library load))
+ (load-library load)
(error nil))))))))
(defun custom-load-widget (widget)
(background dark))
(:background "dim gray"))
(t
- (:italic t)))
+ (:slant italic)))
"Face used for comments on variables or faces"
:version "21.1"
:group 'custom-faces)
'((((class color) (background dark)) (:foreground "gray80"))
(((class color) (background light)) (:foreground "blue4"))
(((class grayscale) (background light))
- (:foreground "DimGray" :bold t :italic t))
+ (:foreground "DimGray" :weight bold :slant italic))
(((class grayscale) (background dark))
- (:foreground "LightGray" :bold t :italic t))
- (t (:bold t)))
+ (:foreground "LightGray" :weight bold :slant italic))
+ (t (:weight bold)))
"Face used for variables or faces comment tags"
:group 'custom-faces)
(defface custom-variable-tag-face
`((((class color)
(background dark))
- (:foreground "light blue" :bold t :height 1.2 :inherit variable-pitch))
+ (:foreground "light blue" :weight bold :height 1.2 :inherit variable-pitch))
(((class color)
(background light))
- (:foreground "blue" :bold t :height 1.2 :inherit variable-pitch))
- (t (:bold t)))
+ (:foreground "blue" :weight bold :height 1.2 :inherit variable-pitch))
+ (t (:weight bold)))
"Face used for unpushable variable tags."
:group 'custom-faces)
-(defface custom-variable-button-face '((t (:underline t :bold t)))
+(defface custom-variable-button-face '((t (:underline t :weight bold)))
"Face used for pushable variable tags."
:group 'custom-faces)
:tag "Attributes"
:extra-offset 12
:button-args '(:help-echo "Control whether this attribute has any effect.")
+ :value-to-internal 'custom-face-edit-fix-value
+ :match (lambda (widget value)
+ (widget-checklist-match widget
+ (custom-face-edit-fix-value widget value)))
+ :convert-widget 'custom-face-edit-convert-widget
:args (mapcar (lambda (att)
(list 'group
:inline t
(nth 1 att)))
custom-face-attributes))
+(defun custom-face-edit-fix-value (widget value)
+ "Ignoring WIDGET, convert :bold and :italic in VALUE to new form."
+ (let (result)
+ (while value
+ (let ((key (car value))
+ (val (car (cdr value))))
+ (cond ((eq key :italic)
+ (push :slant result)
+ (push (if val 'italic 'normal) result))
+ ((eq key :bold)
+ (push :weight result)
+ (push (if val 'bold 'normal) result))
+ (t
+ (push key result)
+ (push val result))))
+ (setq value (cdr (cdr value))))
+ (setq result (nreverse result))
+ result))
+
+(defun custom-face-edit-convert-widget (widget)
+ "Convert :args as widget types in WIDGET."
+ (widget-put
+ widget
+ :args (mapcar (lambda (arg)
+ (widget-convert arg
+ :deactivate 'custom-face-edit-deactivate
+ :activate 'custom-face-edit-activate
+ :delete 'custom-face-edit-delete))
+ (widget-get widget :args)))
+ widget)
+
+(defun custom-face-edit-deactivate (widget)
+ "Make face widget WIDGET inactive for user modifications."
+ (unless (widget-get widget :inactive)
+ (let ((tag (custom-face-edit-attribute-tag widget))
+ (from (copy-marker (widget-get widget :from)))
+ (to (widget-get widget :to))
+ (value (widget-value widget))
+ (inhibit-read-only t)
+ (inhibit-modification-hooks t))
+ (save-excursion
+ (goto-char from)
+ (widget-default-delete widget)
+ (insert tag ": *\n")
+ (widget-put widget :inactive
+ (cons value (cons from (- (point) from))))))))
+
+(defun custom-face-edit-activate (widget)
+ "Make face widget WIDGET inactive for user modifications."
+ (let ((inactive (widget-get widget :inactive))
+ (inhibit-read-only t)
+ (inhibit-modification-hooks t))
+ (when (consp inactive)
+ (save-excursion
+ (goto-char (car (cdr inactive)))
+ (delete-region (point) (+ (point) (cdr (cdr inactive))))
+ (widget-put widget :inactive nil)
+ (widget-apply widget :create)
+ (widget-value-set widget (car inactive))
+ (widget-setup)))))
+
+(defun custom-face-edit-delete (widget)
+ "Remove widget from the buffer."
+ (let ((inactive (widget-get widget :inactive))
+ (inhibit-read-only t)
+ (inhibit-modification-hooks t))
+ (if (not inactive)
+ ;; Widget is alive, we don't have to do anything special
+ (widget-default-delete widget)
+ ;; WIDGET is already deleted because we did so to inactivate it;
+ ;; now just get rid of the label we put in its place.
+ (delete-region (car (cdr inactive))
+ (+ (car (cdr inactive)) (cdr (cdr inactive))))
+ (widget-put widget :inactive nil))))
+
+
+(defun custom-face-edit-attribute-tag (widget)
+ "Returns the first :tag property in WIDGET or one of its children."
+ (let ((tag (widget-get widget :tag)))
+ (or (and (not (equal tag "")) tag)
+ (let ((children (widget-get widget :children)))
+ (while (and (null tag) children)
+ (setq tag (custom-face-edit-attribute-tag (pop children))))
+ tag))))
+
;;; The `custom-display' Widget.
(define-widget 'custom-display 'menu-choice
;;; The `custom-face' Widget.
(defface custom-face-tag-face
- `((t (:bold t :height 1.2 :inherit variable-pitch)))
+ `((t (:weight bold :height 1.2 :inherit variable-pitch)))
"Face used for face tags."
:group 'custom-faces)
(defconst custom-face-selected (widget-convert 'custom-face-selected)
"Converted version of the `custom-face-selected' widget.")
-(defun custom-filter-face-spec (spec filter-index default-filter)
+(defun custom-filter-face-spec (spec filter-index &optional default-filter)
"Return a canonicalized version of SPEC using.
FILTER-INDEX is the index in the entry for each attribute in
`custom-face-attributes' at which the appropriate filter function can be
(defun custom-pre-filter-face-spec (spec)
"Return SPEC changed as necessary for editing by the face customization widget.
SPEC must be a full face spec."
- (custom-filter-face-spec
- spec 2
- (lambda (value)
- (cond ((eq value 'unspecified) nil)
- ((eq value nil) 'off)
- (t value)))))
+ (custom-filter-face-spec spec 2))
(defun custom-post-filter-face-spec (spec)
"Return the customized SPEC in a form suitable for setting the face."
- (custom-filter-face-spec
- spec 3
- (lambda (value)
- (cond ((eq value nil) 'unspecified)
- ((eq value 'off) nil)
- (t value)))))
+ (custom-filter-face-spec spec 3))
(defun custom-face-value-create (widget)
"Create a list of the display specifications for 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)
+ (spec (or (get symbol 'customized-face)
+ (get symbol 'saved-face)
(get symbol 'face-defface-spec)
;; Attempt to construct it.
(list (list t (custom-face-attributes-get
"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))
+ (value (custom-post-filter-face-spec (widget-value child)))
(comment-widget (widget-get widget :comment-widget))
(comment (widget-value comment-widget)))
(when (equal comment "")
(setq comment nil)
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
- (face-spec-set symbol value)
+ (if (face-spec-choose value)
+ (face-spec-set symbol value)
+ ;; face-set-spec ignores empty attribute lists, so just give it
+ ;; something harmless instead.
+ (face-spec-set symbol '((t :foreground unspecified))))
(put symbol 'saved-face value)
(put symbol 'customized-face nil)
(put symbol 'face-comment comment)
(defface custom-group-tag-face-1
`((((class color)
(background dark))
- (:foreground "pink" :bold t :height 1.2 :inherit variable-pitch))
+ (:foreground "pink" :weight bold :height 1.2 :inherit variable-pitch))
(((class color)
(background light))
- (:foreground "red" :bold t :height 1.2 :inherit variable-pitch))
- (t (:bold t)))
+ (:foreground "red" :weight bold :height 1.2 :inherit variable-pitch))
+ (t (:weight bold)))
"Face used for group tags."
:group 'custom-faces)
(defface custom-group-tag-face
`((((class color)
(background dark))
- (:foreground "light blue" :bold t :height 1.2))
+ (:foreground "light blue" :weight bold :height 1.2))
(((class color)
(background light))
- (:foreground "blue" :bold t :height 1.2))
- (t (:bold t)))
+ (:foreground "blue" :weight bold :height 1.2))
+ (t (:weight bold)))
"Face used for low level group tags."
:group 'custom-faces)
"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"))))
+ (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.
(setq first (point)))))))
(if first
(goto-char first)
- (goto-char (point-max)))))
+ ;; Move in front of local variables, otherwise long Custom
+ ;; entries would make them ineffective.
+ (let ((pos (point-max))
+ (case-fold-search t))
+ (save-excursion
+ (goto-char (point-max))
+ (search-backward "\n\^L" (max (- (point-max) 3000) (point-min))
+ 'move)
+ (when (search-forward "Local Variables:" nil t)
+ (setq pos (line-beginning-position))))
+ (goto-char pos)))))
(defun custom-save-variables ()
"Save all customized variables in `custom-file'."
(save-excursion
(let ((default-major-mode nil))
(set-buffer (find-file-noselect (custom-file))))
- (save-buffer))))
+ (let ((file-precious-flag t))
+ (save-buffer)))))
+
+;;;###autoload
+(defun customize-mark-to-save (symbol)
+ "Mark SYMBOL for later saving.
+
+If the default value of SYMBOL is different from the standard value,
+set the `saved-value' property to a list whose car evaluates to the
+default value. Otherwise, set it til nil.
+
+To actually save the value, call `custom-save-all'.
+
+Return non-nil iff the `saved-value' property actually changed."
+ (let* ((get (or (get symbol 'custom-get) 'default-value))
+ (value (funcall get symbol))
+ (saved (get symbol 'saved-value))
+ (standard (get symbol 'standard-value))
+ (comment (get symbol 'customized-variable-comment)))
+ ;; Save default value iff different from standard value.
+ (if (or (null standard)
+ (not (equal value (condition-case nil
+ (eval (car standard))
+ (error nil)))))
+ (put symbol 'saved-value (list (custom-quote value)))
+ (put symbol 'saved-value nil))
+ ;; Clear customized information (set, but not saved).
+ (put symbol 'customized-value nil)
+ ;; Save any comment that might have been set.
+ (when comment
+ (put symbol 'saved-variable-comment comment))
+ (not (equal saved (get symbol 'saved-value)))))
+
+;;;###autoload
+(defun customize-mark-as-set (symbol)
+ "Mark current value of SYMBOL as being set from customize.
+
+If the default value of SYMBOL is different from the saved value if any,
+or else if it is different from the standard value, set the
+`customized-value' property to a list whose car evaluates to the
+default value. Otherwise, set it til nil.
+
+Return non-nil iff the `customized-value' property actually changed."
+ (let* ((get (or (get symbol 'custom-get) 'default-value))
+ (value (funcall get symbol))
+ (customized (get symbol 'customized-value))
+ (old (or (get symbol 'saved-value) (get symbol 'standard-value))))
+ ;; Mark default value as set iff different from old value.
+ (if (or (null old)
+ (not (equal value (condition-case nil
+ (eval (car old))
+ (error nil)))))
+ (put symbol 'customized-value (list (custom-quote value)))
+ (put symbol 'customized-value nil))
+ ;; Changed?
+ (not (equal customized (get symbol 'customized-value)))))
;;; The Customize Menu.
(setq name "Customize"))
`(,name
:filter (lambda (&rest junk)
- (cdr (custom-menu-create ',symbol)))))
+ (custom-menu-create ',symbol))))
;;; The Custom Mode.