;;; 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,97,1999,2000,01,02,03,2004 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Maintainer: FSF
(defgroup emulations nil
"Emulations of other editors."
+ :link '(custom-manual "(emacs)Emulation")
:group 'editing)
(defgroup mouse nil
"Interfacing to external utilities."
:group 'emacs)
-(defgroup bib nil
- "Code related to the `bib' bibliography processor."
- :tag "Bibliography"
- :group 'external)
-
(defgroup processes nil
"Process, subshell, compilation, and job control support."
:group 'external
(defgroup c nil
"Support for the C language and related languages."
+ :link '(custom-manual "(ccmode)")
:group 'languages)
(defgroup tools nil
(defgroup news nil
"Support for netnews reading and posting."
+ :link '(custom-manual "(gnus)")
:group 'applications)
(defgroup games nil
(defgroup i18n nil
"Internationalization and alternate character-set support."
+ :link '(custom-manual "(emacs)International")
:group 'environment
:group 'editing)
(defgroup customize '((widgets custom-group))
"Customization of the Customization support."
:link '(custom-manual "(elisp)Customization")
- :link '(url-link :tag "(Old?) Development Page"
- "http://www.dina.kvl.dk/~abraham/custom/")
:prefix "custom-"
:group 'help)
(defgroup abbrev-mode nil
"Word abbreviations mode."
+ :link '(custom-manual "(emacs)Abbrevs")
:group 'abbrev)
(defgroup alloc nil
(defgroup undo nil
"Undoing changes in buffers."
+ :link '(custom-manual "(emacs)Undo")
:group 'editing)
(defgroup modeline nil
"Content of the modeline."
:group 'environment)
-(defgroup fill nil
- "Indenting and filling text."
- :group 'editing)
-
(defgroup editing-basics nil
"Most basic editing facilities."
:group 'editing)
(defgroup minibuffer nil
"Controling the behaviour of the minibuffer."
+ :link '(custom-manual "(emacs)Minibuffer")
:group 'environment)
(defgroup keyboard nil
(defgroup windows nil
"Windows within a frame."
+ :link '(custom-manual "(emacs)Windows")
:group 'environment)
;;; Utilities.
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
(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)
(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))))
(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
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))))
;; If we pass BUFFER to `bury-buffer', the buffer isn't removed from
;; the window.
(defun custom-bury-buffer (buffer)
- (bury-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.
:type 'integer
:group 'custom-buffer)
+(defun custom-get-fresh-buffer (name)
+ "Get a fresh new buffer with name NAME.
+If the buffer already exist, clean it up to be like new.
+Beware: it's not quite like new. Good enough for custom, but maybe
+not for everybody."
+ ;; To be more complete, we should also kill all permanent-local variables,
+ ;; but it's not needed for custom.
+ (let ((buf (get-buffer name)))
+ (when (and buf (buffer-local-value 'buffer-file-name buf))
+ ;; This will check if the file is not saved.
+ (kill-buffer buf)
+ (setq buf nil))
+ (if (null buf)
+ (get-buffer-create name)
+ (with-current-buffer buf
+ (kill-all-local-variables)
+ (run-hooks 'kill-buffer-hook)
+ ;; Delete overlays before erasing the buffer so the overlay hooks
+ ;; don't get run spuriously when we erase the buffer.
+ (let ((ols (overlay-lists)))
+ (dolist (ol (nconc (car ols) (cdr ols)))
+ (delete-overlay ol)))
+ (erase-buffer)
+ buf))))
+
;;;###autoload
(defun custom-buffer-create (options &optional name description)
"Create a buffer containing OPTIONS.
OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
SYMBOL is a customization option, and WIDGET is a widget for editing
that option."
- (unless name (setq name "*Customization*"))
- (kill-buffer (get-buffer-create name))
- (pop-to-buffer (get-buffer-create name))
+ (pop-to-buffer (custom-get-fresh-buffer (or name "*Customization*")))
(custom-buffer-create-internal options description))
;;;###autoload
SYMBOL is a customization option, and WIDGET is a widget for editing
that option."
(unless name (setq name "*Customization*"))
- (kill-buffer (get-buffer-create name))
(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))
+ (pop-to-buffer (custom-get-fresh-buffer name))
(custom-buffer-create-internal options description)
(select-window window)))
(unless group
(setq group 'emacs))
(let ((name "*Customize Browser*"))
- (kill-buffer (get-buffer-create name))
- (pop-to-buffer (get-buffer-create name)))
+ (pop-to-buffer (custom-get-fresh-buffer name)))
(custom-mode)
(widget-insert "\
Square brackets show active fields; type RET or click mouse-1
:custom-state 'unknown
:tag (custom-unlispify-tag-name group)
:value group))
+ (widget-setup)
(goto-char (point-min)))
(define-widget 'custom-browse-visibility 'item
(type (widget-type widget))
(buttons (widget-get widget :buttons))
(start (point))
- found)
+ (parents nil))
(insert (or initial-string "Parent groups:"))
(mapatoms (lambda (symbol)
(let ((entry (assq name (get symbol 'custom-group))))
:tag (custom-unlispify-tag-name symbol)
symbol)
buttons)
- (setq found t)))))
- (widget-put widget :buttons buttons)
- (if found
- (insert "\n")
+ (setq parents (cons symbol parents))))))
+ (and (null (get name 'custom-links)) ;No links of its own.
+ (= (length parents) 1) ;A single parent.
+ (let* ((links (get (car parents) 'custom-links))
+ (many (> (length links) 2)))
+ (when links
+ (insert "\nParent documentation: ")
+ (while links
+ (push (widget-create-child-and-convert widget (car links))
+ buttons)
+ (setq links (cdr links))
+ (cond ((null links)
+ (insert ".\n"))
+ ((null (cdr links))
+ (if many
+ (insert ", and ")
+ (insert " and ")))
+ (t
+ (insert ", ")))))))
+ (if parents
+ (insert "\n")
(delete-region start (point)))
- found))
+ (widget-put widget :buttons buttons)
+ parents))
;;; The `custom-comment' Widget.
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))
- (comment-widget (widget-get widget :comment-widget)))
+ (set (or (get symbol 'custom-set) 'set-default)))
(if (get symbol 'standard-value)
(progn
(custom-variable-backup-value widget)
: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))))
(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))
(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."
"Set the state of WIDGET."
(let* ((symbol (widget-value widget))
(comment (get symbol 'face-comment))
- tmp temp)
- (widget-put widget :custom-state
- (cond ((progn
- (setq tmp (get symbol 'customized-face))
- (setq temp (get symbol 'customized-face-comment))
- (or tmp temp))
- (if (equal temp comment)
- 'set
- 'changed))
- ((progn
- (setq tmp (get symbol 'saved-face))
- (setq temp (get symbol 'saved-face-comment))
- (or tmp temp))
- (if (equal temp comment)
- 'saved
- 'changed))
- ((get symbol 'face-defface-spec)
- (if (equal comment nil)
- 'standard
- 'changed))
- (t
- 'rogue)))))
+ tmp temp
+ (state
+ (cond ((progn
+ (setq tmp (get symbol 'customized-face))
+ (setq temp (get symbol 'customized-face-comment))
+ (or tmp temp))
+ (if (equal temp comment)
+ 'set
+ 'changed))
+ ((progn
+ (setq tmp (get symbol 'saved-face))
+ (setq temp (get symbol 'saved-face-comment))
+ (or tmp temp))
+ (if (equal temp comment)
+ 'saved
+ 'changed))
+ ((get symbol 'face-defface-spec)
+ (if (equal comment nil)
+ 'standard
+ 'changed))
+ (t
+ 'rogue))))
+ ;; If the user called set-face-attribute to change the default
+ ;; for new frames, this face is "set outside of Customize".
+ (if (and (not (eq state 'rogue))
+ (get symbol 'face-modified))
+ (setq state 'changed))
+ (widget-put widget :custom-state state)))
(defun custom-face-action (widget &optional event)
"Show the menu for `custom-face' WIDGET.
(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))
;; 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 ((spec (car-safe (get symbol 'theme-value)))
- (value (get symbol 'saved-value))
- (requests (get symbol 'custom-requests))
- (now (not (or (get symbol 'standard-value)
- (and (not (boundp symbol))
- (not (eq (get symbol 'force-value)
- 'rogue))))))
- (comment (get symbol 'saved-variable-comment))
- sep)
- (when (or (and spec
- (eq (nth 0 spec) 'user)
- (eq (nth 1 spec) 'set))
- 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)))
+ ;; 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 ")")
;; 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 ((theme-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 theme-spec
- (eq (nth 0 theme-spec) 'user)
- (eq (nth 1 theme-spec) 'set))
- 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 ")")
(mapatoms mapper)
(when started-writing
(princ ")\n")))))
-
+
(defun custom-save-loaded-themes ()
(let ((themes (reverse (get 'user 'theme-loads-themes)))
(standard-output (current-buffer)))
(mapc (lambda (theme)
(princ "\n '")
(prin1 theme)) themes)
- (princ " )\n"))))
+ (princ " )\n"))))
;;;###autoload
(defun customize-save-customized ()
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)
(provide 'cus-edit)
+;;; arch-tag: 64533aa4-1b1a-48c3-8812-f9dc718e8a6f
;;; cus-edit.el ends here