Remove defining user variables via * in docstring.
[bpt/emacs.git] / lisp / custom.el
index 8295777..d8909f8 100644 (file)
@@ -1,6 +1,6 @@
 ;;; custom.el --- tools for declaring and initializing options
 ;;
-;; Copyright (C) 1996-1997, 1999, 2001-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999, 2001-2012 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -120,8 +120,10 @@ the :set function.
 For variables in preloaded files, you can simply use this
 function for the :initialize property.  For autoloaded variables,
 you will also need to add an autoload stanza calling this
-function, and another one setting the standard-value property.
-See `send-mail-function' in sendmail.el for an example."
+function, and another one setting the standard-value property."
+  ;; No longer true:
+  ;; "See `send-mail-function' in sendmail.el for an example."
+
   ;; Until the var is actually initialized, it is kept unbound.
   ;; This seemed to be at least as good as setting it to an arbitrary
   ;; value like nil (evaluating `value' is not an option because it
@@ -196,13 +198,21 @@ set to nil, as the value is no longer rogue."
   (run-hooks 'custom-define-hook)
   symbol)
 
-(defmacro defcustom (symbol value doc &rest args)
-  "Declare SYMBOL as a customizable variable that defaults to VALUE.
+(defmacro defcustom (symbol standard doc &rest args)
+  "Declare SYMBOL as a customizable variable.
+SYMBOL is the variable name; it should not be quoted.
+STANDARD is an expression specifying the variable's standard
+value.  It should not be quoted.  It is evaluated once by
+`defcustom', and the value is assigned to SYMBOL if the variable
+is unbound.  The expression itself is also stored, so that
+Customize can re-evaluate it later to get the standard value.
 DOC is the variable documentation.
 
-Neither SYMBOL nor VALUE need to be quoted.
-If SYMBOL is not already bound, initialize it to VALUE.
-The remaining arguments should have the form
+This macro uses `defvar' as a subroutine, which also marks the
+variable as \"special\", so that it is always dynamically bound
+even when `lexical-binding' is t.
+
+The remaining arguments to `defcustom' should have the form
 
    [KEYWORD VALUE]...
 
@@ -215,7 +225,8 @@ The following keywords are meaningful:
        variable.  It takes two arguments, the symbol and value
        given in the `defcustom' call.  The default is
        `custom-initialize-reset'.
-:set   VALUE should be a function to set the value of the symbol.
+:set   VALUE should be a function to set the value of the symbol
+        when using the Customize user interface.
        It takes two arguments, the symbol to set and the value to
        give it.  The default choice of function is `set-default'.
 :get   VALUE should be a function to extract the value of symbol.
@@ -226,8 +237,12 @@ The following keywords are meaningful:
        VALUE should be a feature symbol.  If you save a value
        for this option, then when your `.emacs' file loads the value,
        it does (require VALUE) first.
+:set-after VARIABLES
+       Specifies that SYMBOL should be set after the list of variables
+        VARIABLES when both have been customized.
 :risky Set SYMBOL's `risky-local-variable' property to VALUE.
 :safe  Set SYMBOL's `safe-local-variable' property to VALUE.
+        See Info node `(elisp) File Local Variables'.
 
 The following common keywords are also meaningful.
 
@@ -296,9 +311,6 @@ The following common keywords are also meaningful.
         Load file FILE (a string) before displaying this customization
         item.  Loading is done with `load', and only if the file is
         not already loaded.
-:set-after VARIABLES
-       Specifies that SYMBOL should be set after the list of variables
-        VARIABLES when both have been customized.
 
 If SYMBOL has a local binding, then this form affects the local
 binding.  This is normally not what you want.  Thus, if you need
@@ -316,14 +328,15 @@ for more information."
   `(custom-declare-variable
     ',symbol
     ,(if lexical-binding    ;FIXME: This is not reliable, but is all we have.
-         ;; The `default' arg should be an expression that evaluates to
-         ;; the value to use.  The use of `eval' for it is spread over
-         ;; many different places and hence difficult to eliminate, yet
-         ;; we want to make sure that the `value' expression is checked by the
-         ;; byte-compiler, and that lexical-binding is obeyed, so quote the
-         ;; expression with `lambda' rather than with `quote'.
-         `(list (lambda () ,value))
-       `',value)
+         ;; The STANDARD arg should be an expression that evaluates to
+         ;; the standard value.  The use of `eval' for it is spread
+         ;; over many different places and hence difficult to
+         ;; eliminate, yet we want to make sure that the `standard'
+         ;; expression is checked by the byte-compiler, and that
+         ;; lexical-binding is obeyed, so quote the expression with
+         ;; `lambda' rather than with `quote'.
+         `(list (lambda () ,standard))
+       `',standard)
     ,doc
     ,@args))
 
@@ -586,13 +599,17 @@ If NOSET is non-nil, don't bother autoloading LOAD when setting the variable."
   (put symbol 'custom-autoload (if noset 'noset t))
   (custom-add-load symbol load))
 
