]> code.delx.au - gnu-emacs/blobdiff - lisp/custom.el
Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[gnu-emacs] / lisp / custom.el
index 01b0e6d16504329f62b5541628b6961de8368ca1..4cf9609123a9cbbcd33e938d31ded65009728278 100644 (file)
@@ -1,6 +1,7 @@
 ;;; custom.el --- tools for declaring and initializing options
 ;;
-;; Copyright (C) 1996-1997, 1999, 2001-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999, 2001-2013 Free Software Foundation,
+;; Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -350,68 +351,62 @@ FACE does not need to be quoted.
 
 Third argument DOC is the face documentation.
 
-If FACE has been set with `custom-set-faces', set the face attributes
-as specified by that function, otherwise set the face attributes
-according to SPEC.
-
-The remaining arguments should have the form
-
-   [KEYWORD VALUE]...
+If FACE has been set with `custom-set-faces', set the face
+attributes as specified by that function, otherwise set the face
+attributes according to SPEC.
 
+The remaining arguments should have the form [KEYWORD VALUE]...
 For a list of valid keywords, see the common keywords listed in
 `defcustom'.
 
-SPEC should be an alist of the form ((DISPLAY ATTS)...).
-
-In the first element, DISPLAY can be `default'.  The ATTS in that
-element then act as defaults for all the following elements.
-
-Aside from that, DISPLAY specifies conditions to match some or
-all frames.  For each frame, the first element of SPEC where the
-DISPLAY conditions are satisfied is the one that applies to that
-frame.  The ATTRs in this element take effect, and the following
-elements are ignored, on that frame.
-
-In the last element, DISPLAY can be t.  That element applies to a
-frame if none of the previous elements (except the `default' if
-any) did.
-
-ATTS is a list of face attributes followed by their values:
-  (ATTR VALUE ATTR VALUE...)
-
-The possible attributes are `:family', `:width', `:height', `:weight',
-`:slant', `:underline', `:overline', `:strike-through', `:box',
-`:foreground', `:background', `:stipple', `:inverse-video', and `:inherit'.
-
-DISPLAY can be `default' (only in the first element), the symbol
-t (only in the last element) to match all frames, or an alist of
-conditions of the form \(REQ ITEM...).  For such an alist to
-match a frame, each of the conditions must be satisfied, meaning
-that the REQ property of the frame must match one of the
-corresponding ITEMs.  These are the defined REQ values:
-
-`type' (the value of `window-system')
-  Under X, in addition to the values `window-system' can take,
-  `motif', `lucid', `gtk' and `x-toolkit' are allowed, and match when
-  the Motif toolkit, Lucid toolkit, GTK toolkit or any X toolkit is in use.
-
-`class' (the frame's color support)
-  Should be one of `color', `grayscale', or `mono'.
-
-`background' (what color is used for the background text)
-  Should be one of `light' or `dark'.
-
-`min-colors' (the minimum number of colors the frame should support)
-  Should be an integer, it is compared with the result of
-  `display-color-cells'.
-
-`supports' (only match frames that support the specified face attributes)
-  Should be a list of face attributes.  See the documentation for
-  the function `display-supports-face-attributes-p' for more
-  information on exactly how testing is done.
-
-See Info node `(elisp) Customization' in the Emacs Lisp manual
-for more information."
+SPEC should be an alist of the form
+
+   ((DISPLAY . ATTS)...)
+
+where DISPLAY is a form specifying conditions to match certain
+terminals and ATTS is a property list (ATTR VALUE ATTR VALUE...)
+specifying face attributes and values for frames on those
+terminals.  On each terminal, the first element with a matching
+DISPLAY specification takes effect, and the remaining elements in
+SPEC are disregarded.
+
+As a special exception, in the first element of SPEC, DISPLAY can
+be the special value `default'.  Then the ATTS in that element
+act as defaults for all the following elements.
+
+For backward compatibility, elements of SPEC can be written
+as (DISPLAY ATTS) instead of (DISPLAY . ATTS).
+
+Each DISPLAY can have the following values:
+ - `default' (only in the first element).
+ - The symbol t, which matches all terminals.
+ - An alist of conditions.  Each alist element must have the form
+   (REQ ITEM...).  A matching terminal must satisfy each
+   specified condition by matching one of its ITEMs.  Each REQ
+   must be one of the following:
+   - `type' (the terminal type).
+     Each ITEM must be one of the values returned by
+     `window-system'.  Under X, additional allowed values are
+     `motif', `lucid', `gtk' and `x-toolkit'.
+   - `class' (the terminal's color support).
+     Each ITEM should be one of `color', `grayscale', or `mono'.
+   - `background' (what color is used for the background text)
+     Each ITEM should be one of `light' or `dark'.
+   - `min-colors' (the minimum number of supported colors)
+     Each ITEM should be an integer, which is compared with the
+     result of `display-color-cells'.
+   - `supports' (match terminals supporting certain attributes).
+     Each ITEM should be a list of face attributes.  See
+     `display-supports-face-attributes-p' for more information on
+     exactly how testing is done.
+
+In the ATTS property list, possible attributes are `:family',
+`:width', `:height', `:weight', `:slant', `:underline',
+`:overline', `:strike-through', `:box', `:foreground',
+`:background', `:stipple', `:inverse-video', and `:inherit'.
+
+See Info node `(elisp) Faces' in the Emacs Lisp manual for more
+information."
   (declare (doc-string 3))
   ;; It is better not to use backquote in this file,
   ;; because that makes a bootstrapping problem
@@ -954,7 +949,6 @@ prior to evaluating EXP).
 
 COMMENT is a comment string about SYMBOL."
   (custom-check-theme theme)
-
   ;; Process all the needed autoloads before anything else, so that the
   ;; subsequent code has all the info it needs (e.g. which var corresponds
   ;; to a minor mode), regardless of the ordering of the variables.
@@ -964,29 +958,7 @@ COMMENT is a comment string about SYMBOL."
                   (memq (get symbol 'custom-autoload) '(nil noset)))
         ;; This symbol needs to be autoloaded, even just for a `set'.
         (custom-load-symbol symbol))))
