;;; cus-edit.el --- tools for customizing Emacs and Lisp packages
;;
-;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
+;; Maintainer: FSF
;; Keywords: help, faces
;; This file is part of GNU Emacs.
;;; Commentary:
;;
;; This file implements the code to create and edit customize buffers.
-;;
+;;
;; See `custom.el'.
;; No commands should have names starting with `custom-' because
regexp))
(defun custom-variable-prompt ()
- "Prompt for a variable, defaulting to the variable at point.
+ "Prompt for a custom variable, defaulting to the variable at point.
Return a list suitable for use in `interactive'."
(let ((v (variable-at-point))
(enable-recursive-minibuffers t)
val)
(setq val (completing-read
- (if (symbolp v)
+ (if (and (symbolp v) (custom-variable-p v))
(format "Customize option: (default %s) " v)
- "Customize variable: ")
- obarray (lambda (symbol)
- (and (boundp symbol)
- (or (get symbol 'custom-type)
- (get symbol 'custom-loads)
- (get symbol 'standard-value)))) t))
+ "Customize option: ")
+ obarray 'custom-variable-p t))
(list (if (equal val "")
(if (symbolp v) v nil)
(intern val)))))
(get symbol 'custom-tag)
(concat (get symbol 'custom-tag) "...")))
(t
- (save-excursion
- (set-buffer (get-buffer-create " *Custom-Work*"))
+ (with-current-buffer (get-buffer-create " *Custom-Work*")
(erase-buffer)
(princ symbol (current-buffer))
(goto-char (point-min))
(interactive (custom-prompt-variable "Set variable: "
"Set %s to value: "
current-prefix-arg))
-
+
(cond ((string= comment "")
(put variable 'variable-comment nil))
(comment
current-prefix-arg))
(funcall (or (get variable 'custom-set) 'set-default) variable value)
(put variable 'saved-value (list (custom-quote value)))
+ (custom-push-theme 'theme-value variable 'user 'set (list (custom-quote value)))
(cond ((string= comment "")
(put variable 'variable-comment nil)
(put variable 'saved-variable-comment nil))
(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)
(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)))
+ (let ((window (selected-window))
+ ;; 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))
(custom-buffer-create-other-window
(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))))
+;;;###autoload
+(defalias 'customize-variable-other-window 'customize-option-other-window)
+
+;;;###autoload
+(defun customize-option-other-window (symbol)
+ "Customize SYMBOL, which must be a user option variable.
+Show the buffer in another window, but don't select it."
+ (interactive (custom-variable-prompt))
+ (custom-buffer-create-other-window
+ (list (list symbol 'custom-variable))
+ (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.")
(signal 'wrong-type-argument (list 'numberp since-version))))
(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*"))))
+
+ ;; Load the information for versions since since-version. We use
+ ;; custom-load-symbol for this.
+ (put 'custom-versions-load-alist 'custom-loads nil)
+ (dolist (elt custom-versions-load-alist)
+ (if (customize-version-lessp since-version (car elt))
+ (dolist (load (cdr elt))
+ (custom-add-load 'custom-versions-load-alist load))))
+ (custom-load-symbol 'custom-versions-load-alist)
+ (put 'custom-versions-load-alist 'custom-loads nil)
+
+ (let (found)
+ (mapatoms
+ (lambda (symbol)
+ (let ((version (get symbol 'custom-version)))
+ (if version
+ (when (customize-version-lessp since-version version)
+ (if (or (get symbol 'custom-group)
+ (get symbol 'group-documentation))
+ (push (list symbol 'custom-group) found))
+ (if (custom-variable-p symbol)
+ (push (list symbol 'custom-variable) found))
+ (if (custom-facep symbol)
+ (push (list symbol 'custom-face) found)))))))
+ (if found
+ (custom-buffer-create (custom-sort-items found t 'first)
+ "*Customize Changed Options*")
+ (error "No user option defaults have been changed since Emacs %s"
+ since-version))))
(defun customize-version-lessp (version1 version2)
;; Why are the versions strings, and given that they are, why aren't
(or (< major1 major2)
(and (= major1 major2)
(< minor1 minor2)))))
-
-;;;###autoload
-(defalias 'customize-variable-other-window 'customize-option-other-window)
-
-;;;###autoload
-(defun customize-option-other-window (symbol)
- "Customize SYMBOL, which must be a user option variable.
-Show the buffer in another window, but don't select it."
- (interactive (custom-variable-prompt))
- (custom-buffer-create-other-window
- (list (list symbol 'custom-variable))
- (format "*Customize Option: %s*" (custom-unlispify-tag-name symbol))))
;;;###autoload
(defun customize-face (&optional face)
t nil)
"*Customize Faces*")
(unless (facep face)
- (error "Invalid face %S"))
+ (error "Invalid face %S" face))
(custom-buffer-create (list (list face 'custom-face))
(format "*Customize Face: %s*"
(custom-unlispify-tag-name face)))))
t nil)
"*Customize Faces*")
(unless (facep face)
- (error "Invalid face %S"))
+ (error "Invalid face %S" face))
(custom-buffer-create-other-window
(list (list face 'custom-face))
(format "*Customize Face: %s*"
"*Customize Customized*"))))
;;;###autoload
+(defun customize-rogue ()
+ "Customize all user variable modified outside customize."
+ (interactive)
+ (let ((found nil))
+ (mapatoms (lambda (symbol)
+ (let ((cval (or (get symbol 'customized-value)
+ (get symbol 'saved-value)
+ (get symbol 'standard-value))))
+ (when (and cval ;Declared with defcustom.
+ (default-boundp symbol) ;Has a value.
+ (not (equal (eval (car cval))
+ ;; Which does not match customize.
+ (default-value symbol))))
+ (push (list symbol 'custom-variable) found)))))
+ (if (not found)
+ (error "No rogue user options")
+ (custom-buffer-create (custom-sort-items found t nil)
+ "*Customize Rogue*"))))
+;;;###autoload
(defun customize-saved ()
"Customize all already saved user options."
(interactive)
(when (and (not (memq all '(groups faces)))
(boundp symbol)
(or (get symbol 'saved-value)
- (get symbol 'standard-value)
+ (custom-variable-p symbol)
(if (memq all '(nil options))
(user-variable-p symbol)
(get symbol 'variable-documentation))))
:custom-state 'unknown
:tag (custom-unlispify-tag-name group)
:value group))
+ (widget-setup)
(goto-char (point-min)))
(define-widget 'custom-browse-visibility 'item
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
(put symbol 'saved-value (list (widget-value child)))
+ (custom-push-theme 'theme-value symbol 'user
+ 'set (list (widget-value child)))
(funcall set symbol (eval (widget-value child)))
(put symbol 'variable-comment comment)
(put symbol 'saved-variable-comment comment))
(custom-comment-hide comment-widget))
(put symbol 'saved-value
(list (custom-quote (widget-value child))))
+ (custom-push-theme 'theme-value symbol 'user
+ 'set (list (custom-quote (widget-value
+ child))))
(funcall set symbol (widget-value child))
(put symbol 'variable-comment comment)
(put symbol 'saved-variable-comment comment)))
becomes the backup value, so you can get it again."
(let* ((symbol (widget-value widget))
(set (or (get symbol 'custom-set) 'set-default))
+ (comment-widget (widget-get widget :comment-widget))
(value (get symbol 'saved-value))
(comment (get symbol 'saved-variable-comment)))
(cond ((or value comment)
The value that was current before this operation
becomes the backup value, so you can get it again."
(let* ((symbol (widget-value widget))
- (set (or (get symbol 'custom-set) 'set-default)))
+ (set (or (get symbol 'custom-set) 'set-default))
+ (comment-widget (widget-get widget :comment-widget)))
(if (get symbol 'standard-value)
(progn
(custom-variable-backup-value widget)
(put symbol 'customized-variable-comment nil)
(when (or (get symbol 'saved-value) (get symbol 'saved-variable-comment))
(put symbol 'saved-value nil)
+ (custom-push-theme 'theme-value symbol 'user 'reset 'standard)
+ ;; As a special optimizations we do not (explictly)
+ ;; save resets to standard when no theme set the value.
+ (if (null (cdr (get symbol 'theme-value)))
+ (put symbol 'theme-value nil))
(put symbol 'saved-variable-comment nil)
(custom-save-all))
(widget-put widget :custom-state 'unknown)
: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
+ (widget-checklist-match widget
(custom-face-edit-fix-value widget value)))
:convert-widget 'custom-face-edit-convert-widget
:args (mapcar (lambda (att)
((eq key :reverse-video)
(push :inverse-video result)
(push val result))
- (t
+ (t
(push key result)
(push val result))))
(setq value (cdr (cdr value))))
(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."
(face-spec-set symbol '((t :foreground unspecified))))
(unless (eq (widget-get widget :custom-state) 'standard)
(put symbol 'saved-face value))
+ (custom-push-theme 'theme-face symbol 'user 'set value)
(put symbol 'customized-face nil)
(put symbol 'face-comment comment)
(put symbol 'customized-face-comment nil)
(put symbol 'customized-face-comment nil)
(when (or (get symbol 'saved-face) (get symbol 'saved-face-comment))
(put symbol 'saved-face nil)
+ (custom-push-theme 'theme-face symbol 'user 'reset 'standard)
+ ;; Do not explictly save resets to standards without themes.
+ (if (null (cdr (get symbol 'theme-face)))
+ (put symbol 'theme-face nil))
(put symbol 'saved-face-comment nil)
(custom-save-all))
(face-spec-set symbol value)
(defun custom-group-value-create (widget)
"Insert a customize group for WIDGET in the current buffer."
+ (unless (eq (widget-get widget :custom-state) 'hidden)
+ (custom-load-widget widget))
(let* ((state (widget-get widget :custom-state))
(level (widget-get widget :custom-level))
;; (indent (widget-get widget :indent))
(widget-put widget :buttons buttons))
((eq custom-buffer-style 'tree)
(custom-browse-insert-prefix prefix)
- (custom-load-widget widget)
(if (zerop (length members))
(progn
(custom-browse-insert-prefix prefix)
?\ ))
;; Members.
(message "Creating group...")
- (custom-load-widget widget)
(let* ((members (custom-sort-items members
custom-buffer-sort-alphabetically
custom-buffer-order-groups))
(defun custom-save-variables ()
"Save all customized variables in `custom-file'."
(save-excursion
+ (custom-save-delete 'custom-load-themes)
+ (custom-save-delete 'custom-reset-variables)
(custom-save-delete 'custom-set-variables)
+ (custom-save-loaded-themes)
+ (custom-save-resets 'theme-value 'custom-reset-variables nil)
(let ((standard-output (current-buffer))
(saved-list (make-list 1 0))
sort-fold-case)
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.\n")
- (mapcar
- (lambda (symbol)
- (let ((value (get symbol 'saved-value))
- (requests (get symbol 'custom-requests))
- (now (not (or (get symbol 'standard-value)
- (and (not (boundp symbol))
- (not (get symbol 'force-value))))))
- (comment (get symbol 'saved-variable-comment))
- sep)
- (when (or value comment)
- (unless (bolp)
- (princ "\n"))
- (princ " '(")
- (prin1 symbol)
- (princ " ")
- (prin1 (car value))
- (cond ((or now requests comment)
- (princ " ")
- (if now
- (princ "t")
- (princ "nil"))
- (cond ((or requests comment)
- (princ " ")
- (if requests
- (prin1 requests)
- (princ "nil"))
- (cond (comment
- (princ " ")
- (prin1 comment)
- (princ ")"))
- (t
- (princ ")"))))
- (t
- (princ ")"))))
- (t
- (princ ")"))))))
- saved-list)
+ (dolist (symbol saved-list)
+ (let ((spec (car-safe (get symbol 'theme-value)))
+ (value (get symbol 'saved-value))
+ (requests (get symbol 'custom-requests))
+ (now (not (or (custom-variable-p symbol)
+ (and (not (boundp symbol))
+ (not (eq (get symbol 'force-value)
+ 'rogue))))))
+ (comment (get symbol 'saved-variable-comment))
+ sep)
+ ;; Check `requests'.
+ (dolist (request requests)
+ (when (and (symbolp request) (not (featurep request)))
+ (message "Unknown requested feature: %s" request)
+ (setq requests (delq request requests))))
+ (when (or (and spec
+ (eq (nth 0 spec) 'user)
+ (eq (nth 1 spec) 'set))
+ comment
+ (and (null spec) (get symbol 'saved-value)))
+ (unless (bolp)
+ (princ "\n"))
+ (princ " '(")
+ (prin1 symbol)
+ (princ " ")
+ (prin1 (car value))
+ (when (or now requests comment)
+ (princ " ")
+ (prin1 now)
+ (when (or requests comment)
+ (princ " ")
+ (prin1 requests)
+ (when comment
+ (princ " ")
+ (prin1 comment))))
+ (princ ")"))))
(if (bolp)
(princ " "))
(princ ")")
(defun custom-save-faces ()
"Save all customized faces in `custom-file'."
(save-excursion
+ (custom-save-delete 'custom-reset-faces)
(custom-save-delete 'custom-set-faces)
+ (custom-save-resets 'theme-face 'custom-reset-faces '(default))
(let ((standard-output (current-buffer))
(saved-list (make-list 1 0))
sort-fold-case)
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.\n")
- (mapcar
- (lambda (symbol)
- (let ((value (get symbol 'saved-face))
- (now (not (or (get symbol 'face-defface-spec)
- (and (not (custom-facep symbol))
- (not (get symbol 'force-face))))))
- (comment (get symbol 'saved-face-comment)))
- ;; Don't print default face here.
- (unless (bolp)
- (princ "\n"))
- (princ " '(")
- (prin1 symbol)
- (princ " ")
- (prin1 value)
- (cond ((or now comment)
- (princ " ")
- (if now
- (princ "t")
- (princ "nil"))
- (cond (comment
- (princ " ")
- (prin1 comment)
- (princ ")"))
- (t
- (princ ")"))))
- (t
- (princ ")")))))
- saved-list)
+ (dolist (symbol saved-list)
+ (let ((spec (car-safe (get symbol 'theme-face)))
+ (value (get symbol 'saved-face))
+ (now (not (or (get symbol 'face-defface-spec)
+ (and (not (custom-facep symbol))
+ (not (get symbol 'force-face))))))
+ (comment (get symbol 'saved-face-comment)))
+ (when (or (and spec
+ (eq (nth 0 spec) 'user)
+ (eq (nth 1 spec) 'set))
+ comment
+ (and (null spec) (get symbol 'saved-face)))
+ ;; Don't print default face here.
+ (unless (bolp)
+ (princ "\n"))
+ (princ " '(")
+ (prin1 symbol)
+ (princ " ")
+ (prin1 value)
+ (when (or now comment)
+ (princ " ")
+ (prin1 now)
+ (when comment
+ (princ " ")
+ (prin1 comment)))
+ (princ ")"))))
(if (bolp)
(princ " "))
(princ ")")
(unless (looking-at "\n")
(princ "\n")))))
+(defun custom-save-resets (property setter special)
+ (let (started-writing ignored-special)
+ ;; (custom-save-delete setter) Done by caller
+ (let ((standard-output (current-buffer))
+ (mapper `(lambda (object)
+ (let ((spec (car-safe (get object (quote ,property)))))
+ (when (and (not (memq object ignored-special))
+ (eq (nth 0 spec) 'user)
+ (eq (nth 1 spec) 'reset))
+ ;; Do not write reset statements unless necessary.
+ (unless started-writing
+ (setq started-writing t)
+ (unless (bolp)
+ (princ "\n"))
+ (princ "(")
+ (princ (quote ,setter))
+ (princ "\n '(")
+ (prin1 object)
+ (princ " ")
+ (prin1 (nth 3 spec))
+ (princ ")")))))))
+ (mapc mapper special)
+ (setq ignored-special special)
+ (mapatoms mapper)
+ (when started-writing
+ (princ ")\n")))))
+
+(defun custom-save-loaded-themes ()
+ (let ((themes (reverse (get 'user 'theme-loads-themes)))
+ (standard-output (current-buffer)))
+ (when themes
+ (unless (bolp) (princ "\n"))
+ (princ "(custom-load-themes")
+ (mapc (lambda (theme)
+ (princ "\n '")
+ (prin1 theme)) themes)
+ (princ " )\n"))))
+
;;;###autoload
(defun customize-save-customized ()
"Save all user options which have been set in this session."
(get symbol 'customized-variable-comment)))
(when face
(put symbol 'saved-face face)
+ (custom-push-theme 'theme-face symbol 'user 'set value)
(put symbol 'customized-face nil))
(when value
(put symbol 'saved-value value)
+ (custom-push-theme 'theme-value symbol 'user 'set value)
(put symbol 'customized-value nil))
(when variable-comment
(put symbol 'saved-variable-comment variable-comment)
t)))
(if (and (or (not (boundp 'custom-menu-nesting))
(>= custom-menu-nesting 0))
- (< (length (get symbol 'custom-group)) widget-menu-max-size))
+ (progn
+ (custom-load-symbol symbol)
+ (< (length (get symbol 'custom-group)) widget-menu-max-size)))
(let ((custom-prefix-list (custom-prefix-add symbol
custom-prefix-list))
(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
"--"
(use-local-map custom-mode-map)
(easy-menu-add Custom-mode-menu)
(make-local-variable 'custom-options)
+ (make-local-variable 'custom-local-buffer)
(make-local-variable 'widget-documentation-face)
(setq widget-documentation-face 'custom-documentation-face)
(make-local-variable 'widget-button-face)