summary refs log tree commit diff
path: root/pkgs/lib/default.nix
diff options
context:
space:
mode:
authorNicolas Pierron <nicolas.b.pierron@gmail.com>2009-01-25 00:31:23 +0000
committerNicolas Pierron <nicolas.b.pierron@gmail.com>2009-01-25 00:31:23 +0000
commit13d5c8923d9fd93fcef50d88546cae8dbe7316b1 (patch)
tree2024473d3571b7dce2f195d9cc4abfbded355e5d /pkgs/lib/default.nix
parentdb7f0d3ef582b0c251acfd9b1eb7944df6954572 (diff)
downloadnixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar.gz
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar.bz2
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar.lz
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar.xz
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.tar.zst
nixlib-13d5c8923d9fd93fcef50d88546cae8dbe7316b1.zip
factor mergeOptionSets and filterOptionSets into the function handleOptionSets.
svn path=/nixpkgs/trunk/; revision=13838
Diffstat (limited to 'pkgs/lib/default.nix')
-rw-r--r--pkgs/lib/default.nix81
1 files changed, 52 insertions, 29 deletions
diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 73cb9d383c44..cbe2938483d7 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -485,11 +485,11 @@ rec {
     else if all __isAttrs list then mergeAttrs list
     else if all (x: true == x || false == x) list then fold logicalOR false list
     else if all (x: x == toString x) list then concatStrings list
-    else abort "${name}: Cannot merge values.";
+    else throw "Cannot merge values.";
 
   mergeTypedOption = typeName: predicate: merge: name: list:
     if all predicate list then merge list
-    else abort "${name}: Expect a ${typeName}.";
+    else throw "Expect a ${typeName}.";
 
   mergeEnableOption = mergeTypedOption "boolean"
     (x: true == x || false == x) (fold logicalOR false);
@@ -501,38 +501,59 @@ rec {
     (x: if builtins ? isString then builtins.isString x else x + "")
     concatStrings;
 
-  # Merge sets of options and bindings.
-  # noOption: function to call if no option is declared.
-  mergeOptionSets = noOption: path: opts:
-    if all __isAttrs opts then
-      zip (attr: opts:
-        let
-          name = if path == "" then attr else path + "." + attr;
-          test = partition isOption opts;
-          opt = ({ merge = mergeDefaultOption; apply = id; } // head test.right);
-        in
-          if test.right == [] then mergeOptionSets noOption name (map delayIf test.wrong)
-          else if tail test.right != [] then throw "Multiple options for '${name}'."
-          else if test.wrong == [] then opt.apply opt.default
-          else opt.apply (opt.merge name (map evalIf test.wrong))
-      ) opts
-   else noOption path opts;
 
-  # Keep all option declarations and add an attribute "name" inside
-  # each option which contains the path that has to be followed to
-  # access it.
-  filterOptionSets = path: opts:
+  # Handle the traversal of option sets.  All sets inside 'opts' are zipped
+  # and options declaration and definition are separated.  If no option are
+  # declared at a specific depth, then the function recurse into the values.
+  # Other cases are handled by the optionHandler which contains two
+  # functions that are used to defined your goal.
+  # - export is a function which takes two arguments which are the option
+  # and the list of values.
+  # - notHandle is a function which takes the list of values are not handle
+  # by this function.
+  handleOptionSets = optionHandler@{export, notHandle, ...}: path: opts:
     if all __isAttrs opts then
       zip (attr: opts:
         let
           name = if path == "" then attr else path + "." + attr;
           test = partition isOption opts;
+          opt = {
+            inherit name;
+            merge = mergeDefaultOption;
+            apply = id;
+          } // (head test.right);
         in
-          if test.right == [] then filterOptionSets name (map delayIf test.wrong)
-          else if tail test.right != [] then  throw "Multiple options for '${name}'."
-          else { inherit name; } // (head test.right)
+          if test.right == [] then handleOptionSets optionHandler name (map delayIf test.wrong)
+          else addLocation "while evaluating the option ${name}:" (
+            if tail test.right != [] then throw "Multiple options."
+            else export opt (map evalIf test.wrong)
+          )
       ) opts
-    else {};
+   else addLocation "while evaluating ${path}:" (notHandle opts);
+
+  # Merge option sets and produce a set of values which is the merging of
+  # all options declare and defined.  If no values are defined for an
+  # option, then the default value is used otherwise it use the merge
+  # function of each option to get the result.
+  mergeOptionSets = noOption: newMergeOptionSets; # ignore argument
+  newMergeOptionSets =
+    handleOptionSets {
+      export = opt: values:
+        opt.apply (
+          if values == [] then
+            if opt ? default then opt.default
+            else throw "Not defined."
+          else opt.merge (opt.name) values
+        );
+      notHandle = throw "Used without option declaration.";
+    };
+
+  # Keep all option declarations.
+  filterOptionSets =
+    handleOptionSets {
+      export = opt: values: opt;
+      notHandle = {};
+    };
 
   # Evaluate a list of option sets that would be merged with the
   # function "merge" which expects two arguments.  The attribute named
@@ -550,11 +571,11 @@ rec {
       # call configuration "files" with one of the existing convention.
       optionSet = config: configFun:
         if __isFunction configFun then
-          let result = configFun { inherit pkgs config; }; in
-        # {pkgs, config, ...}: {..}
+          let result = configFun { inherit pkgs config merge; }; in
+        # {pkgs, config, merge, ...}: {..}
           if builtins.isAttrs result then result
         # pkgs: config: {..}
-          else configFun pkgs config
+          else builtins.trace "obsolete:" (configFun {} {})
         # {..}
         else configFun;
 
@@ -592,6 +613,8 @@ rec {
 	innerModifySumArgs f x (a // b);
   modifySumArgs = f: x: innerModifySumArgs f x {};
 
+  addLocation = if builtins ? addLocation then builtins.addLocation else msg: val: val;
+
   debugVal = if builtins ? trace then x: (builtins.trace x x) else x: x;
   debugXMLVal = if builtins ? trace then x: (builtins.trace (builtins.toXML x) x) else x: x;