-
-  ;; Move minor modes and variables with explicit requires to the end.
-  (setq args
-       (sort args
-             (lambda (a1 a2)
-               (let* ((sym1 (car a1))
-                      (sym2 (car a2))
-                      (1-then-2 (memq sym1 (get sym2 'custom-dependencies)))
-                      (2-then-1 (memq sym2 (get sym1 'custom-dependencies))))
-                 (cond ((and 1-then-2 2-then-1)
-                        (error "Circular custom dependency between `%s' and `%s'"
-                               sym1 sym2))
-                       (2-then-1 nil)
-                       ;; 1 is a dependency of 2, so needs to be set first.
-                       (1-then-2)
-                       ;; Put minor modes and symbols with :require last.
-                       ;; Putting minor modes last ensures that the mode
-                       ;; function will see other customized values rather
-                       ;; than default values.
-                       (t (or (nth 3 a2)
-                               (eq (get sym2 'custom-set)
-                                   'custom-set-minor-mode))))))))
-
+  (setq args (custom--sort-vars args))
   (dolist (entry args)
     (unless (listp entry)
       (error "Incompatible Custom theme spec"))
@@ -1020,6 +992,60 @@ COMMENT is a comment string about SYMBOL."
          (and (or now (default-boundp symbol))
               (put symbol 'variable-comment comment)))))))
 
+(defvar custom--sort-vars-table)
+(defvar custom--sort-vars-result)
+
+(defun custom--sort-vars (vars)
+  "Sort VARS based on custom dependencies.
+VARS is a list whose elements have the same form as the ARGS
+arguments to `custom-theme-set-variables'.  Return the sorted
+list, in which A occurs before B if B was defined with a
+`:set-after' keyword specifying A (see `defcustom')."
+  (let ((custom--sort-vars-table (make-hash-table))
+       (dependants (make-hash-table))
+       (custom--sort-vars-result nil)
+       last)
+    ;; Construct a pair of tables keyed with the symbols of VARS.
+    (dolist (var vars)
+      (puthash (car var) (cons t var) custom--sort-vars-table)
+      (puthash (car var) var dependants))
+    ;; From the second table, remove symbols that are depended-on.
+    (dolist (var vars)
+      (dolist (dep (get (car var) 'custom-dependencies))
+       (remhash dep dependants)))
+    ;; If a variable is "stand-alone", put it last if it's a minor
+    ;; mode or has a :require flag.  This is not really necessary, but
+    ;; putting minor modes last helps ensure that the mode function
+    ;; sees other customized values rather than default values.
+    (maphash (lambda (sym var)
+              (when (and (null (get sym 'custom-dependencies))
+                         (or (nth 3 var)
+                             (eq (get sym 'custom-set)
+                                 'custom-set-minor-mode)))
+                (remhash sym dependants)
+                (push var last)))
+            dependants)
+    ;; The remaining symbols depend on others but are not
+    ;; depended-upon.  Do a depth-first topological sort.
+    (maphash #'custom--sort-vars-1 dependants)
+    (nreverse (append last custom--sort-vars-result))))
+
+(defun custom--sort-vars-1 (sym &optional _ignored)
+  (let ((elt (gethash sym custom--sort-vars-table)))
+    ;; The car of the hash table value is nil if the variable has
+    ;; already been processed, `dependant' if it is a dependant in the
+    ;; current graph descent, and t otherwise.
+    (when elt
+      (cond
+       ((eq (car elt) 'dependant)
+       (error "Circular custom dependency on `%s'" sym))
+       ((car elt)
+       (setcar elt 'dependant)
+       (dolist (dep (get sym 'custom-dependencies))
+         (custom--sort-vars-1 dep))
+       (setcar elt nil)
+       (push (cdr elt) custom--sort-vars-result))))))
+
 \f
 ;;; Defining themes.
 
@@ -1199,7 +1225,8 @@ Return t if THEME was successfully loaded, nil otherwise."
                            (expand-file-name "themes/" data-directory)))
                (member hash custom-safe-themes)
                (custom-theme-load-confirm hash))
-       (let ((custom--inhibit-theme-enable t))
+       (let ((custom--inhibit-theme-enable t)
+              (buffer-file-name fn))    ;For load-history.
          (eval-buffer))
        ;; Optimization: if the theme changes the `default' face, put that
        ;; entry first.  This avoids some `frame-set-background-mode' rigmarole