Merge pull request #49383 from tazjin/docs/lib-docstrings
Update library function "docstrings" for nixdoc generation
This commit is contained in:
commit
0c5d9e5c52
|
@ -23,27 +23,54 @@ rec {
|
||||||
|
|
||||||
# -- TRACING --
|
# -- TRACING --
|
||||||
|
|
||||||
/* Trace msg, but only if pred is true.
|
/* Conditionally trace the supplied message, based on a predicate.
|
||||||
|
|
||||||
|
Type: traceIf :: bool -> string -> a -> a
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
traceIf true "hello" 3
|
traceIf true "hello" 3
|
||||||
trace: hello
|
trace: hello
|
||||||
=> 3
|
=> 3
|
||||||
*/
|
*/
|
||||||
traceIf = pred: msg: x: if pred then trace msg x else x;
|
traceIf =
|
||||||
|
# Predicate to check
|
||||||
|
pred:
|
||||||
|
# Message that should be traced
|
||||||
|
msg:
|
||||||
|
# Value to return
|
||||||
|
x: if pred then trace msg x else x;
|
||||||
|
|
||||||
/* Trace the value and also return it.
|
/* Trace the supplied value after applying a function to it, and
|
||||||
|
return the original value.
|
||||||
|
|
||||||
|
Type: traceValFn :: (a -> b) -> a -> a
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
traceValFn (v: "mystring ${v}") "foo"
|
traceValFn (v: "mystring ${v}") "foo"
|
||||||
trace: mystring foo
|
trace: mystring foo
|
||||||
=> "foo"
|
=> "foo"
|
||||||
*/
|
*/
|
||||||
traceValFn = f: x: trace (f x) x;
|
traceValFn =
|
||||||
|
# Function to apply
|
||||||
|
f:
|
||||||
|
# Value to trace and return
|
||||||
|
x: trace (f x) x;
|
||||||
|
|
||||||
|
/* Trace the supplied value and return it.
|
||||||
|
|
||||||
|
Type: traceVal :: a -> a
|
||||||
|
|
||||||
|
Example:
|
||||||
|
traceVal 42
|
||||||
|
# trace: 42
|
||||||
|
=> 42
|
||||||
|
*/
|
||||||
traceVal = traceValFn id;
|
traceVal = traceValFn id;
|
||||||
|
|
||||||
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
|
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
|
||||||
|
|
||||||
|
Type: traceSeq :: a -> b -> b
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
trace { a.b.c = 3; } null
|
trace { a.b.c = 3; } null
|
||||||
trace: { a = <CODE>; }
|
trace: { a = <CODE>; }
|
||||||
|
@ -52,7 +79,11 @@ rec {
|
||||||
trace: { a = { b = { c = 3; }; }; }
|
trace: { a = { b = { c = 3; }; }; }
|
||||||
=> null
|
=> null
|
||||||
*/
|
*/
|
||||||
traceSeq = x: y: trace (builtins.deepSeq x x) y;
|
traceSeq =
|
||||||
|
# The value to trace
|
||||||
|
x:
|
||||||
|
# The value to return
|
||||||
|
y: trace (builtins.deepSeq x x) y;
|
||||||
|
|
||||||
/* Like `traceSeq`, but only evaluate down to depth n.
|
/* Like `traceSeq`, but only evaluate down to depth n.
|
||||||
This is very useful because lots of `traceSeq` usages
|
This is very useful because lots of `traceSeq` usages
|
||||||
|
@ -76,27 +107,49 @@ rec {
|
||||||
in trace (generators.toPretty { allowPrettyValues = true; }
|
in trace (generators.toPretty { allowPrettyValues = true; }
|
||||||
(modify depth snip x)) y;
|
(modify depth snip x)) y;
|
||||||
|
|
||||||
/* A combination of `traceVal` and `traceSeq` */
|
/* A combination of `traceVal` and `traceSeq` that applies a
|
||||||
traceValSeqFn = f: v: traceValFn f (builtins.deepSeq v v);
|
provided function to the value to be traced after `deepSeq`ing
|
||||||
|
it.
|
||||||
|
*/
|
||||||
|
traceValSeqFn =
|
||||||
|
# Function to apply
|
||||||
|
f:
|
||||||
|
# Value to trace
|
||||||
|
v: traceValFn f (builtins.deepSeq v v);
|
||||||
|
|
||||||
|
/* A combination of `traceVal` and `traceSeq`. */
|
||||||
traceValSeq = traceValSeqFn id;
|
traceValSeq = traceValSeqFn id;
|
||||||
|
|
||||||
|
/* A combination of `traceVal` and `traceSeqN` that applies a
|
||||||
|
provided function to the value to be traced. */
|
||||||
|
traceValSeqNFn =
|
||||||
|
# Function to apply
|
||||||
|
f:
|
||||||
|
depth:
|
||||||
|
# Value to trace
|
||||||
|
v: traceSeqN depth (f v) v;
|
||||||
|
|
||||||
/* A combination of `traceVal` and `traceSeqN`. */
|
/* A combination of `traceVal` and `traceSeqN`. */
|
||||||
traceValSeqNFn = f: depth: v: traceSeqN depth (f v) v;
|
|
||||||
traceValSeqN = traceValSeqNFn id;
|
traceValSeqN = traceValSeqNFn id;
|
||||||
|
|
||||||
|
|
||||||
# -- TESTING --
|
# -- TESTING --
|
||||||
|
|
||||||
/* Evaluate a set of tests. A test is an attribute set {expr,
|
/* Evaluate a set of tests. A test is an attribute set `{expr,
|
||||||
expected}, denoting an expression and its expected result. The
|
expected}`, denoting an expression and its expected result. The
|
||||||
result is a list of failed tests, each represented as {name,
|
result is a list of failed tests, each represented as `{name,
|
||||||
expected, actual}, denoting the attribute name of the failing
|
expected, actual}`, denoting the attribute name of the failing
|
||||||
test and its expected and actual results. Used for regression
|
test and its expected and actual results.
|
||||||
testing of the functions in lib; see tests.nix for an example.
|
|
||||||
Only tests having names starting with "test" are run.
|
Used for regression testing of the functions in lib; see
|
||||||
Add attr { tests = ["testName"]; } to run these test only
|
tests.nix for an example. Only tests having names starting with
|
||||||
|
"test" are run.
|
||||||
|
|
||||||
|
Add attr { tests = ["testName"]; } to run these tests only.
|
||||||
*/
|
*/
|
||||||
runTests = tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
|
runTests =
|
||||||
|
# Tests to run
|
||||||
|
tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
|
||||||
let testsToRun = if tests ? tests then tests.tests else [];
|
let testsToRun = if tests ? tests then tests.tests else [];
|
||||||
in if (substring 0 4 name == "test" || elem name testsToRun)
|
in if (substring 0 4 name == "test" || elem name testsToRun)
|
||||||
&& ((testsToRun == []) || elem name tests.tests)
|
&& ((testsToRun == []) || elem name tests.tests)
|
||||||
|
@ -105,8 +158,11 @@ rec {
|
||||||
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
||||||
else [] ) tests));
|
else [] ) tests));
|
||||||
|
|
||||||
# create a test assuming that list elements are true
|
/* Create a test assuming that list elements are `true`.
|
||||||
# usage: { testX = allTrue [ true ]; }
|
|
||||||
|
Example:
|
||||||
|
{ testX = allTrue [ true ]; }
|
||||||
|
*/
|
||||||
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
|
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
|
||||||
|
|
||||||
|
|
||||||
|
|
184
lib/lists.nix
184
lib/lists.nix
|
@ -1,4 +1,5 @@
|
||||||
# General list operations.
|
# General list operations.
|
||||||
|
|
||||||
{ lib }:
|
{ lib }:
|
||||||
with lib.trivial;
|
with lib.trivial;
|
||||||
let
|
let
|
||||||
|
@ -8,21 +9,23 @@ rec {
|
||||||
|
|
||||||
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
||||||
|
|
||||||
/* Create a list consisting of a single element. `singleton x' is
|
/* Create a list consisting of a single element. `singleton x` is
|
||||||
sometimes more convenient with respect to indentation than `[x]'
|
sometimes more convenient with respect to indentation than `[x]`
|
||||||
when x spans multiple lines.
|
when x spans multiple lines.
|
||||||
|
|
||||||
|
Type: singleton :: a -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
singleton "foo"
|
singleton "foo"
|
||||||
=> [ "foo" ]
|
=> [ "foo" ]
|
||||||
*/
|
*/
|
||||||
singleton = x: [x];
|
singleton = x: [x];
|
||||||
|
|
||||||
/* “right fold” a binary function `op' between successive elements of
|
/* “right fold” a binary function `op` between successive elements of
|
||||||
`list' with `nul' as the starting value, i.e.,
|
`list` with `nul' as the starting value, i.e.,
|
||||||
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.
|
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
|
||||||
Type:
|
|
||||||
foldr :: (a -> b -> b) -> b -> [a] -> b
|
Type: foldr :: (a -> b -> b) -> b -> [a] -> b
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concat = foldr (a: b: a + b) "z"
|
concat = foldr (a: b: a + b) "z"
|
||||||
|
@ -42,16 +45,15 @@ rec {
|
||||||
else op (elemAt list n) (fold' (n + 1));
|
else op (elemAt list n) (fold' (n + 1));
|
||||||
in fold' 0;
|
in fold' 0;
|
||||||
|
|
||||||
/* `fold' is an alias of `foldr' for historic reasons */
|
/* `fold` is an alias of `foldr` for historic reasons */
|
||||||
# FIXME(Profpatsch): deprecate?
|
# FIXME(Profpatsch): deprecate?
|
||||||
fold = foldr;
|
fold = foldr;
|
||||||
|
|
||||||
|
|
||||||
/* “left fold”, like `foldr', but from the left:
|
/* “left fold”, like `foldr`, but from the left:
|
||||||
`foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
|
`foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
|
||||||
|
|
||||||
Type:
|
Type: foldl :: (b -> a -> b) -> b -> [a] -> b
|
||||||
foldl :: (b -> a -> b) -> b -> [a] -> b
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
lconcat = foldl (a: b: a + b) "z"
|
lconcat = foldl (a: b: a + b) "z"
|
||||||
|
@ -70,16 +72,20 @@ rec {
|
||||||
else op (foldl' (n - 1)) (elemAt list n);
|
else op (foldl' (n - 1)) (elemAt list n);
|
||||||
in foldl' (length list - 1);
|
in foldl' (length list - 1);
|
||||||
|
|
||||||
/* Strict version of `foldl'.
|
/* Strict version of `foldl`.
|
||||||
|
|
||||||
The difference is that evaluation is forced upon access. Usually used
|
The difference is that evaluation is forced upon access. Usually used
|
||||||
with small whole results (in contract with lazily-generated list or large
|
with small whole results (in contract with lazily-generated list or large
|
||||||
lists where only a part is consumed.)
|
lists where only a part is consumed.)
|
||||||
|
|
||||||
|
Type: foldl' :: (b -> a -> b) -> b -> [a] -> b
|
||||||
*/
|
*/
|
||||||
foldl' = builtins.foldl' or foldl;
|
foldl' = builtins.foldl' or foldl;
|
||||||
|
|
||||||
/* Map with index starting from 0
|
/* Map with index starting from 0
|
||||||
|
|
||||||
|
Type: imap0 :: (int -> a -> b) -> [a] -> [b]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
imap0 (i: v: "${v}-${toString i}") ["a" "b"]
|
imap0 (i: v: "${v}-${toString i}") ["a" "b"]
|
||||||
=> [ "a-0" "b-1" ]
|
=> [ "a-0" "b-1" ]
|
||||||
|
@ -88,6 +94,8 @@ rec {
|
||||||
|
|
||||||
/* Map with index starting from 1
|
/* Map with index starting from 1
|
||||||
|
|
||||||
|
Type: imap1 :: (int -> a -> b) -> [a] -> [b]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
imap1 (i: v: "${v}-${toString i}") ["a" "b"]
|
imap1 (i: v: "${v}-${toString i}") ["a" "b"]
|
||||||
=> [ "a-1" "b-2" ]
|
=> [ "a-1" "b-2" ]
|
||||||
|
@ -96,6 +104,8 @@ rec {
|
||||||
|
|
||||||
/* Map and concatenate the result.
|
/* Map and concatenate the result.
|
||||||
|
|
||||||
|
Type: concatMap :: (a -> [b]) -> [a] -> [b]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatMap (x: [x] ++ ["z"]) ["a" "b"]
|
concatMap (x: [x] ++ ["z"]) ["a" "b"]
|
||||||
=> [ "a" "z" "b" "z" ]
|
=> [ "a" "z" "b" "z" ]
|
||||||
|
@ -118,15 +128,21 @@ rec {
|
||||||
|
|
||||||
/* Remove elements equal to 'e' from a list. Useful for buildInputs.
|
/* Remove elements equal to 'e' from a list. Useful for buildInputs.
|
||||||
|
|
||||||
|
Type: remove :: a -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
remove 3 [ 1 3 4 3 ]
|
remove 3 [ 1 3 4 3 ]
|
||||||
=> [ 1 4 ]
|
=> [ 1 4 ]
|
||||||
*/
|
*/
|
||||||
remove = e: filter (x: x != e);
|
remove =
|
||||||
|
# Element to remove from the list
|
||||||
|
e: filter (x: x != e);
|
||||||
|
|
||||||
/* Find the sole element in the list matching the specified
|
/* Find the sole element in the list matching the specified
|
||||||
predicate, returns `default' if no such element exists, or
|
predicate, returns `default` if no such element exists, or
|
||||||
`multiple' if there are multiple matching elements.
|
`multiple` if there are multiple matching elements.
|
||||||
|
|
||||||
|
Type: findSingle :: (a -> bool) -> a -> a -> [a] -> a
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
|
findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
|
||||||
|
@ -136,14 +152,24 @@ rec {
|
||||||
findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
|
findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
|
||||||
=> "none"
|
=> "none"
|
||||||
*/
|
*/
|
||||||
findSingle = pred: default: multiple: list:
|
findSingle =
|
||||||
|
# Predicate
|
||||||
|
pred:
|
||||||
|
# Default value to return if element was not found.
|
||||||
|
default:
|
||||||
|
# Default value to return if more than one element was found
|
||||||
|
multiple:
|
||||||
|
# Input list
|
||||||
|
list:
|
||||||
let found = filter pred list; len = length found;
|
let found = filter pred list; len = length found;
|
||||||
in if len == 0 then default
|
in if len == 0 then default
|
||||||
else if len != 1 then multiple
|
else if len != 1 then multiple
|
||||||
else head found;
|
else head found;
|
||||||
|
|
||||||
/* Find the first element in the list matching the specified
|
/* Find the first element in the list matching the specified
|
||||||
predicate or returns `default' if no such element exists.
|
predicate or return `default` if no such element exists.
|
||||||
|
|
||||||
|
Type: findFirst :: (a -> bool) -> a -> [a] -> a
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
findFirst (x: x > 3) 7 [ 1 6 4 ]
|
findFirst (x: x > 3) 7 [ 1 6 4 ]
|
||||||
|
@ -151,12 +177,20 @@ rec {
|
||||||
findFirst (x: x > 9) 7 [ 1 6 4 ]
|
findFirst (x: x > 9) 7 [ 1 6 4 ]
|
||||||
=> 7
|
=> 7
|
||||||
*/
|
*/
|
||||||
findFirst = pred: default: list:
|
findFirst =
|
||||||
|
# Predicate
|
||||||
|
pred:
|
||||||
|
# Default value to return
|
||||||
|
default:
|
||||||
|
# Input list
|
||||||
|
list:
|
||||||
let found = filter pred list;
|
let found = filter pred list;
|
||||||
in if found == [] then default else head found;
|
in if found == [] then default else head found;
|
||||||
|
|
||||||
/* Return true iff function `pred' returns true for at least element
|
/* Return true if function `pred` returns true for at least one
|
||||||
of `list'.
|
element of `list`.
|
||||||
|
|
||||||
|
Type: any :: (a -> bool) -> [a] -> bool
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
any isString [ 1 "a" { } ]
|
any isString [ 1 "a" { } ]
|
||||||
|
@ -166,8 +200,10 @@ rec {
|
||||||
*/
|
*/
|
||||||
any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
|
any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
|
||||||
|
|
||||||
/* Return true iff function `pred' returns true for all elements of
|
/* Return true if function `pred` returns true for all elements of
|
||||||
`list'.
|
`list`.
|
||||||
|
|
||||||
|
Type: all :: (a -> bool) -> [a] -> bool
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
all (x: x < 3) [ 1 2 ]
|
all (x: x < 3) [ 1 2 ]
|
||||||
|
@ -177,19 +213,25 @@ rec {
|
||||||
*/
|
*/
|
||||||
all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
|
all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
|
||||||
|
|
||||||
/* Count how many times function `pred' returns true for the elements
|
/* Count how many elements of `list` match the supplied predicate
|
||||||
of `list'.
|
function.
|
||||||
|
|
||||||
|
Type: count :: (a -> bool) -> [a] -> int
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
count (x: x == 3) [ 3 2 3 4 6 ]
|
count (x: x == 3) [ 3 2 3 4 6 ]
|
||||||
=> 2
|
=> 2
|
||||||
*/
|
*/
|
||||||
count = pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
count =
|
||||||
|
# Predicate
|
||||||
|
pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
||||||
|
|
||||||
/* Return a singleton list or an empty list, depending on a boolean
|
/* Return a singleton list or an empty list, depending on a boolean
|
||||||
value. Useful when building lists with optional elements
|
value. Useful when building lists with optional elements
|
||||||
(e.g. `++ optional (system == "i686-linux") flashplayer').
|
(e.g. `++ optional (system == "i686-linux") flashplayer').
|
||||||
|
|
||||||
|
Type: optional :: bool -> a -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
optional true "foo"
|
optional true "foo"
|
||||||
=> [ "foo" ]
|
=> [ "foo" ]
|
||||||
|
@ -200,13 +242,19 @@ rec {
|
||||||
|
|
||||||
/* Return a list or an empty list, depending on a boolean value.
|
/* Return a list or an empty list, depending on a boolean value.
|
||||||
|
|
||||||
|
Type: optionals :: bool -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
optionals true [ 2 3 ]
|
optionals true [ 2 3 ]
|
||||||
=> [ 2 3 ]
|
=> [ 2 3 ]
|
||||||
optionals false [ 2 3 ]
|
optionals false [ 2 3 ]
|
||||||
=> [ ]
|
=> [ ]
|
||||||
*/
|
*/
|
||||||
optionals = cond: elems: if cond then elems else [];
|
optionals =
|
||||||
|
# Condition
|
||||||
|
cond:
|
||||||
|
# List to return if condition is true
|
||||||
|
elems: if cond then elems else [];
|
||||||
|
|
||||||
|
|
||||||
/* If argument is a list, return it; else, wrap it in a singleton
|
/* If argument is a list, return it; else, wrap it in a singleton
|
||||||
|
@ -223,20 +271,28 @@ rec {
|
||||||
|
|
||||||
/* Return a list of integers from `first' up to and including `last'.
|
/* Return a list of integers from `first' up to and including `last'.
|
||||||
|
|
||||||
|
Type: range :: int -> int -> [int]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
range 2 4
|
range 2 4
|
||||||
=> [ 2 3 4 ]
|
=> [ 2 3 4 ]
|
||||||
range 3 2
|
range 3 2
|
||||||
=> [ ]
|
=> [ ]
|
||||||
*/
|
*/
|
||||||
range = first: last:
|
range =
|
||||||
|
# First integer in the range
|
||||||
|
first:
|
||||||
|
# Last integer in the range
|
||||||
|
last:
|
||||||
if first > last then
|
if first > last then
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
genList (n: first + n) (last - first + 1);
|
genList (n: first + n) (last - first + 1);
|
||||||
|
|
||||||
/* Splits the elements of a list in two lists, `right' and
|
/* Splits the elements of a list in two lists, `right` and
|
||||||
`wrong', depending on the evaluation of a predicate.
|
`wrong`, depending on the evaluation of a predicate.
|
||||||
|
|
||||||
|
Type: (a -> bool) -> [a] -> { right :: [a], wrong :: [a] }
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
partition (x: x > 2) [ 5 1 2 3 4 ]
|
partition (x: x > 2) [ 5 1 2 3 4 ]
|
||||||
|
@ -252,7 +308,7 @@ rec {
|
||||||
/* Splits the elements of a list into many lists, using the return value of a predicate.
|
/* Splits the elements of a list into many lists, using the return value of a predicate.
|
||||||
Predicate should return a string which becomes keys of attrset `groupBy' returns.
|
Predicate should return a string which becomes keys of attrset `groupBy' returns.
|
||||||
|
|
||||||
`groupBy'' allows to customise the combining function and initial value
|
`groupBy'` allows to customise the combining function and initial value
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
||||||
|
@ -268,10 +324,6 @@ rec {
|
||||||
xfce = [ { name = "xfce"; script = "xfce4-session &"; } ];
|
xfce = [ { name = "xfce"; script = "xfce4-session &"; } ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
groupBy' allows to customise the combining function and initial value
|
|
||||||
|
|
||||||
Example:
|
|
||||||
groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
||||||
=> { true = 12; false = 3; }
|
=> { true = 12; false = 3; }
|
||||||
*/
|
*/
|
||||||
|
@ -289,17 +341,27 @@ rec {
|
||||||
the merging stops at the shortest. How both lists are merged is defined
|
the merging stops at the shortest. How both lists are merged is defined
|
||||||
by the first argument.
|
by the first argument.
|
||||||
|
|
||||||
|
Type: zipListsWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
|
zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
|
||||||
=> ["he" "lo"]
|
=> ["he" "lo"]
|
||||||
*/
|
*/
|
||||||
zipListsWith = f: fst: snd:
|
zipListsWith =
|
||||||
|
# Function to zip elements of both lists
|
||||||
|
f:
|
||||||
|
# First list
|
||||||
|
fst:
|
||||||
|
# Second list
|
||||||
|
snd:
|
||||||
genList
|
genList
|
||||||
(n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
|
(n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
|
||||||
|
|
||||||
/* Merges two lists of the same size together. If the sizes aren't the same
|
/* Merges two lists of the same size together. If the sizes aren't the same
|
||||||
the merging stops at the shortest.
|
the merging stops at the shortest.
|
||||||
|
|
||||||
|
Type: zipLists :: [a] -> [b] -> [{ fst :: a, snd :: b}]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
zipLists [ 1 2 ] [ "a" "b" ]
|
zipLists [ 1 2 ] [ "a" "b" ]
|
||||||
=> [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
|
=> [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
|
||||||
|
@ -308,6 +370,8 @@ rec {
|
||||||
|
|
||||||
/* Reverse the order of the elements of a list.
|
/* Reverse the order of the elements of a list.
|
||||||
|
|
||||||
|
Type: reverseList :: [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
reverseList [ "b" "o" "j" ]
|
reverseList [ "b" "o" "j" ]
|
||||||
|
@ -321,8 +385,7 @@ rec {
|
||||||
`before a b == true` means that `b` depends on `a` (there's an
|
`before a b == true` means that `b` depends on `a` (there's an
|
||||||
edge from `b` to `a`).
|
edge from `b` to `a`).
|
||||||
|
|
||||||
Examples:
|
Example:
|
||||||
|
|
||||||
listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
|
listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
|
||||||
== { minimal = "/"; # minimal element
|
== { minimal = "/"; # minimal element
|
||||||
visited = [ "/home/user" ]; # seen elements (in reverse order)
|
visited = [ "/home/user" ]; # seen elements (in reverse order)
|
||||||
|
@ -336,7 +399,6 @@ rec {
|
||||||
rest = [ "/home" "other" ]; # everything else
|
rest = [ "/home" "other" ]; # everything else
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
listDfs = stopOnCycles: before: list:
|
listDfs = stopOnCycles: before: list:
|
||||||
let
|
let
|
||||||
dfs' = us: visited: rest:
|
dfs' = us: visited: rest:
|
||||||
|
@ -361,7 +423,7 @@ rec {
|
||||||
`before a b == true` means that `b` should be after `a`
|
`before a b == true` means that `b` should be after `a`
|
||||||
in the result.
|
in the result.
|
||||||
|
|
||||||
Examples:
|
Example:
|
||||||
|
|
||||||
toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
|
toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
|
||||||
== { result = [ "/" "/home" "/home/user" "other" ]; }
|
== { result = [ "/" "/home" "/home/user" "other" ]; }
|
||||||
|
@ -376,7 +438,6 @@ rec {
|
||||||
toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
|
toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
toposort = before: list:
|
toposort = before: list:
|
||||||
let
|
let
|
||||||
dfsthis = listDfs true before list;
|
dfsthis = listDfs true before list;
|
||||||
|
@ -467,26 +528,38 @@ rec {
|
||||||
|
|
||||||
/* Return the first (at most) N elements of a list.
|
/* Return the first (at most) N elements of a list.
|
||||||
|
|
||||||
|
Type: take :: int -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
take 2 [ "a" "b" "c" "d" ]
|
take 2 [ "a" "b" "c" "d" ]
|
||||||
=> [ "a" "b" ]
|
=> [ "a" "b" ]
|
||||||
take 2 [ ]
|
take 2 [ ]
|
||||||
=> [ ]
|
=> [ ]
|
||||||
*/
|
*/
|
||||||
take = count: sublist 0 count;
|
take =
|
||||||
|
# Number of elements to take
|
||||||
|
count: sublist 0 count;
|
||||||
|
|
||||||
/* Remove the first (at most) N elements of a list.
|
/* Remove the first (at most) N elements of a list.
|
||||||
|
|
||||||
|
Type: drop :: int -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
drop 2 [ "a" "b" "c" "d" ]
|
drop 2 [ "a" "b" "c" "d" ]
|
||||||
=> [ "c" "d" ]
|
=> [ "c" "d" ]
|
||||||
drop 2 [ ]
|
drop 2 [ ]
|
||||||
=> [ ]
|
=> [ ]
|
||||||
*/
|
*/
|
||||||
drop = count: list: sublist count (length list) list;
|
drop =
|
||||||
|
# Number of elements to drop
|
||||||
|
count:
|
||||||
|
# Input list
|
||||||
|
list: sublist count (length list) list;
|
||||||
|
|
||||||
/* Return a list consisting of at most ‘count’ elements of ‘list’,
|
/* Return a list consisting of at most `count` elements of `list`,
|
||||||
starting at index ‘start’.
|
starting at index `start`.
|
||||||
|
|
||||||
|
Type: sublist :: int -> int -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
sublist 1 3 [ "a" "b" "c" "d" "e" ]
|
sublist 1 3 [ "a" "b" "c" "d" "e" ]
|
||||||
|
@ -494,7 +567,13 @@ rec {
|
||||||
sublist 1 3 [ ]
|
sublist 1 3 [ ]
|
||||||
=> [ ]
|
=> [ ]
|
||||||
*/
|
*/
|
||||||
sublist = start: count: list:
|
sublist =
|
||||||
|
# Index at which to start the sublist
|
||||||
|
start:
|
||||||
|
# Number of elements to take
|
||||||
|
count:
|
||||||
|
# Input list
|
||||||
|
list:
|
||||||
let len = length list; in
|
let len = length list; in
|
||||||
genList
|
genList
|
||||||
(n: elemAt list (n + start))
|
(n: elemAt list (n + start))
|
||||||
|
@ -504,6 +583,10 @@ rec {
|
||||||
|
|
||||||
/* Return the last element of a list.
|
/* Return the last element of a list.
|
||||||
|
|
||||||
|
This function throws an error if the list is empty.
|
||||||
|
|
||||||
|
Type: last :: [a] -> a
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
last [ 1 2 3 ]
|
last [ 1 2 3 ]
|
||||||
=> 3
|
=> 3
|
||||||
|
@ -512,7 +595,11 @@ rec {
|
||||||
assert lib.assertMsg (list != []) "lists.last: list must not be empty!";
|
assert lib.assertMsg (list != []) "lists.last: list must not be empty!";
|
||||||
elemAt list (length list - 1);
|
elemAt list (length list - 1);
|
||||||
|
|
||||||
/* Return all elements but the last
|
/* Return all elements but the last.
|
||||||
|
|
||||||
|
This function throws an error if the list is empty.
|
||||||
|
|
||||||
|
Type: init :: [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
init [ 1 2 3 ]
|
init [ 1 2 3 ]
|
||||||
|
@ -523,7 +610,7 @@ rec {
|
||||||
take (length list - 1) list;
|
take (length list - 1) list;
|
||||||
|
|
||||||
|
|
||||||
/* return the image of the cross product of some lists by a function
|
/* Return the image of the cross product of some lists by a function.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
|
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
|
||||||
|
@ -534,8 +621,9 @@ rec {
|
||||||
|
|
||||||
/* Remove duplicate elements from the list. O(n^2) complexity.
|
/* Remove duplicate elements from the list. O(n^2) complexity.
|
||||||
|
|
||||||
Example:
|
Type: unique :: [a] -> [a]
|
||||||
|
|
||||||
|
Example:
|
||||||
unique [ 3 2 3 4 ]
|
unique [ 3 2 3 4 ]
|
||||||
=> [ 3 2 4 ]
|
=> [ 3 2 4 ]
|
||||||
*/
|
*/
|
||||||
|
|
155
lib/options.nix
155
lib/options.nix
|
@ -8,61 +8,72 @@ with lib.strings;
|
||||||
|
|
||||||
rec {
|
rec {
|
||||||
|
|
||||||
# Returns true when the given argument is an option
|
/* Returns true when the given argument is an option
|
||||||
#
|
|
||||||
# Examples:
|
Type: isOption :: a -> bool
|
||||||
# isOption 1 // => false
|
|
||||||
# isOption (mkOption {}) // => true
|
Example:
|
||||||
|
isOption 1 // => false
|
||||||
|
isOption (mkOption {}) // => true
|
||||||
|
*/
|
||||||
isOption = lib.isType "option";
|
isOption = lib.isType "option";
|
||||||
|
|
||||||
# Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
|
/* Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
|
||||||
#
|
|
||||||
# default: Default value used when no definition is given in the configuration.
|
All keys default to `null` when not given.
|
||||||
# defaultText: Textual representation of the default, for in the manual.
|
|
||||||
# example: Example value used in the manual.
|
Example:
|
||||||
# description: String describing the option.
|
mkOption { } // => { _type = "option"; }
|
||||||
# type: Option type, providing type-checking and value merging.
|
mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
|
||||||
# apply: Function that converts the option value to something else.
|
*/
|
||||||
# internal: Whether the option is for NixOS developers only.
|
|
||||||
# visible: Whether the option shows up in the manual.
|
|
||||||
# readOnly: Whether the option can be set only once
|
|
||||||
# options: Obsolete, used by types.optionSet.
|
|
||||||
#
|
|
||||||
# All keys default to `null` when not given.
|
|
||||||
#
|
|
||||||
# Examples:
|
|
||||||
# mkOption { } // => { _type = "option"; }
|
|
||||||
# mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
|
|
||||||
mkOption =
|
mkOption =
|
||||||
{ default ? null # Default value used when no definition is given in the configuration.
|
{
|
||||||
, defaultText ? null # Textual representation of the default, for in the manual.
|
# Default value used when no definition is given in the configuration.
|
||||||
, example ? null # Example value used in the manual.
|
default ? null,
|
||||||
, description ? null # String describing the option.
|
# Textual representation of the default, for the manual.
|
||||||
, relatedPackages ? null # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
|
defaultText ? null,
|
||||||
, type ? null # Option type, providing type-checking and value merging.
|
# Example value used in the manual.
|
||||||
, apply ? null # Function that converts the option value to something else.
|
example ? null,
|
||||||
, internal ? null # Whether the option is for NixOS developers only.
|
# String describing the option.
|
||||||
, visible ? null # Whether the option shows up in the manual.
|
description ? null,
|
||||||
, readOnly ? null # Whether the option can be set only once
|
# Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
|
||||||
, options ? null # Obsolete, used by types.optionSet.
|
relatedPackages ? null,
|
||||||
|
# Option type, providing type-checking and value merging.
|
||||||
|
type ? null,
|
||||||
|
# Function that converts the option value to something else.
|
||||||
|
apply ? null,
|
||||||
|
# Whether the option is for NixOS developers only.
|
||||||
|
internal ? null,
|
||||||
|
# Whether the option shows up in the manual.
|
||||||
|
visible ? null,
|
||||||
|
# Whether the option can be set only once
|
||||||
|
readOnly ? null,
|
||||||
|
# Obsolete, used by types.optionSet.
|
||||||
|
options ? null
|
||||||
} @ attrs:
|
} @ attrs:
|
||||||
attrs // { _type = "option"; };
|
attrs // { _type = "option"; };
|
||||||
|
|
||||||
# Creates a Option attribute set for a boolean value option i.e an option to be toggled on or off:
|
/* Creates an Option attribute set for a boolean value option i.e an
|
||||||
#
|
option to be toggled on or off:
|
||||||
# Examples:
|
|
||||||
# mkEnableOption "foo" // => { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
|
Example:
|
||||||
mkEnableOption = name: mkOption {
|
mkEnableOption "foo"
|
||||||
|
=> { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
|
||||||
|
*/
|
||||||
|
mkEnableOption =
|
||||||
|
# Name for the created option
|
||||||
|
name: mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
example = true;
|
example = true;
|
||||||
description = "Whether to enable ${name}.";
|
description = "Whether to enable ${name}.";
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
# This option accept anything, but it does not produce any result. This
|
/* This option accepts anything, but it does not produce any result.
|
||||||
# is useful for sharing a module across different module sets without
|
|
||||||
# having to implement similar features as long as the value of the options
|
This is useful for sharing a module across different module sets
|
||||||
# are not expected.
|
without having to implement similar features as long as the
|
||||||
|
values of the options are not accessed. */
|
||||||
mkSinkUndeclaredOptions = attrs: mkOption ({
|
mkSinkUndeclaredOptions = attrs: mkOption ({
|
||||||
internal = true;
|
internal = true;
|
||||||
visible = false;
|
visible = false;
|
||||||
|
@ -102,18 +113,24 @@ rec {
|
||||||
else
|
else
|
||||||
val) (head defs).value defs;
|
val) (head defs).value defs;
|
||||||
|
|
||||||
# Extracts values of all "value" keys of the given list
|
/* Extracts values of all "value" keys of the given list.
|
||||||
#
|
|
||||||
# Examples:
|
Type: getValues :: [ { value :: a } ] -> [a]
|
||||||
# getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
|
|
||||||
# getValues [ ] // => [ ]
|
Example:
|
||||||
|
getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
|
||||||
|
getValues [ ] // => [ ]
|
||||||
|
*/
|
||||||
getValues = map (x: x.value);
|
getValues = map (x: x.value);
|
||||||
|
|
||||||
# Extracts values of all "file" keys of the given list
|
/* Extracts values of all "file" keys of the given list
|
||||||
#
|
|
||||||
# Examples:
|
Type: getFiles :: [ { file :: a } ] -> [a]
|
||||||
# getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
|
|
||||||
# getFiles [ ] // => [ ]
|
Example:
|
||||||
|
getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
|
||||||
|
getFiles [ ] // => [ ]
|
||||||
|
*/
|
||||||
getFiles = map (x: x.file);
|
getFiles = map (x: x.file);
|
||||||
|
|
||||||
# Generate documentation template from the list of option declaration like
|
# Generate documentation template from the list of option declaration like
|
||||||
|
@ -146,10 +163,13 @@ rec {
|
||||||
|
|
||||||
|
|
||||||
/* This function recursively removes all derivation attributes from
|
/* This function recursively removes all derivation attributes from
|
||||||
`x' except for the `name' attribute. This is to make the
|
`x` except for the `name` attribute.
|
||||||
generation of `options.xml' much more efficient: the XML
|
|
||||||
representation of derivations is very large (on the order of
|
This is to make the generation of `options.xml` much more
|
||||||
megabytes) and is not actually used by the manual generator. */
|
efficient: the XML representation of derivations is very large
|
||||||
|
(on the order of megabytes) and is not actually used by the
|
||||||
|
manual generator.
|
||||||
|
*/
|
||||||
scrubOptionValue = x:
|
scrubOptionValue = x:
|
||||||
if isDerivation x then
|
if isDerivation x then
|
||||||
{ type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; }
|
{ type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; }
|
||||||
|
@ -158,20 +178,21 @@ rec {
|
||||||
else x;
|
else x;
|
||||||
|
|
||||||
|
|
||||||
/* For use in the ‘example’ option attribute. It causes the given
|
/* For use in the `example` option attribute. It causes the given
|
||||||
text to be included verbatim in documentation. This is necessary
|
text to be included verbatim in documentation. This is necessary
|
||||||
for example values that are not simple values, e.g.,
|
for example values that are not simple values, e.g., functions.
|
||||||
functions. */
|
*/
|
||||||
literalExample = text: { _type = "literalExample"; inherit text; };
|
literalExample = text: { _type = "literalExample"; inherit text; };
|
||||||
|
|
||||||
|
# Helper functions.
|
||||||
|
|
||||||
/* Helper functions. */
|
/* Convert an option, described as a list of the option parts in to a
|
||||||
|
safe, human readable version.
|
||||||
|
|
||||||
# Convert an option, described as a list of the option parts in to a
|
Example:
|
||||||
# safe, human readable version. ie:
|
(showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
|
||||||
#
|
(showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
|
||||||
# (showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
|
*/
|
||||||
# (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
|
|
||||||
showOption = parts: let
|
showOption = parts: let
|
||||||
escapeOptionPart = part:
|
escapeOptionPart = part:
|
||||||
let
|
let
|
||||||
|
|
204
lib/strings.nix
204
lib/strings.nix
|
@ -12,6 +12,8 @@ rec {
|
||||||
|
|
||||||
/* Concatenate a list of strings.
|
/* Concatenate a list of strings.
|
||||||
|
|
||||||
|
Type: concatStrings :: [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatStrings ["foo" "bar"]
|
concatStrings ["foo" "bar"]
|
||||||
=> "foobar"
|
=> "foobar"
|
||||||
|
@ -20,15 +22,19 @@ rec {
|
||||||
|
|
||||||
/* Map a function over a list and concatenate the resulting strings.
|
/* Map a function over a list and concatenate the resulting strings.
|
||||||
|
|
||||||
|
Type: concatMapStrings :: (a -> string) -> [a] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatMapStrings (x: "a" + x) ["foo" "bar"]
|
concatMapStrings (x: "a" + x) ["foo" "bar"]
|
||||||
=> "afooabar"
|
=> "afooabar"
|
||||||
*/
|
*/
|
||||||
concatMapStrings = f: list: concatStrings (map f list);
|
concatMapStrings = f: list: concatStrings (map f list);
|
||||||
|
|
||||||
/* Like `concatMapStrings' except that the f functions also gets the
|
/* Like `concatMapStrings` except that the f functions also gets the
|
||||||
position as a parameter.
|
position as a parameter.
|
||||||
|
|
||||||
|
Type: concatImapStrings :: (int -> a -> string) -> [a] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"]
|
concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"]
|
||||||
=> "1-foo2-bar"
|
=> "1-foo2-bar"
|
||||||
|
@ -37,17 +43,25 @@ rec {
|
||||||
|
|
||||||
/* Place an element between each element of a list
|
/* Place an element between each element of a list
|
||||||
|
|
||||||
|
Type: intersperse :: a -> [a] -> [a]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
intersperse "/" ["usr" "local" "bin"]
|
intersperse "/" ["usr" "local" "bin"]
|
||||||
=> ["usr" "/" "local" "/" "bin"].
|
=> ["usr" "/" "local" "/" "bin"].
|
||||||
*/
|
*/
|
||||||
intersperse = separator: list:
|
intersperse =
|
||||||
|
# Separator to add between elements
|
||||||
|
separator:
|
||||||
|
# Input list
|
||||||
|
list:
|
||||||
if list == [] || length list == 1
|
if list == [] || length list == 1
|
||||||
then list
|
then list
|
||||||
else tail (lib.concatMap (x: [separator x]) list);
|
else tail (lib.concatMap (x: [separator x]) list);
|
||||||
|
|
||||||
/* Concatenate a list of strings with a separator between each element
|
/* Concatenate a list of strings with a separator between each element
|
||||||
|
|
||||||
|
Type: concatStringsSep :: string -> [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatStringsSep "/" ["usr" "local" "bin"]
|
concatStringsSep "/" ["usr" "local" "bin"]
|
||||||
=> "usr/local/bin"
|
=> "usr/local/bin"
|
||||||
|
@ -55,43 +69,77 @@ rec {
|
||||||
concatStringsSep = builtins.concatStringsSep or (separator: list:
|
concatStringsSep = builtins.concatStringsSep or (separator: list:
|
||||||
concatStrings (intersperse separator list));
|
concatStrings (intersperse separator list));
|
||||||
|
|
||||||
/* First maps over the list and then concatenates it.
|
/* Maps a function over a list of strings and then concatenates the
|
||||||
|
result with the specified separator interspersed between
|
||||||
|
elements.
|
||||||
|
|
||||||
|
Type: concatMapStringsSep :: string -> (string -> string) -> [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
concatMapStringsSep "-" (x: toUpper x) ["foo" "bar" "baz"]
|
concatMapStringsSep "-" (x: toUpper x) ["foo" "bar" "baz"]
|
||||||
=> "FOO-BAR-BAZ"
|
=> "FOO-BAR-BAZ"
|
||||||
*/
|
*/
|
||||||
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list);
|
concatMapStringsSep =
|
||||||
|
# Separator to add between elements
|
||||||
|
sep:
|
||||||
|
# Function to map over the list
|
||||||
|
f:
|
||||||
|
# List of input strings
|
||||||
|
list: concatStringsSep sep (map f list);
|
||||||
|
|
||||||
/* First imaps over the list and then concatenates it.
|
/* Same as `concatMapStringsSep`, but the mapping function
|
||||||
|
additionally receives the position of its argument.
|
||||||
|
|
||||||
|
Type: concatMapStringsSep :: string -> (int -> string -> string) -> [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ]
|
concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ]
|
||||||
=> "6-3-2"
|
=> "6-3-2"
|
||||||
*/
|
*/
|
||||||
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap1 f list);
|
concatImapStringsSep =
|
||||||
|
# Separator to add between elements
|
||||||
|
sep:
|
||||||
|
# Function that receives elements and their positions
|
||||||
|
f:
|
||||||
|
# List of input strings
|
||||||
|
list: concatStringsSep sep (lib.imap1 f list);
|
||||||
|
|
||||||
/* Construct a Unix-style search path consisting of each `subDir"
|
/* Construct a Unix-style, colon-separated search path consisting of
|
||||||
directory of the given list of packages.
|
the given `subDir` appended to each of the given paths.
|
||||||
|
|
||||||
|
Type: makeSearchPath :: string -> [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
makeSearchPath "bin" ["/root" "/usr" "/usr/local"]
|
makeSearchPath "bin" ["/root" "/usr" "/usr/local"]
|
||||||
=> "/root/bin:/usr/bin:/usr/local/bin"
|
=> "/root/bin:/usr/bin:/usr/local/bin"
|
||||||
makeSearchPath "bin" ["/"]
|
makeSearchPath "bin" [""]
|
||||||
=> "//bin"
|
=> "/bin"
|
||||||
*/
|
*/
|
||||||
makeSearchPath = subDir: packages:
|
makeSearchPath =
|
||||||
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) packages));
|
# Directory name to append
|
||||||
|
subDir:
|
||||||
|
# List of base paths
|
||||||
|
paths:
|
||||||
|
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) paths));
|
||||||
|
|
||||||
/* Construct a Unix-style search path, using given package output.
|
/* Construct a Unix-style search path by appending the given
|
||||||
If no output is found, fallback to `.out` and then to the default.
|
`subDir` to the specified `output` of each of the packages. If no
|
||||||
|
output by the given name is found, fallback to `.out` and then to
|
||||||
|
the default.
|
||||||
|
|
||||||
|
Type: string -> string -> [package] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
makeSearchPathOutput "dev" "bin" [ pkgs.openssl pkgs.zlib ]
|
makeSearchPathOutput "dev" "bin" [ pkgs.openssl pkgs.zlib ]
|
||||||
=> "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev/bin:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/bin"
|
=> "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev/bin:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/bin"
|
||||||
*/
|
*/
|
||||||
makeSearchPathOutput = output: subDir: pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs);
|
makeSearchPathOutput =
|
||||||
|
# Package output to use
|
||||||
|
output:
|
||||||
|
# Directory name to append
|
||||||
|
subDir:
|
||||||
|
# List of packages
|
||||||
|
pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs);
|
||||||
|
|
||||||
/* Construct a library search path (such as RPATH) containing the
|
/* Construct a library search path (such as RPATH) containing the
|
||||||
libraries for a set of packages
|
libraries for a set of packages
|
||||||
|
@ -117,13 +165,12 @@ rec {
|
||||||
|
|
||||||
/* Construct a perl search path (such as $PERL5LIB)
|
/* Construct a perl search path (such as $PERL5LIB)
|
||||||
|
|
||||||
FIXME(zimbatm): this should be moved in perl-specific code
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
pkgs = import <nixpkgs> { }
|
pkgs = import <nixpkgs> { }
|
||||||
makePerlPath [ pkgs.perlPackages.libnet ]
|
makePerlPath [ pkgs.perlPackages.libnet ]
|
||||||
=> "/nix/store/n0m1fk9c960d8wlrs62sncnadygqqc6y-perl-Net-SMTP-1.25/lib/perl5/site_perl"
|
=> "/nix/store/n0m1fk9c960d8wlrs62sncnadygqqc6y-perl-Net-SMTP-1.25/lib/perl5/site_perl"
|
||||||
*/
|
*/
|
||||||
|
# FIXME(zimbatm): this should be moved in perl-specific code
|
||||||
makePerlPath = makeSearchPathOutput "lib" "lib/perl5/site_perl";
|
makePerlPath = makeSearchPathOutput "lib" "lib/perl5/site_perl";
|
||||||
|
|
||||||
/* Construct a perl search path recursively including all dependencies (such as $PERL5LIB)
|
/* Construct a perl search path recursively including all dependencies (such as $PERL5LIB)
|
||||||
|
@ -138,34 +185,51 @@ rec {
|
||||||
/* Depending on the boolean `cond', return either the given string
|
/* Depending on the boolean `cond', return either the given string
|
||||||
or the empty string. Useful to concatenate against a bigger string.
|
or the empty string. Useful to concatenate against a bigger string.
|
||||||
|
|
||||||
|
Type: optionalString :: bool -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
optionalString true "some-string"
|
optionalString true "some-string"
|
||||||
=> "some-string"
|
=> "some-string"
|
||||||
optionalString false "some-string"
|
optionalString false "some-string"
|
||||||
=> ""
|
=> ""
|
||||||
*/
|
*/
|
||||||
optionalString = cond: string: if cond then string else "";
|
optionalString =
|
||||||
|
# Condition
|
||||||
|
cond:
|
||||||
|
# String to return if condition is true
|
||||||
|
string: if cond then string else "";
|
||||||
|
|
||||||
/* Determine whether a string has given prefix.
|
/* Determine whether a string has given prefix.
|
||||||
|
|
||||||
|
Type: hasPrefix :: string -> string -> bool
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
hasPrefix "foo" "foobar"
|
hasPrefix "foo" "foobar"
|
||||||
=> true
|
=> true
|
||||||
hasPrefix "foo" "barfoo"
|
hasPrefix "foo" "barfoo"
|
||||||
=> false
|
=> false
|
||||||
*/
|
*/
|
||||||
hasPrefix = pref: str:
|
hasPrefix =
|
||||||
substring 0 (stringLength pref) str == pref;
|
# Prefix to check for
|
||||||
|
pref:
|
||||||
|
# Input string
|
||||||
|
str: substring 0 (stringLength pref) str == pref;
|
||||||
|
|
||||||
/* Determine whether a string has given suffix.
|
/* Determine whether a string has given suffix.
|
||||||
|
|
||||||
|
Type: hasSuffix :: string -> string -> bool
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
hasSuffix "foo" "foobar"
|
hasSuffix "foo" "foobar"
|
||||||
=> false
|
=> false
|
||||||
hasSuffix "foo" "barfoo"
|
hasSuffix "foo" "barfoo"
|
||||||
=> true
|
=> true
|
||||||
*/
|
*/
|
||||||
hasSuffix = suffix: content:
|
hasSuffix =
|
||||||
|
# Suffix to check for
|
||||||
|
suffix:
|
||||||
|
# Input string
|
||||||
|
content:
|
||||||
let
|
let
|
||||||
lenContent = stringLength content;
|
lenContent = stringLength content;
|
||||||
lenSuffix = stringLength suffix;
|
lenSuffix = stringLength suffix;
|
||||||
|
@ -180,6 +244,8 @@ rec {
|
||||||
Also note that Nix treats strings as a list of bytes and thus doesn't
|
Also note that Nix treats strings as a list of bytes and thus doesn't
|
||||||
handle unicode.
|
handle unicode.
|
||||||
|
|
||||||
|
Type: stringtoCharacters :: string -> [string]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
stringToCharacters ""
|
stringToCharacters ""
|
||||||
=> [ ]
|
=> [ ]
|
||||||
|
@ -194,18 +260,25 @@ rec {
|
||||||
/* Manipulate a string character by character and replace them by
|
/* Manipulate a string character by character and replace them by
|
||||||
strings before concatenating the results.
|
strings before concatenating the results.
|
||||||
|
|
||||||
|
Type: stringAsChars :: (string -> string) -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
stringAsChars (x: if x == "a" then "i" else x) "nax"
|
stringAsChars (x: if x == "a" then "i" else x) "nax"
|
||||||
=> "nix"
|
=> "nix"
|
||||||
*/
|
*/
|
||||||
stringAsChars = f: s:
|
stringAsChars =
|
||||||
concatStrings (
|
# Function to map over each individual character
|
||||||
|
f:
|
||||||
|
# Input string
|
||||||
|
s: concatStrings (
|
||||||
map f (stringToCharacters s)
|
map f (stringToCharacters s)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Escape occurrence of the elements of ‘list’ in ‘string’ by
|
/* Escape occurrence of the elements of `list` in `string` by
|
||||||
prefixing it with a backslash.
|
prefixing it with a backslash.
|
||||||
|
|
||||||
|
Type: escape :: [string] -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
escape ["(" ")"] "(foo)"
|
escape ["(" ")"] "(foo)"
|
||||||
=> "\\(foo\\)"
|
=> "\\(foo\\)"
|
||||||
|
@ -214,6 +287,8 @@ rec {
|
||||||
|
|
||||||
/* Quote string to be used safely within the Bourne shell.
|
/* Quote string to be used safely within the Bourne shell.
|
||||||
|
|
||||||
|
Type: escapeShellArg :: string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
escapeShellArg "esc'ape\nme"
|
escapeShellArg "esc'ape\nme"
|
||||||
=> "'esc'\\''ape\nme'"
|
=> "'esc'\\''ape\nme'"
|
||||||
|
@ -222,6 +297,8 @@ rec {
|
||||||
|
|
||||||
/* Quote all arguments to be safely passed to the Bourne shell.
|
/* Quote all arguments to be safely passed to the Bourne shell.
|
||||||
|
|
||||||
|
Type: escapeShellArgs :: [string] -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
escapeShellArgs ["one" "two three" "four'five"]
|
escapeShellArgs ["one" "two three" "four'five"]
|
||||||
=> "'one' 'two three' 'four'\\''five'"
|
=> "'one' 'two three' 'four'\\''five'"
|
||||||
|
@ -230,13 +307,15 @@ rec {
|
||||||
|
|
||||||
/* Turn a string into a Nix expression representing that string
|
/* Turn a string into a Nix expression representing that string
|
||||||
|
|
||||||
|
Type: string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
escapeNixString "hello\${}\n"
|
escapeNixString "hello\${}\n"
|
||||||
=> "\"hello\\\${}\\n\""
|
=> "\"hello\\\${}\\n\""
|
||||||
*/
|
*/
|
||||||
escapeNixString = s: escape ["$"] (builtins.toJSON s);
|
escapeNixString = s: escape ["$"] (builtins.toJSON s);
|
||||||
|
|
||||||
/* Obsolete - use replaceStrings instead. */
|
# Obsolete - use replaceStrings instead.
|
||||||
replaceChars = builtins.replaceStrings or (
|
replaceChars = builtins.replaceStrings or (
|
||||||
del: new: s:
|
del: new: s:
|
||||||
let
|
let
|
||||||
|
@ -256,6 +335,8 @@ rec {
|
||||||
|
|
||||||
/* Converts an ASCII string to lower-case.
|
/* Converts an ASCII string to lower-case.
|
||||||
|
|
||||||
|
Type: toLower :: string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
toLower "HOME"
|
toLower "HOME"
|
||||||
=> "home"
|
=> "home"
|
||||||
|
@ -264,6 +345,8 @@ rec {
|
||||||
|
|
||||||
/* Converts an ASCII string to upper-case.
|
/* Converts an ASCII string to upper-case.
|
||||||
|
|
||||||
|
Type: toUpper :: string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
toUpper "home"
|
toUpper "home"
|
||||||
=> "HOME"
|
=> "HOME"
|
||||||
|
@ -273,7 +356,7 @@ rec {
|
||||||
/* Appends string context from another string. This is an implementation
|
/* Appends string context from another string. This is an implementation
|
||||||
detail of Nix.
|
detail of Nix.
|
||||||
|
|
||||||
Strings in Nix carry an invisible `context' which is a list of strings
|
Strings in Nix carry an invisible `context` which is a list of strings
|
||||||
representing store paths. If the string is later used in a derivation
|
representing store paths. If the string is later used in a derivation
|
||||||
attribute, the derivation will properly populate the inputDrvs and
|
attribute, the derivation will properly populate the inputDrvs and
|
||||||
inputSrcs.
|
inputSrcs.
|
||||||
|
@ -319,8 +402,9 @@ rec {
|
||||||
in
|
in
|
||||||
recurse 0 0;
|
recurse 0 0;
|
||||||
|
|
||||||
/* Return the suffix of the second argument if the first argument matches
|
/* Return a string without the specified prefix, if the prefix matches.
|
||||||
its prefix.
|
|
||||||
|
Type: string -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
removePrefix "foo." "foo.bar.baz"
|
removePrefix "foo." "foo.bar.baz"
|
||||||
|
@ -328,18 +412,23 @@ rec {
|
||||||
removePrefix "xxx" "foo.bar.baz"
|
removePrefix "xxx" "foo.bar.baz"
|
||||||
=> "foo.bar.baz"
|
=> "foo.bar.baz"
|
||||||
*/
|
*/
|
||||||
removePrefix = pre: s:
|
removePrefix =
|
||||||
|
# Prefix to remove if it matches
|
||||||
|
prefix:
|
||||||
|
# Input string
|
||||||
|
str:
|
||||||
let
|
let
|
||||||
preLen = stringLength pre;
|
preLen = stringLength prefix;
|
||||||
sLen = stringLength s;
|
sLen = stringLength str;
|
||||||
in
|
in
|
||||||
if hasPrefix pre s then
|
if hasPrefix prefix str then
|
||||||
substring preLen (sLen - preLen) s
|
substring preLen (sLen - preLen) str
|
||||||
else
|
else
|
||||||
s;
|
str;
|
||||||
|
|
||||||
/* Return the prefix of the second argument if the first argument matches
|
/* Return a string without the specified suffix, if the suffix matches.
|
||||||
its suffix.
|
|
||||||
|
Type: string -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
removeSuffix "front" "homefront"
|
removeSuffix "front" "homefront"
|
||||||
|
@ -347,17 +436,21 @@ rec {
|
||||||
removeSuffix "xxx" "homefront"
|
removeSuffix "xxx" "homefront"
|
||||||
=> "homefront"
|
=> "homefront"
|
||||||
*/
|
*/
|
||||||
removeSuffix = suf: s:
|
removeSuffix =
|
||||||
|
# Suffix to remove if it matches
|
||||||
|
suffix:
|
||||||
|
# Input string
|
||||||
|
str:
|
||||||
let
|
let
|
||||||
sufLen = stringLength suf;
|
sufLen = stringLength suffix;
|
||||||
sLen = stringLength s;
|
sLen = stringLength str;
|
||||||
in
|
in
|
||||||
if sufLen <= sLen && suf == substring (sLen - sufLen) sufLen s then
|
if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str then
|
||||||
substring 0 (sLen - sufLen) s
|
substring 0 (sLen - sufLen) str
|
||||||
else
|
else
|
||||||
s;
|
str;
|
||||||
|
|
||||||
/* Return true iff string v1 denotes a version older than v2.
|
/* Return true if string v1 denotes a version older than v2.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
versionOlder "1.1" "1.2"
|
versionOlder "1.1" "1.2"
|
||||||
|
@ -367,7 +460,7 @@ rec {
|
||||||
*/
|
*/
|
||||||
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
|
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
|
||||||
|
|
||||||
/* Return true iff string v1 denotes a version equal to or newer than v2.
|
/* Return true if string v1 denotes a version equal to or newer than v2.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
versionAtLeast "1.1" "1.0"
|
versionAtLeast "1.1" "1.0"
|
||||||
|
@ -459,6 +552,11 @@ rec {
|
||||||
/* Create a fixed width string with additional prefix to match
|
/* Create a fixed width string with additional prefix to match
|
||||||
required width.
|
required width.
|
||||||
|
|
||||||
|
This function will fail if the input string is longer than the
|
||||||
|
requested length.
|
||||||
|
|
||||||
|
Type: fixedWidthString :: int -> string -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
fixedWidthString 5 "0" (toString 15)
|
fixedWidthString 5 "0" (toString 15)
|
||||||
=> "00015"
|
=> "00015"
|
||||||
|
@ -509,8 +607,9 @@ rec {
|
||||||
else
|
else
|
||||||
false;
|
false;
|
||||||
|
|
||||||
/* Convert string to int
|
/* Parse a string string as an int.
|
||||||
Obviously, it is a bit hacky to use fromJSON that way.
|
|
||||||
|
Type: string -> int
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
toInt "1337"
|
toInt "1337"
|
||||||
|
@ -520,17 +619,18 @@ rec {
|
||||||
toInt "3.14"
|
toInt "3.14"
|
||||||
=> error: floating point JSON numbers are not supported
|
=> error: floating point JSON numbers are not supported
|
||||||
*/
|
*/
|
||||||
|
# Obviously, it is a bit hacky to use fromJSON this way.
|
||||||
toInt = str:
|
toInt = str:
|
||||||
let may_be_int = builtins.fromJSON str; in
|
let may_be_int = builtins.fromJSON str; in
|
||||||
if builtins.isInt may_be_int
|
if builtins.isInt may_be_int
|
||||||
then may_be_int
|
then may_be_int
|
||||||
else throw "Could not convert ${str} to int.";
|
else throw "Could not convert ${str} to int.";
|
||||||
|
|
||||||
/* Read a list of paths from `file', relative to the `rootPath'. Lines
|
/* Read a list of paths from `file`, relative to the `rootPath`.
|
||||||
beginning with `#' are treated as comments and ignored. Whitespace
|
Lines beginning with `#` are treated as comments and ignored.
|
||||||
is significant.
|
Whitespace is significant.
|
||||||
|
|
||||||
NOTE: this function is not performant and should be avoided
|
NOTE: This function is not performant and should be avoided.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
readPathsFromFile /prefix
|
readPathsFromFile /prefix
|
||||||
|
@ -552,6 +652,8 @@ rec {
|
||||||
|
|
||||||
/* Read the contents of a file removing the trailing \n
|
/* Read the contents of a file removing the trailing \n
|
||||||
|
|
||||||
|
Type: fileContents :: path -> string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
$ echo "1.0" > ./version
|
$ echo "1.0" > ./version
|
||||||
|
|
||||||
|
|
117
lib/trivial.nix
117
lib/trivial.nix
|
@ -9,23 +9,37 @@ rec {
|
||||||
|
|
||||||
Type: id :: a -> a
|
Type: id :: a -> a
|
||||||
*/
|
*/
|
||||||
id = x: x;
|
id =
|
||||||
|
# The value to return
|
||||||
|
x: x;
|
||||||
|
|
||||||
/* The constant function
|
/* The constant function
|
||||||
Ignores the second argument.
|
|
||||||
Or: Construct a function that always returns a static value.
|
Ignores the second argument. If called with only one argument,
|
||||||
|
constructs a function that always returns a static value.
|
||||||
|
|
||||||
Type: const :: a -> b -> a
|
Type: const :: a -> b -> a
|
||||||
Example:
|
Example:
|
||||||
let f = const 5; in f 10
|
let f = const 5; in f 10
|
||||||
=> 5
|
=> 5
|
||||||
*/
|
*/
|
||||||
const = x: y: x;
|
const =
|
||||||
|
# Value to return
|
||||||
|
x:
|
||||||
|
# Value to ignore
|
||||||
|
y: x;
|
||||||
|
|
||||||
|
|
||||||
## Named versions corresponding to some builtin operators.
|
## Named versions corresponding to some builtin operators.
|
||||||
|
|
||||||
/* Concatenate two lists */
|
/* Concatenate two lists
|
||||||
|
|
||||||
|
Type: concat :: [a] -> [a] -> [a]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
concat [ 1 2 ] [ 3 4 ]
|
||||||
|
=> [ 1 2 3 4 ]
|
||||||
|
*/
|
||||||
concat = x: y: x ++ y;
|
concat = x: y: x ++ y;
|
||||||
|
|
||||||
/* boolean “or” */
|
/* boolean “or” */
|
||||||
|
@ -53,27 +67,40 @@ rec {
|
||||||
bitNot = builtins.sub (-1);
|
bitNot = builtins.sub (-1);
|
||||||
|
|
||||||
/* Convert a boolean to a string.
|
/* Convert a boolean to a string.
|
||||||
Note that toString on a bool returns "1" and "".
|
|
||||||
|
This function uses the strings "true" and "false" to represent
|
||||||
|
boolean values. Calling `toString` on a bool instead returns "1"
|
||||||
|
and "" (sic!).
|
||||||
|
|
||||||
|
Type: boolToString :: bool -> string
|
||||||
*/
|
*/
|
||||||
boolToString = b: if b then "true" else "false";
|
boolToString = b: if b then "true" else "false";
|
||||||
|
|
||||||
/* Merge two attribute sets shallowly, right side trumps left
|
/* Merge two attribute sets shallowly, right side trumps left
|
||||||
|
|
||||||
|
mergeAttrs :: attrs -> attrs -> attrs
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
|
mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
|
||||||
=> { a = 1; b = 3; c = 4; }
|
=> { a = 1; b = 3; c = 4; }
|
||||||
*/
|
*/
|
||||||
mergeAttrs = x: y: x // y;
|
mergeAttrs =
|
||||||
|
# Left attribute set
|
||||||
|
x:
|
||||||
|
# Right attribute set (higher precedence for equal keys)
|
||||||
|
y: x // y;
|
||||||
|
|
||||||
/* Flip the order of the arguments of a binary function.
|
/* Flip the order of the arguments of a binary function.
|
||||||
|
|
||||||
|
Type: flip :: (a -> b -> c) -> (b -> a -> c)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
flip concat [1] [2]
|
flip concat [1] [2]
|
||||||
=> [ 2 1 ]
|
=> [ 2 1 ]
|
||||||
*/
|
*/
|
||||||
flip = f: a: b: f b a;
|
flip = f: a: b: f b a;
|
||||||
|
|
||||||
/* Apply function if argument is non-null.
|
/* Apply function if the supplied argument is non-null.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
mapNullable (x: x+1) null
|
mapNullable (x: x+1) null
|
||||||
|
@ -81,7 +108,11 @@ rec {
|
||||||
mapNullable (x: x+1) 22
|
mapNullable (x: x+1) 22
|
||||||
=> 23
|
=> 23
|
||||||
*/
|
*/
|
||||||
mapNullable = f: a: if isNull a then a else f a;
|
mapNullable =
|
||||||
|
# Function to call
|
||||||
|
f:
|
||||||
|
# Argument to check for null before passing it to `f`
|
||||||
|
a: if isNull a then a else f a;
|
||||||
|
|
||||||
# Pull in some builtins not included elsewhere.
|
# Pull in some builtins not included elsewhere.
|
||||||
inherit (builtins)
|
inherit (builtins)
|
||||||
|
@ -92,21 +123,27 @@ rec {
|
||||||
|
|
||||||
## nixpks version strings
|
## nixpks version strings
|
||||||
|
|
||||||
# The current full nixpkgs version number.
|
/* Returns the current full nixpkgs version number. */
|
||||||
version = release + versionSuffix;
|
version = release + versionSuffix;
|
||||||
|
|
||||||
# The current nixpkgs version number as string.
|
/* Returns the current nixpkgs release number as string. */
|
||||||
release = lib.strings.fileContents ../.version;
|
release = lib.strings.fileContents ../.version;
|
||||||
|
|
||||||
# The current nixpkgs version suffix as string.
|
/* Returns the current nixpkgs version suffix as string. */
|
||||||
versionSuffix =
|
versionSuffix =
|
||||||
let suffixFile = ../.version-suffix;
|
let suffixFile = ../.version-suffix;
|
||||||
in if pathExists suffixFile
|
in if pathExists suffixFile
|
||||||
then lib.strings.fileContents suffixFile
|
then lib.strings.fileContents suffixFile
|
||||||
else "pre-git";
|
else "pre-git";
|
||||||
|
|
||||||
# Attempt to get the revision nixpkgs is from
|
/* Attempts to return the the current revision of nixpkgs and
|
||||||
revisionWithDefault = default:
|
returns the supplied default value otherwise.
|
||||||
|
|
||||||
|
Type: revisionWithDefault :: string -> string
|
||||||
|
*/
|
||||||
|
revisionWithDefault =
|
||||||
|
# Default value to return if revision can not be determined
|
||||||
|
default:
|
||||||
let
|
let
|
||||||
revisionFile = "${toString ./..}/.git-revision";
|
revisionFile = "${toString ./..}/.git-revision";
|
||||||
gitRepo = "${toString ./..}/.git";
|
gitRepo = "${toString ./..}/.git";
|
||||||
|
@ -117,14 +154,20 @@ rec {
|
||||||
|
|
||||||
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
|
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
|
||||||
|
|
||||||
# Whether we're being called by nix-shell.
|
/* Determine whether the function is being called from inside a Nix
|
||||||
|
shell.
|
||||||
|
|
||||||
|
Type: inNixShell :: bool
|
||||||
|
*/
|
||||||
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
|
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
|
||||||
|
|
||||||
|
|
||||||
## Integer operations
|
## Integer operations
|
||||||
|
|
||||||
# Return minimum/maximum of two numbers.
|
/* Return minimum of two numbers. */
|
||||||
min = x: y: if x < y then x else y;
|
min = x: y: if x < y then x else y;
|
||||||
|
|
||||||
|
/* Return maximum of two numbers. */
|
||||||
max = x: y: if x > y then x else y;
|
max = x: y: if x > y then x else y;
|
||||||
|
|
||||||
/* Integer modulus
|
/* Integer modulus
|
||||||
|
@ -158,8 +201,9 @@ rec {
|
||||||
second subtype, compare elements of a single subtype with `yes`
|
second subtype, compare elements of a single subtype with `yes`
|
||||||
and `no` respectively.
|
and `no` respectively.
|
||||||
|
|
||||||
Example:
|
Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
|
||||||
|
|
||||||
|
Example:
|
||||||
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
|
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
|
||||||
|
|
||||||
cmp "a" "z" => -1
|
cmp "a" "z" => -1
|
||||||
|
@ -170,31 +214,44 @@ rec {
|
||||||
# while
|
# while
|
||||||
compare "fooa" "a" => 1
|
compare "fooa" "a" => 1
|
||||||
*/
|
*/
|
||||||
splitByAndCompare = p: yes: no: a: b:
|
splitByAndCompare =
|
||||||
|
# Predicate
|
||||||
|
p:
|
||||||
|
# Comparison function if predicate holds for both values
|
||||||
|
yes:
|
||||||
|
# Comparison function if predicate holds for neither value
|
||||||
|
no:
|
||||||
|
# First value to compare
|
||||||
|
a:
|
||||||
|
# Second value to compare
|
||||||
|
b:
|
||||||
if p a
|
if p a
|
||||||
then if p b then yes a b else -1
|
then if p b then yes a b else -1
|
||||||
else if p b then 1 else no a b;
|
else if p b then 1 else no a b;
|
||||||
|
|
||||||
|
|
||||||
/* Reads a JSON file. */
|
/* Reads a JSON file.
|
||||||
|
|
||||||
|
Type :: path -> any
|
||||||
|
*/
|
||||||
importJSON = path:
|
importJSON = path:
|
||||||
builtins.fromJSON (builtins.readFile path);
|
builtins.fromJSON (builtins.readFile path);
|
||||||
|
|
||||||
|
|
||||||
## Warnings
|
## Warnings
|
||||||
|
|
||||||
/* See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
|
# See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
|
||||||
to expand to Nix builtins that carry metadata so that Nix can filter out
|
# to expand to Nix builtins that carry metadata so that Nix can filter out
|
||||||
the INFO messages without parsing the message string.
|
# the INFO messages without parsing the message string.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# {
|
||||||
|
# foo = lib.warn "foo is deprecated" oldFoo;
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# TODO: figure out a clever way to integrate location information from
|
||||||
|
# something like __unsafeGetAttrPos.
|
||||||
|
|
||||||
Usage:
|
|
||||||
{
|
|
||||||
foo = lib.warn "foo is deprecated" oldFoo;
|
|
||||||
}
|
|
||||||
|
|
||||||
TODO: figure out a clever way to integrate location information from
|
|
||||||
something like __unsafeGetAttrPos.
|
|
||||||
*/
|
|
||||||
warn = msg: builtins.trace "WARNING: ${msg}";
|
warn = msg: builtins.trace "WARNING: ${msg}";
|
||||||
info = msg: builtins.trace "INFO: ${msg}";
|
info = msg: builtins.trace "INFO: ${msg}";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue