forked from DGNum/infrastructure
417 lines
8.1 KiB
Nix
417 lines
8.1 KiB
Nix
|
###
|
|||
|
# Collection of nixpkgs library functions, those are necessary for defining our own lib
|
|||
|
#
|
|||
|
# They have been simplified and builtins are used in some places, instead of lib shims.
|
|||
|
|
|||
|
rec {
|
|||
|
/**
|
|||
|
Does the same as the update operator '//' except that attributes are
|
|||
|
merged until the given predicate is verified. The predicate should
|
|||
|
accept 3 arguments which are the path to reach the attribute, a part of
|
|||
|
the first attribute set and a part of the second attribute set. When
|
|||
|
the predicate is satisfied, the value of the first attribute set is
|
|||
|
replaced by the value of the second attribute set.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`pred`
|
|||
|
|
|||
|
: Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
|
|||
|
|
|||
|
`lhs`
|
|||
|
|
|||
|
: Left attribute set of the merge.
|
|||
|
|
|||
|
`rhs`
|
|||
|
|
|||
|
: Right attribute set of the merge.
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.attrsets.recursiveUpdateUntil` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
recursiveUpdateUntil (path: l: r: path == ["foo"]) {
|
|||
|
# first attribute set
|
|||
|
foo.bar = 1;
|
|||
|
foo.baz = 2;
|
|||
|
bar = 3;
|
|||
|
} {
|
|||
|
#second attribute set
|
|||
|
foo.bar = 1;
|
|||
|
foo.quz = 2;
|
|||
|
baz = 4;
|
|||
|
}
|
|||
|
|
|||
|
=> {
|
|||
|
foo.bar = 1; # 'foo.*' from the second set
|
|||
|
foo.quz = 2; #
|
|||
|
bar = 3; # 'bar' from the first set
|
|||
|
baz = 4; # 'baz' from the second set
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
recursiveUpdateUntil =
|
|||
|
pred: lhs: rhs:
|
|||
|
let
|
|||
|
f =
|
|||
|
attrPath:
|
|||
|
builtins.zipAttrsWith (
|
|||
|
n: values:
|
|||
|
let
|
|||
|
here = attrPath ++ [ n ];
|
|||
|
in
|
|||
|
if builtins.length values == 1 || pred here (builtins.elemAt values 1) (builtins.head values) then
|
|||
|
builtins.head values
|
|||
|
else
|
|||
|
f here values
|
|||
|
);
|
|||
|
in
|
|||
|
f [ ] [
|
|||
|
rhs
|
|||
|
lhs
|
|||
|
];
|
|||
|
|
|||
|
/**
|
|||
|
A recursive variant of the update operator ‘//’. The recursion
|
|||
|
stops when one of the attribute values is not an attribute set,
|
|||
|
in which case the right hand side value takes precedence over the
|
|||
|
left hand side value.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`lhs`
|
|||
|
|
|||
|
: Left attribute set of the merge.
|
|||
|
|
|||
|
`rhs`
|
|||
|
|
|||
|
: Right attribute set of the merge.
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.attrsets.recursiveUpdate` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
recursiveUpdate {
|
|||
|
boot.loader.grub.enable = true;
|
|||
|
boot.loader.grub.device = "/dev/hda";
|
|||
|
} {
|
|||
|
boot.loader.grub.device = "";
|
|||
|
}
|
|||
|
|
|||
|
returns: {
|
|||
|
boot.loader.grub.enable = true;
|
|||
|
boot.loader.grub.device = "";
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
recursiveUpdate =
|
|||
|
lhs: rhs:
|
|||
|
recursiveUpdateUntil (
|
|||
|
_: lhs: rhs:
|
|||
|
!(builtins.isAttrs lhs && builtins.isAttrs rhs)
|
|||
|
) lhs rhs;
|
|||
|
|
|||
|
/**
|
|||
|
Determine whether a string has given prefix.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`pref`
|
|||
|
: Prefix to check for
|
|||
|
|
|||
|
`str`
|
|||
|
: Input string
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
hasPrefix :: string -> string -> bool
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.hasPrefix` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
hasPrefix "foo" "foobar"
|
|||
|
=> true
|
|||
|
hasPrefix "foo" "barfoo"
|
|||
|
=> false
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
hasPrefix = pref: str: (builtins.substring 0 (builtins.stringLength pref) str == pref);
|
|||
|
|
|||
|
/**
|
|||
|
Escape occurrence of the elements of `list` in `string` by
|
|||
|
prefixing it with a backslash.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`list`
|
|||
|
: 1\. Function argument
|
|||
|
|
|||
|
`string`
|
|||
|
: 2\. Function argument
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
escape :: [string] -> string -> string
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.escape` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
escape ["(" ")"] "(foo)"
|
|||
|
=> "\\(foo\\)"
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
escape = list: builtins.replaceStrings list (builtins.map (c: "\\${c}") list);
|
|||
|
|
|||
|
/**
|
|||
|
Convert a string `s` to a list of characters (i.e. singleton strings).
|
|||
|
This allows you to, e.g., map a function over each character. However,
|
|||
|
note that this will likely be horribly inefficient; Nix is not a
|
|||
|
general purpose programming language. Complex string manipulations
|
|||
|
should, if appropriate, be done in a derivation.
|
|||
|
Also note that Nix treats strings as a list of bytes and thus doesn't
|
|||
|
handle unicode.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`s`
|
|||
|
: 1\. Function argument
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
stringToCharacters :: string -> [string]
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.stringToCharacters` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
stringToCharacters ""
|
|||
|
=> [ ]
|
|||
|
stringToCharacters "abc"
|
|||
|
=> [ "a" "b" "c" ]
|
|||
|
stringToCharacters "🦄"
|
|||
|
=> [ "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" ]
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
stringToCharacters = s: builtins.genList (p: builtins.substring p 1 s) (builtins.stringLength s);
|
|||
|
|
|||
|
/**
|
|||
|
Turn a string `s` into an exact regular expression
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`s`
|
|||
|
: 1\. Function argument
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
escapeRegex :: string -> string
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.escapeRegex` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
escapeRegex "[^a-z]*"
|
|||
|
=> "\\[\\^a-z]\\*"
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
escapeRegex = escape (stringToCharacters "\\[{()^$?*+|.");
|
|||
|
|
|||
|
/**
|
|||
|
Appends string context from string like object `src` to `target`.
|
|||
|
|
|||
|
:::{.warning}
|
|||
|
This is an implementation
|
|||
|
detail of Nix and should be used carefully.
|
|||
|
:::
|
|||
|
|
|||
|
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
|
|||
|
attribute, the derivation will properly populate the inputDrvs and
|
|||
|
inputSrcs.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`src`
|
|||
|
: The string to take the context from. If the argument is not a string,
|
|||
|
it will be implicitly converted to a string.
|
|||
|
|
|||
|
`target`
|
|||
|
: The string to append the context to. If the argument is not a string,
|
|||
|
it will be implicitly converted to a string.
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
addContextFrom :: string -> string -> string
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.addContextFrom` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
pkgs = import <nixpkgs> { };
|
|||
|
addContextFrom pkgs.coreutils "bar"
|
|||
|
=> "bar"
|
|||
|
```
|
|||
|
|
|||
|
The context can be displayed using the `toString` function:
|
|||
|
|
|||
|
```nix
|
|||
|
nix-repl> builtins.getContext (lib.strings.addContextFrom pkgs.coreutils "bar")
|
|||
|
{
|
|||
|
"/nix/store/m1s1d2dk2dqqlw3j90jl3cjy2cykbdxz-coreutils-9.5.drv" = { ... };
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
addContextFrom = src: target: builtins.substring 0 0 src + target;
|
|||
|
|
|||
|
/**
|
|||
|
Cut a string with a separator and produces a list of strings which
|
|||
|
were separated by this separator.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`sep`
|
|||
|
: 1\. Function argument
|
|||
|
|
|||
|
`s`
|
|||
|
: 2\. Function argument
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
splitString :: string -> string -> [string]
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.strings.splitString` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
splitString "." "foo.bar.baz"
|
|||
|
=> [ "foo" "bar" "baz" ]
|
|||
|
splitString "/" "/usr/local/bin"
|
|||
|
=> [ "" "usr" "local" "bin" ]
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
splitString =
|
|||
|
sep: s:
|
|||
|
let
|
|||
|
splits = builtins.filter builtins.isString (
|
|||
|
builtins.split (escapeRegex (builtins.toString sep)) (builtins.toString s)
|
|||
|
);
|
|||
|
in
|
|||
|
builtins.map (addContextFrom s) splits;
|
|||
|
|
|||
|
/**
|
|||
|
Remove duplicate elements from the `list`. O(n^2) complexity.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`list`
|
|||
|
|
|||
|
: Input list
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
unique :: [a] -> [a]
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.lists.unique` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
unique [ 3 2 3 4 ]
|
|||
|
=> [ 3 2 4 ]
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
unique = builtins.foldl' (acc: e: if builtins.elem e acc then acc else acc ++ [ e ]) [ ];
|
|||
|
|
|||
|
/**
|
|||
|
Flip the order of the arguments of a binary function.
|
|||
|
|
|||
|
# Inputs
|
|||
|
|
|||
|
`f`
|
|||
|
|
|||
|
: 1\. Function argument
|
|||
|
|
|||
|
`a`
|
|||
|
|
|||
|
: 2\. Function argument
|
|||
|
|
|||
|
`b`
|
|||
|
|
|||
|
: 3\. Function argument
|
|||
|
|
|||
|
# Type
|
|||
|
|
|||
|
```
|
|||
|
flip :: (a -> b -> c) -> (b -> a -> c)
|
|||
|
```
|
|||
|
|
|||
|
# Examples
|
|||
|
:::{.example}
|
|||
|
## `lib.trivial.flip` usage example
|
|||
|
|
|||
|
```nix
|
|||
|
flip concat [1] [2]
|
|||
|
=> [ 2 1 ]
|
|||
|
```
|
|||
|
|
|||
|
:::
|
|||
|
*/
|
|||
|
flip =
|
|||
|
f: a: b:
|
|||
|
f b a;
|
|||
|
}
|