-;; This test is also in the C code of `user-variable-p'.
 (defun custom-variable-p (variable)
-  "Return non-nil if VARIABLE is a custom variable.
-This recursively follows aliases."
-  (setq variable (indirect-variable variable))
-  (or (get variable 'standard-value)
-      (get variable 'custom-autoload)))
+  "Return non-nil if VARIABLE is a customizable variable.
+A customizable variable is either (i) a variable whose property
+list contains a non-nil `standard-value' or `custom-autoload'
+property, or (ii) an alias for another customizable variable."
+  (when (symbolp variable)
+    (setq variable (indirect-variable variable))
+    (or (get variable 'standard-value)
+       (get variable 'custom-autoload))))
+
+(define-obsolete-function-alias 'user-variable-p 'custom-variable-p "24.2")
 
 (defun custom-note-var-changed (variable)
   "Inform Custom that VARIABLE has been set (changed).
@@ -854,25 +871,18 @@ See `custom-known-themes' for a list of known themes."
      ;; Add a new setting:
      (t
       (unless old
-       ;; If the user changed the value outside of Customize, we
-       ;; first save the current value to a fake theme, `changed'.
-       ;; This ensures that the user-set value comes back if the
-       ;; theme is later disabled.
-       (cond ((and (eq prop 'theme-value)
-                   (boundp symbol))
-              (let ((sv  (get symbol 'standard-value))
-                    (val (symbol-value symbol)))
-                (unless (and sv (equal (eval (car sv)) val))
-                  (setq old `((changed ,(custom-quote val)))))))
-             ((and (facep symbol)
-                   (not (face-attr-match-p
-                         symbol
-                         (custom-fix-face-spec
-                          (face-spec-choose
-                           (get symbol 'face-defface-spec))))))
-              (setq old `((changed
-                           (,(append '(t) (custom-face-attributes-get
-                                           symbol nil)))))))))
+       ;; If the user changed a variable outside of Customize, save
+       ;; the value to a fake theme, `changed'.  If the theme is
+       ;; later disabled, we use this to bring back the old value.
+       ;;
+       ;; For faces, we just use `face-new-frame-defaults' to
+       ;; recompute when the theme is disabled.
+       (when (and (eq prop 'theme-value)
+                  (boundp symbol))
+         (let ((sv  (get symbol 'standard-value))
+               (val (symbol-value symbol)))
+           (unless (and sv (equal (eval (car sv)) val))
+             (setq old `((changed ,(custom-quote val))))))))
       (put symbol prop (cons (list theme value) old))
       (put theme 'theme-settings
           (cons (list prop symbol theme value) theme-settings))))))
@@ -1108,33 +1118,55 @@ property `theme-feature' (which is usually a symbol created by
   (provide (get theme 'theme-feature)))
 
 (defcustom custom-safe-themes '(default)
-  "List of themes that are considered safe to load.
-Each list element should be the `sha1' hash of a theme file, or
-the symbol `default', which stands for any theme in the built-in
-Emacs theme directory (a directory named \"themes\" in
-`data-directory')."
-  :type '(repeat
-         (choice string (const :tag "Built-in themes" default)))
+  "Themes that are considered safe to load.
+If the value is a list, each element should be either the SHA-256
+hash of a safe theme file, or the symbol `default', which stands
+for any theme in the built-in Emacs theme directory (a directory
+named \"themes\" in `data-directory').
+
+If the value is t, Emacs treats all themes as safe.
+
+This variable cannot be set in a Custom theme."
+  :type '(choice (repeat :tag "List of safe themes"
+                        (choice string
+                                (const :tag "Built-in themes" default)))
+                (const :tag "All themes" t))
   :group 'customize
   :risky t
   :version "24.1")
 
-(defun load-theme (theme &optional no-enable)
+(defun load-theme (theme &optional no-confirm no-enable)
   "Load Custom theme named THEME from its file.
-Normally, this also enables THEME.  If optional arg NO-ENABLE is
-non-nil, load THEME but don't enable it.
-
 The theme file is named THEME-theme.el, in one of the directories
 specified by `custom-theme-load-path'.
 
+If the theme is not considered safe by `custom-safe-themes',
+prompt the user for confirmation before loading it.  But if
+optional arg NO-CONFIRM is non-nil, load the theme without
+prompting.
+
+Normally, this function also enables THEME.  If optional arg
+NO-ENABLE is non-nil, load the theme but don't enable it, unless
+the theme was already enabled.
+
+This function is normally called through Customize when setting
+`custom-enabled-themes'.  If used directly in your init file, it
+should be called with a non-nil NO-CONFIRM argument, or after
+`custom-safe-themes' has been loaded.
+
 Return t if THEME was successfully loaded, nil otherwise."
   (interactive
    (list
     (intern (completing-read "Load custom theme: "
                             (mapcar 'symbol-name
-                                    (custom-available-themes))))))
+                                    (custom-available-themes))))
+    nil nil))
   (unless (custom-theme-name-valid-p theme)
     (error "Invalid theme name `%s'" theme))
+  ;; If THEME is already enabled, re-enable it after loading, even if
+  ;; NO-ENABLE is t.
+  (if no-enable
+      (setq no-enable (not (custom-theme-enabled-p theme))))
   ;; If reloading, clear out the old theme settings.
   (when (custom-theme-p theme)
     (disable-theme theme)
@@ -1149,10 +1181,12 @@ Return t if THEME was successfully loaded, nil otherwise."
       (error "Unable to find theme file for `%s'" theme))
     (with-temp-buffer
       (insert-file-contents fn)
-      (setq hash (sha1 (current-buffer)))
+      (setq hash (secure-hash 'sha256 (current-buffer)))
       ;; Check file safety with `custom-safe-themes', prompting the
       ;; user if necessary.
-      (when (or (and (memq 'default custom-safe-themes)
+      (when (or no-confirm
+               (eq custom-safe-themes t)
+               (and (memq 'default custom-safe-themes)
                     (equal (file-name-directory fn)
                            (expand-file-name "themes/" data-directory)))
                (member hash custom-safe-themes)
@@ -1211,10 +1245,7 @@ query also about adding HASH to `custom-safe-themes'."
          ;; Offer to save to `custom-safe-themes'.
          (and (or custom-file user-init-file)
               (y-or-n-p "Treat this theme as safe in future sessions? ")
-              (let ((coding-system-for-read nil))
-                (push hash custom-safe-themes)
-                (customize-save-variable 'custom-safe-themes
-                                         custom-safe-themes)))
+              (customize-push-and-save 'custom-safe-themes (list hash)))
          t)))))
 
 (defun custom-theme-name-valid-p (name)
@@ -1276,8 +1307,8 @@ precedence (after `user')."
         ((eq prop 'theme-face)
          (custom-theme-recalc-face symbol))
         ((eq prop 'theme-value)
-         ;; Don't change `custom-enabled-themes'; that's special.
-         (unless (eq symbol 'custom-enabled-themes)
+         ;; Ignore `custom-enabled-themes' and `custom-safe-themes'.
+         (unless (memq symbol '(custom-enabled-themes custom-safe-themes))
            (custom-theme-recalc-variable symbol)))))))
   (unless (eq theme 'user)
     (setq custom-enabled-themes
@@ -1291,7 +1322,10 @@ This list does not include the `user' theme, which is set by
 Customize and always takes precedence over other Custom Themes.
 
 This variable cannot be defined inside a Custom theme; there, it
-is simply ignored."
+is simply ignored.
+
+Setting this variable through Customize calls `enable-theme' or
+`load-theme' for each theme in the list."
   :group 'customize
   :type  '(repeat symbol)
   :set-after '(custom-theme-directory custom-theme-load-path
@@ -1345,11 +1379,33 @@ See `custom-enabled-themes' for a list of enabled themes."
            ;; If the face spec specified by this theme is in the
            ;; saved-face property, reset that property.
            (when (equal (nth 3 s) (get symbol 'saved-face))
-             (put symbol 'saved-face (and val (cadr (car val)))))
-           (custom-theme-recalc-face symbol)))))
+             (put symbol 'saved-face (and val (cadr (car val)))))))))
+      ;; Recompute faces on all frames.
+      (dolist (frame (frame-list))
+       ;; We must reset the fg and bg color frame parameters, or
+       ;; `face-set-after-frame-default' will use the existing
+       ;; parameters, which could be from the disabled theme.
+       (set-frame-parameter frame 'background-color
+                            (custom--frame-color-default
+                             frame :background "background" "Background"
+                             "unspecified-bg" "white"))
+       (set-frame-parameter frame 'foreground-color
+                            (custom--frame-color-default
+                             frame :foreground "foreground" "Foreground"
+                             "unspecified-fg" "black"))
+       (face-set-after-frame-default frame))
       (setq custom-enabled-themes
            (delq theme custom-enabled-themes)))))
 
+(defun custom--frame-color-default (frame attribute resource-attr resource-class
+                                         tty-default x-default)
+  (let ((col (face-attribute 'default attribute t)))
+    (cond
+     ((and col (not (eq col 'unspecified))) col)
+     ((null (window-system frame)) tty-default)
+     ((setq col (x-get-resource resource-attr resource-class)) col)
+     (t x-default))))
+
 (defun custom-variable-theme-value (variable)
   "Return (list VALUE) indicating the custom theme value of VARIABLE.
 That is to say, it specifies what the value should be according to
@@ -1381,7 +1437,7 @@ This function returns nil if no custom theme specifies a value for VARIABLE."
     (face-spec-recalc face frame)))
 
 \f
-;;; XEmacs compability functions
+;;; XEmacs compatibility functions
 
 ;; In XEmacs, when you reset a Custom Theme, you have to specify the
 ;; theme to reset it to.  We just apply the next available theme, so