2017-07-29 00:05:35 +00:00
{ lib }:
2018-07-25 22:10:53 +00:00
2023-10-31 12:35:51 +00:00
let
inherit ( lib . trivial )
isFunction
isInt
functionArgs
pathExists
release
setFunctionArgs
toBaseDigits
version
versionSuffix
warn ;
2024-04-24 09:10:29 +00:00
inherit ( lib )
isString
;
2023-10-31 12:35:51 +00:00
in {
2009-02-09 16:51:03 +00:00
2018-07-25 22:03:51 +00:00
## Simple (higher order) functions
2024-03-20 02:04:14 +00:00
/* *
The identity function
For when you need a function that does “ nothing ” .
2017-03-15 17:29:33 +00:00
2024-03-20 02:04:14 +00:00
# Inputs
` x `
: The value to return
# Type
` ` `
id : : a -> a
` ` `
2017-03-15 17:29:33 +00:00
* /
2024-03-20 02:04:14 +00:00
id = x : x ;
/* *
The constant function
Ignores the second argument . If called with only one argument ,
constructs a function that always returns a static value .
# Inputs
` x `
: Value to return
` y `
: Value to ignore
# Type
` ` `
const : : a -> b -> a
` ` `
2009-02-09 16:51:03 +00:00
2024-03-20 02:04:14 +00:00
# Examples
: : : { . example }
## `lib.trivial.const` usage example
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
` ` ` nix
let f = const 5 ; in f 10
= > 5
` ` `
2017-03-15 17:29:33 +00:00
2024-03-20 02:04:14 +00:00
: : :
2017-03-15 17:29:33 +00:00
* /
2018-10-27 14:40:04 +00:00
const =
x :
y : x ;
2009-02-09 16:51:03 +00:00
2024-03-20 02:04:14 +00:00
/* *
Pipes a value through a list of functions , left to right .
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
# Inputs
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
` value `
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
: Value to start piping .
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
` fns `
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
: List of functions to apply sequentially .
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
# Type
2019-10-18 15:57:33 +00:00
2024-03-20 02:04:14 +00:00
` ` `
pipe : : a -> [ <functions> ] -> < return type of last function >
` ` `
# Examples
: : : { . example }
## `lib.trivial.pipe` usage example
` ` ` nix
pipe 2 [
( x : x + 2 ) # 2 + 2 = 4
( x : x * 2 ) # 4 * 2 = 8
]
= > 8
# ideal to do text transformations
pipe [ " a / b " " a / c " ] [
# create the cp command
( map ( file : '' c p " ${ src } / ${ file } " $o u t \ n '' ) )
# concatenate all commands into one string
lib . concatStrings
# make that string into a nix derivation
( pkgs . runCommand " c o p y - t o - o u t " { } )
]
= > < drv which copies all files to $ out >
The output type of each function has to be the input type
of the next function , and the last function returns the
final value .
` ` `
: : :
2019-10-18 15:57:33 +00:00
* /
2023-12-11 03:21:46 +00:00
pipe = builtins . foldl' ( x : f : f x ) ;
2022-01-30 00:53:24 +00:00
# note please don’ t add a function like `compose = flip pipe`.
# This would confuse users, because the order of the functions
# in the list is not clear. With pipe, it’ s obvious that it
# goes first-to-last. With `compose`, not so much.
2017-03-15 17:29:33 +00:00
## Named versions corresponding to some builtin operators.
2024-03-20 02:04:14 +00:00
/* *
Concatenate two lists
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
# Type
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
` ` `
concat : : [ a ] -> [ a ] -> [ a ]
` ` `
# Examples
: : : { . example }
## `lib.trivial.concat` usage example
` ` ` nix
concat [ 1 2 ] [ 3 4 ]
= > [ 1 2 3 4 ]
` ` `
: : :
2018-10-27 14:40:04 +00:00
* /
2009-02-09 16:51:03 +00:00
concat = x : y : x ++ y ;
2017-03-15 17:29:33 +00:00
2024-03-20 02:04:14 +00:00
/* *
boolean “ or ”
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
* /
2009-02-09 16:51:03 +00:00
or = x : y : x || y ;
2017-03-15 17:29:33 +00:00
2024-03-20 02:04:14 +00:00
/* *
boolean “ and ”
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
* /
2009-02-09 16:51:03 +00:00
and = x : y : x && y ;
2017-03-15 17:29:33 +00:00
2024-04-04 14:05:18 +00:00
/* *
boolean “ exclusive or ”
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
* /
# We explicitly invert the arguments purely as a type assertion.
# This is invariant under XOR, so it does not affect the result.
xor = x : y : ( ! x ) != ( ! y ) ;
2024-03-20 02:04:14 +00:00
/* *
bitwise “ not ”
* /
2018-06-10 19:25:48 +00:00
bitNot = builtins . sub ( -1 ) ;
2024-03-20 02:04:14 +00:00
/* *
Convert a boolean to a string .
This function uses the strings " t r u e " and " f a l s e " to represent
boolean values . Calling ` toString ` on a bool instead returns " 1 "
and " " ( sic ! ) .
# Inputs
` b `
: 1 \ . Function argument
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
# Type
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
` ` `
boolToString : : bool -> string
` ` `
2017-04-11 16:08:51 +00:00
* /
boolToString = b : if b then " t r u e " else " f a l s e " ;
2024-03-20 02:04:14 +00:00
/* *
Merge two attribute sets shallowly , right side trumps left
mergeAttrs : : attrs -> attrs -> attrs
# Inputs
` x `
: Left attribute set
` y `
: Right attribute set ( higher precedence for equal keys )
2017-03-15 17:29:33 +00:00
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
# Examples
: : : { . example }
## `lib.trivial.mergeAttrs` usage example
` ` ` nix
mergeAttrs { a = 1 ; b = 2 ; } { b = 3 ; c = 4 ; }
= > { a = 1 ; b = 3 ; c = 4 ; }
` ` `
: : :
2017-03-15 17:29:33 +00:00
* /
2018-10-27 14:40:04 +00:00
mergeAttrs =
x :
y : x // y ;
2013-11-12 12:48:19 +00:00
2024-03-20 02:04:14 +00:00
/* *
Flip the order of the arguments of a binary function .
# Inputs
` f `
: 1 \ . Function argument
` a `
: 2 \ . Function argument
2018-07-25 22:03:51 +00:00
2024-03-20 02:04:14 +00:00
` b `
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
: 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 ]
` ` `
: : :
2018-07-25 22:03:51 +00:00
* /
2009-10-23 07:34:56 +00:00
flip = f : a : b : f b a ;
2024-11-20 21:51:15 +00:00
/* *
Return ` maybeValue ` if not null , otherwise return ` default ` .
# Inputs
` default `
: 1 \ . Function argument
` maybeValue `
: 2 \ . Function argument
# Examples
: : : { . example }
## `lib.trivial.defaultTo` usage example
` ` ` nix
defaultTo " d e f a u l t " null
= > " d e f a u l t "
defaultTo " d e f a u l t " " f o o "
= > " f o o "
defaultTo " d e f a u l t " false
= > false
` ` `
: : :
* /
defaultTo = default : maybeValue :
if maybeValue != null then maybeValue
else default ;
2024-03-20 02:04:14 +00:00
/* *
Apply function if the supplied argument is non-null .
# Inputs
2018-07-25 22:03:51 +00:00
2024-03-20 02:04:14 +00:00
` f `
: Function to call
` a `
: Argument to check for null before passing it to ` f `
# Examples
: : : { . example }
## `lib.trivial.mapNullable` usage example
` ` ` nix
mapNullable ( x : x + 1 ) null
= > null
mapNullable ( x : x + 1 ) 22
= > 23
` ` `
: : :
2018-07-25 22:03:51 +00:00
* /
2018-10-27 14:40:04 +00:00
mapNullable =
f :
2019-04-24 03:48:22 +00:00
a : if a == null then a else f a ;
2017-04-17 20:48:10 +00:00
2013-11-12 12:48:19 +00:00
# Pull in some builtins not included elsewhere.
inherit ( builtins )
2018-01-31 19:02:19 +00:00
pathExists readFile isBool
2018-06-30 19:13:49 +00:00
isInt isFloat add sub lessThan
2024-02-09 04:31:01 +00:00
seq deepSeq genericClosure
bitAnd bitOr bitXor ;
2016-07-31 12:59:30 +00:00
2021-04-05 10:13:33 +00:00
## nixpkgs version strings
2018-04-24 18:33:35 +00:00
2024-03-20 02:04:14 +00:00
/* *
Returns the current full nixpkgs version number .
* /
2018-04-26 08:31:05 +00:00
version = release + versionSuffix ;
2024-03-20 02:04:14 +00:00
/* *
Returns the current nixpkgs release number as string .
* /
2024-02-14 15:42:03 +00:00
release = lib . strings . fileContents ./.version ;
2018-07-25 22:03:51 +00:00
2024-03-20 02:04:14 +00:00
/* *
The latest release that is supported , at the time of release branch-off ,
if applicable .
2022-03-09 13:41:43 +00:00
2024-03-20 02:04:14 +00:00
Ideally , out-of-tree modules should be able to evaluate cleanly with all
supported Nixpkgs versions ( master , release and old release until EOL ) .
So if possible , deprecation warnings should take effect only when all
out-of-tree expressions/libs/modules can upgrade to the new way without
losing support for supported Nixpkgs versions .
2022-03-09 13:41:43 +00:00
2024-03-20 02:04:14 +00:00
This release number allows deprecation warnings to be implemented such that
they take effect as soon as the oldest release reaches end of life .
* /
2022-03-09 13:41:43 +00:00
oldestSupportedRelease =
# Update on master only. Do not backport.
2024-06-30 20:25:29 +00:00
2405 ;
2022-03-09 13:41:43 +00:00
2024-03-20 02:04:14 +00:00
/* *
Whether a feature is supported in all supported releases ( at the time of
release branch-off , if applicable ) . See ` oldestSupportedRelease ` .
# Inputs
` release `
: Release number of feature introduction as an integer , e . g . 2111 for 21 .11 .
Set it to the upcoming release , matching the nixpkgs/.version file .
* /
2022-03-09 13:41:43 +00:00
isInOldestRelease =
2024-10-08 09:02:09 +00:00
lib . warnIf ( lib . oldestSupportedReleaseIsAtLeast 2411 )
" l i b . i s I n O l d e s t R e l e a s e i s d e p r e c a t e d . U s e l i b . o l d e s t S u p p o r t e d R e l e a s e I s A t L e a s t i n s t e a d . "
lib . oldestSupportedReleaseIsAtLeast ;
/* *
Alias for ` isInOldestRelease ` introduced in 24 .11 .
Use ` isInOldestRelease ` in expressions outside of Nixpkgs for greater compatibility .
* /
oldestSupportedReleaseIsAtLeast =
2022-03-09 13:41:43 +00:00
release :
release <= lib . trivial . oldestSupportedRelease ;
2024-03-20 02:04:14 +00:00
/* *
Returns the current nixpkgs release code name .
2018-11-15 20:51:29 +00:00
2024-03-20 02:04:14 +00:00
On each release the first letter is bumped and a new animal is chosen
starting with that new letter .
2018-11-15 20:51:29 +00:00
* /
2024-11-14 17:09:41 +00:00
codeName = " W a r b l e r " ;
2018-11-15 20:51:29 +00:00
2024-03-20 02:04:14 +00:00
/* *
Returns the current nixpkgs version suffix as string .
* /
2018-07-25 22:03:51 +00:00
versionSuffix =
let suffixFile = ../.version-suffix ;
in if pathExists suffixFile
then lib . strings . fileContents suffixFile
else " p r e - g i t " ;
2024-03-20 02:04:14 +00:00
/* *
Attempts to return the the current revision of nixpkgs and
returns the supplied default value otherwise .
# Inputs
` default `
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
: Default value to return if revision can not be determined
# Type
` ` `
revisionWithDefault : : string -> string
` ` `
2018-10-27 14:40:04 +00:00
* /
revisionWithDefault =
default :
2018-10-05 14:48:42 +00:00
let
2022-11-22 16:33:09 +00:00
revisionFile = " ${ toString ./.. } / . g i t - r e v i s i o n " ;
gitRepo = " ${ toString ./.. } / . g i t " ;
2020-01-19 23:44:07 +00:00
in if lib . pathIsGitRepo gitRepo
2018-10-05 14:48:42 +00:00
then lib . commitIdFromGitRepo gitRepo
else if lib . pathExists revisionFile then lib . fileContents revisionFile
else default ;
2024-02-03 15:13:04 +00:00
nixpkgsVersion = warn " l i b . n i x p k g s V e r s i o n i s a d e p r e c a t e d a l i a s o f l i b . v e r s i o n . " version ;
2014-02-19 17:47:48 +00:00
2024-03-20 02:04:14 +00:00
/* *
Determine whether the function is being called from inside a Nix
shell .
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
# Type
` ` `
inNixShell : : bool
` ` `
2018-10-27 14:40:04 +00:00
* /
2016-08-11 14:35:06 +00:00
inNixShell = builtins . getEnv " I N _ N I X _ S H E L L " != " " ;
2014-02-19 18:00:51 +00:00
2024-03-20 02:04:14 +00:00
/* *
Determine whether the function is being called from inside pure-eval mode
by seeing whether ` builtins ` contains ` currentSystem ` . If not , we must be in
pure-eval mode .
# Type
2021-11-14 23:14:09 +00:00
2024-03-20 02:04:14 +00:00
` ` `
inPureEvalMode : : bool
` ` `
2021-11-14 23:14:09 +00:00
* /
inPureEvalMode = ! builtins ? currentSystem ;
2018-07-25 22:03:51 +00:00
## Integer operations
2024-03-20 02:04:14 +00:00
/* *
Return minimum of two numbers .
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
* /
2015-02-16 10:57:36 +00:00
min = x : y : if x < y then x else y ;
2018-10-27 14:40:04 +00:00
2024-03-20 02:04:14 +00:00
/* *
Return maximum of two numbers .
# Inputs
` x `
: 1 \ . Function argument
` y `
: 2 \ . Function argument
* /
2015-02-16 10:57:36 +00:00
max = x : y : if x > y then x else y ;
2024-03-20 02:04:14 +00:00
/* *
Integer modulus
# Inputs
` base `
: 1 \ . Function argument
` int `
: 2 \ . Function argument
2017-08-30 12:32:04 +00:00
2024-03-20 02:04:14 +00:00
# Examples
: : : { . example }
## `lib.trivial.mod` usage example
` ` ` nix
mod 11 10
= > 1
mod 1 10
= > 1
` ` `
: : :
2017-08-30 12:32:04 +00:00
* /
mod = base : int : base - ( int * ( builtins . div base int ) ) ;
2018-07-25 22:03:51 +00:00
## Comparisons
2024-03-20 02:04:14 +00:00
/* *
C-style comparisons
a < b , compare a b = > -1
a == b , compare a b = > 0
a > b , compare a b = > 1
# Inputs
` a `
: 1 \ . Function argument
` b `
2017-12-07 21:26:30 +00:00
2024-03-20 02:04:14 +00:00
: 2 \ . Function argument
2017-12-07 21:26:30 +00:00
* /
compare = a : b :
if a < b
then -1
else if a > b
then 1
else 0 ;
2024-03-20 02:04:14 +00:00
/* *
Split type into two subtypes by predicate ` p ` , take all elements
of the first subtype to be less than all the elements of the
second subtype , compare elements of a single subtype with ` yes `
and ` no ` respectively .
# Inputs
` p `
: Predicate
` yes `
: Comparison function if predicate holds for both values
` no `
2017-12-07 21:26:30 +00:00
2024-03-20 02:04:14 +00:00
: Comparison function if predicate holds for neither value
2017-12-07 21:26:30 +00:00
2024-03-20 02:04:14 +00:00
` a `
2017-12-07 21:26:30 +00:00
2024-03-20 02:04:14 +00:00
: First value to compare
2017-12-07 21:26:30 +00:00
2024-03-20 02:04:14 +00:00
` b `
: Second value to compare
# Type
` ` `
( a -> bool ) -> ( a -> a -> int ) -> ( a -> a -> int ) -> ( a -> a -> int )
` ` `
# Examples
: : : { . example }
## `lib.trivial.splitByAndCompare` usage example
` ` ` nix
let cmp = splitByAndCompare ( hasPrefix " f o o " ) compare compare ; in
cmp " a " " z " = > -1
cmp " f o o a " " f o o z " = > -1
cmp " f " " a " = > 1
cmp " f o o a " " a " = > -1
# while
compare " f o o a " " a " = > 1
` ` `
: : :
2017-12-07 21:26:30 +00:00
* /
2018-10-27 14:40:04 +00:00
splitByAndCompare =
2024-03-20 02:04:14 +00:00
p : yes : no : a : b :
2017-12-07 21:26:30 +00:00
if p a
then if p b then yes a b else -1
else if p b then 1 else no a b ;
2018-07-25 22:03:51 +00:00
2024-03-20 02:04:14 +00:00
/* *
Reads a JSON file .
2018-10-27 14:40:04 +00:00
2024-06-07 21:22:17 +00:00
# Examples
: : : { . example }
## `lib.trivial.importJSON` usage example
example . json
` ` ` json
{
" t i t l e " : " E x a m p l e J S O N " ,
" h e l l o " : {
" w o r l d " : " f o o " ,
" b a r " : {
" f o o b a r " : true
}
}
}
` ` `
` ` ` nix
importJSON ./example.json
= > {
title = " E x a m p l e J S O N " ;
hello = {
world = " f o o " ;
bar = {
foobar = true ;
} ;
} ;
}
` ` `
: : :
2024-03-20 02:04:14 +00:00
# Inputs
` path `
: 1 \ . Function argument
# Type
` ` `
importJSON : : path -> any
` ` `
2018-10-27 14:40:04 +00:00
* /
2016-02-28 16:35:27 +00:00
importJSON = path :
builtins . fromJSON ( builtins . readFile path ) ;
2016-08-15 17:54:23 +00:00
2024-03-20 02:04:14 +00:00
/* *
Reads a TOML file .
2024-06-07 21:15:50 +00:00
# Examples
: : : { . example }
## `lib.trivial.importTOML` usage example
example . toml
` ` ` toml
title = " T O M L E x a m p l e "
[ hello ]
world = " f o o "
[ hello . bar ]
foobar = true
` ` `
` ` ` nix
importTOML ./example.toml
= > {
title = " T O M L E x a m p l e " ;
hello = {
world = " f o o " ;
bar = {
foobar = true ;
} ;
} ;
}
` ` `
: : :
2024-03-20 02:04:14 +00:00
# Inputs
2020-08-16 13:39:52 +00:00
2024-03-20 02:04:14 +00:00
` path `
: 1 \ . Function argument
# Type
` ` `
importTOML : : path -> any
` ` `
2020-08-16 13:39:52 +00:00
* /
importTOML = path :
builtins . fromTOML ( builtins . readFile path ) ;
2018-07-25 22:03:51 +00:00
2024-07-23 10:48:01 +00:00
/* *
2018-07-25 22:03:51 +00:00
2024-07-23 10:48:01 +00:00
` warn ` * ` message ` * * ` value ` *
2016-08-15 17:54:23 +00:00
2024-07-23 10:48:01 +00:00
Print a warning before returning the second argument .
2021-08-25 16:35:16 +00:00
2024-07-23 10:48:01 +00:00
See [ ` builtins . warn ` ] ( https://nix.dev/manual/nix/latest/language/builtins.html #builtins-warn) (Nix >= 2.23).
On older versions , the Nix 2 .23 behavior is emulated with [ ` builtins . trace ` ] ( https://nix.dev/manual/nix/latest/language/builtins.html #builtins-warn), including the [`NIX_ABORT_ON_WARN`](https://nix.dev/manual/nix/latest/command-ref/conf-file#conf-abort-on-warn) behavior, but not the `nix.conf` setting or command line option.
2021-08-25 16:35:16 +00:00
2024-03-20 02:04:14 +00:00
# Inputs
2024-07-23 10:48:01 +00:00
* ` message ` * ( String )
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
: Warning message to print before evaluating * ` value ` * .
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
* ` value ` * ( any value )
2024-03-20 02:04:14 +00:00
: Value to return as-is .
# Type
` ` `
2024-07-23 10:48:01 +00:00
String -> a -> a
2024-03-20 02:04:14 +00:00
` ` `
2021-08-25 16:35:16 +00:00
* /
warn =
2024-07-23 10:48:01 +00:00
# Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
2024-04-24 09:10:29 +00:00
builtins . warn or (
let mustAbort = lib . elem ( builtins . getEnv " N I X _ A B O R T _ O N _ W A R N " ) [ " 1 " " t r u e " " y e s " ] ;
in
# Do not eta reduce v, so that we have the same strictness as `builtins.warn`.
msg : v :
# `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions.
assert isString msg ;
if mustAbort
2024-07-16 13:55:05 +00:00
then builtins . trace " [ 1 ; 3 1 m e v a l u a t i o n w a r n i n g : [ 0 m ${ msg } " ( abort " N I X _ A B O R T _ O N _ W A R N = t r u e ; w a r n i n g s a r e t r e a t e d a s u n r e c o v e r a b l e e r r o r s . " )
else builtins . trace " [ 1 ; 3 5 m e v a l u a t i o n w a r n i n g : [ 0 m ${ msg } " v
2024-04-24 09:10:29 +00:00
) ;
2021-08-25 16:35:16 +00:00
2024-03-20 02:04:14 +00:00
/* *
2021-08-25 16:35:16 +00:00
2024-07-23 10:48:01 +00:00
` warnIf ` * ` condition ` * * ` message ` * * ` value ` *
Like ` warn ` , but only warn when the first argument is ` true ` .
2024-03-20 02:04:14 +00:00
# Inputs
2024-07-23 10:48:01 +00:00
* ` condition ` * ( Boolean )
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
: ` true ` to trigger the warning before continuing with * ` value ` * .
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
* ` message ` * ( String )
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
: Warning message to print before evaluating
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
* ` value ` * ( any value )
2024-03-20 02:04:14 +00:00
: Value to return as-is .
# Type
` ` `
2024-07-23 10:48:01 +00:00
Bool -> String -> a -> a
2024-03-20 02:04:14 +00:00
` ` `
2021-08-25 16:35:16 +00:00
* /
2022-03-19 19:39:52 +00:00
warnIf = cond : msg : if cond then warn msg else x : x ;
2024-03-20 02:04:14 +00:00
/* *
2022-03-19 19:39:52 +00:00
2024-07-23 10:48:01 +00:00
` warnIfNot ` * ` condition ` * * ` message ` * * ` value ` *
Like ` warnIf ` , but negated : warn if the first argument is ` false ` .
2024-03-20 02:04:14 +00:00
# Inputs
2024-07-23 10:48:01 +00:00
* ` condition ` *
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
: ` false ` to trigger the warning before continuing with ` val ` .
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
* ` message ` *
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
: Warning message to print before evaluating * ` value ` * .
2024-03-20 02:04:14 +00:00
2024-07-23 10:48:01 +00:00
* ` value ` *
2024-03-20 02:04:14 +00:00
: Value to return as-is .
# Type
` ` `
2024-07-23 10:48:01 +00:00
Boolean -> String -> a -> a
2024-03-20 02:04:14 +00:00
` ` `
2022-03-19 19:39:52 +00:00
* /
warnIfNot = cond : msg : if cond then x : x else warn msg ;
2021-04-27 10:56:51 +00:00
2024-03-20 02:04:14 +00:00
/* *
2021-12-22 12:05:55 +00:00
Like the ` assert b ; e ` expression , but with a custom error message and
without the semicolon .
If true , return the identity function , ` r : r ` .
If false , throw the error message .
Calls can be juxtaposed using function application , as ` ( r : r ) a = a ` , so
` ( r : r ) ( r : r ) a = a ` , and so forth .
2024-03-20 02:04:14 +00:00
# Inputs
` cond `
: 1 \ . Function argument
2021-12-22 12:05:55 +00:00
2024-03-20 02:04:14 +00:00
` msg `
2021-12-22 12:05:55 +00:00
2024-03-20 02:04:14 +00:00
: 2 \ . Function argument
# Type
` ` `
bool -> string -> a -> a
` ` `
# Examples
: : : { . example }
## `lib.trivial.throwIfNot` usage example
` ` ` nix
throwIfNot ( lib . isList overlays ) " T h e o v e r l a y s a r g u m e n t t o n i x p k g s m u s t b e a l i s t . "
lib . foldr ( x : throwIfNot ( lib . isFunction x ) " A l l o v e r l a y s p a s s e d t o n i x p k g s m u s t b e f u n c t i o n s . " ) ( r : r ) overlays
pkgs
` ` `
: : :
2021-12-22 12:05:55 +00:00
* /
throwIfNot = cond : msg : if cond then x : x else throw msg ;
2024-03-20 02:04:14 +00:00
/* *
2022-03-19 19:39:52 +00:00
Like throwIfNot , but negated ( throw if the first argument is ` true ` ) .
2024-03-20 02:04:14 +00:00
# Inputs
` cond `
: 1 \ . Function argument
` msg `
: 2 \ . Function argument
# Type
` ` `
bool -> string -> a -> a
` ` `
2022-03-19 19:39:52 +00:00
* /
throwIf = cond : msg : if cond then throw msg else x : x ;
2024-03-20 02:04:14 +00:00
/* *
Check if the elements in a list are valid values from a enum , returning the identity function , or throwing an error message otherwise .
# Inputs
` msg `
2022-01-09 22:12:27 +00:00
2024-03-20 02:04:14 +00:00
: 1 \ . Function argument
2022-01-09 22:12:27 +00:00
2024-03-20 02:04:14 +00:00
` valid `
: 2 \ . Function argument
` given `
: 3 \ . Function argument
# Type
` ` `
String -> List ComparableVal -> List ComparableVal -> a -> a
` ` `
# Examples
: : : { . example }
## `lib.trivial.checkListOfEnum` usage example
` ` ` nix
let colorVariants = [ " b r i g h t " " d a r k " " b l a c k " ]
in checkListOfEnum " c o l o r v a r i a n t s " [ " s t a n d a r d " " l i g h t " " d a r k " ] colorVariants ;
= >
error : color variants : bright , black unexpected ; valid ones : standard , light , dark
` ` `
: : :
2022-01-09 22:12:27 +00:00
* /
checkListOfEnum = msg : valid : given :
let
unexpected = lib . subtractLists valid given ;
in
lib . throwIfNot ( unexpected == [ ] )
" ${ msg } : ${ builtins . concatStringsSep " , " ( builtins . map builtins . toString unexpected ) } u n e x p e c t e d ; v a l i d o n e s : ${ builtins . concatStringsSep " , " ( builtins . map builtins . toString valid ) } " ;
2016-08-15 17:54:23 +00:00
info = msg : builtins . trace " I N F O : ${ msg } " ;
2018-01-31 19:02:19 +00:00
2021-01-25 06:57:48 +00:00
showWarnings = warnings : res : lib . foldr ( w : x : warn w x ) res warnings ;
2018-07-25 22:03:51 +00:00
## Function annotations
2024-03-20 02:04:14 +00:00
/* *
Add metadata about expected function arguments to a function .
The metadata should match the format given by
builtins . functionArgs , i . e . a set from expected argument to a bool
representing whether that argument has a default or not .
setFunctionArgs : ( a → b ) → Map String Bool → ( a → b )
2018-07-25 22:03:51 +00:00
2024-03-20 02:04:14 +00:00
This function is necessary because you can't dynamically create a
function of the { a , b ? foo , . . . }: format , but some facilities
like callPackage expect to be able to query expected arguments .
# Inputs
` f `
: 1 \ . Function argument
` args `
: 2 \ . Function argument
2018-07-25 22:03:51 +00:00
* /
2018-01-31 19:02:19 +00:00
setFunctionArgs = f : args :
{ # TODO: Should we add call-time "type" checking like built in?
__functor = self : f ;
__functionArgs = args ;
} ;
2024-03-20 02:04:14 +00:00
/* *
Extract the expected function arguments from a function .
This works both with nix-native { a , b ? foo , . . . }: style
functions and functions with args set with ' setFunctionArgs' . It
has the same return type and semantics as builtins . functionArgs .
setFunctionArgs : ( a → b ) → Map String Bool .
# Inputs
` f `
: 1 \ . Function argument
2018-07-25 22:03:51 +00:00
* /
2021-07-23 19:10:31 +00:00
functionArgs = f :
if f ? __functor
2023-10-31 12:35:51 +00:00
then f . __functionArgs or ( functionArgs ( f . __functor f ) )
2021-07-23 19:10:31 +00:00
else builtins . functionArgs f ;
2018-01-31 19:02:19 +00:00
2024-03-20 02:04:14 +00:00
/* *
Check whether something is a function or something
annotated with function args .
# Inputs
` f `
: 1 \ . Function argument
2018-07-25 22:03:51 +00:00
* /
2018-01-31 19:02:19 +00:00
isFunction = f : builtins . isFunction f ||
( f ? __functor && isFunction ( f . __functor f ) ) ;
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
/* *
2023-05-28 21:51:52 +00:00
` mirrorFunctionArgs f g ` creates a new function ` g' ` with the same behavior as ` g ` ( ` g' x == g x ` )
but its function arguments mirroring ` f ` ( ` lib . functionArgs g' == lib . functionArgs f ` ) .
2024-03-20 02:04:14 +00:00
# Inputs
` f `
: Function to provide the argument metadata
` g `
: Function to set the argument metadata to
# Type
` ` `
mirrorFunctionArgs : : ( a -> b ) -> ( a -> c ) -> ( a -> c )
` ` `
# Examples
: : : { . example }
## `lib.trivial.mirrorFunctionArgs` usage example
` ` ` nix
addab = { a , b }: a + b
addab { a = 2 ; b = 4 ; }
= > 6
lib . functionArgs addab
= > { a = false ; b = false ; }
addab1 = attrs : addab attrs + 1
addab1 { a = 2 ; b = 4 ; }
= > 7
lib . functionArgs addab1
= > { }
addab1' = lib . mirrorFunctionArgs addab addab1
addab1' { a = 2 ; b = 4 ; }
= > 7
lib . functionArgs addab1'
= > { a = false ; b = false ; }
` ` `
: : :
2023-05-28 21:51:52 +00:00
* /
mirrorFunctionArgs =
f :
let
fArgs = functionArgs f ;
in
g :
setFunctionArgs g fArgs ;
2024-03-20 02:04:14 +00:00
/* *
2022-03-21 22:06:01 +00:00
Turns any non-callable values into constant functions .
Returns callable values as is .
2024-03-20 02:04:14 +00:00
# Inputs
` v `
: Any value
# Examples
: : : { . example }
## `lib.trivial.toFunction` usage example
` ` ` nix
nix-repl > lib . toFunction 1 2
1
2022-03-21 22:06:01 +00:00
2024-03-20 02:04:14 +00:00
nix-repl > lib . toFunction ( x : x + 1 ) 2
3
` ` `
: : :
2022-03-21 22:06:01 +00:00
* /
toFunction =
v :
if isFunction v
then v
else k : v ;
2023-11-10 17:40:00 +00:00
/* *
Convert a hexadecimal string to it's integer representation .
# Type
` ` `
fromHexString : : String -> [ String ]
` ` `
# Examples
` ` ` nix
fromHexString " F F "
= > 255
fromHexString ( builtins . hashString " s h a 2 5 6 " " t e s t " )
= > 9223372036854775807
` ` `
* /
fromHexString = value :
let
noPrefix = lib . strings . removePrefix " 0 x " ( lib . strings . toLower value ) ;
in let
parsed = builtins . fromTOML " v = 0 x ${ noPrefix } " ;
in parsed . v ;
2024-03-20 02:04:14 +00:00
/* *
Convert the given positive integer to a string of its hexadecimal
representation . For example :
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
toHexString 0 = > " 0 "
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
toHexString 16 = > " 1 0 "
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
toHexString 250 = > " F A "
2020-04-20 10:00:23 +00:00
* /
2023-12-11 03:36:03 +00:00
toHexString = let
hexDigits = {
" 1 0 " = " A " ;
" 1 1 " = " B " ;
" 1 2 " = " C " ;
" 1 3 " = " D " ;
" 1 4 " = " E " ;
" 1 5 " = " F " ;
} ;
toHexDigit = d :
if d < 10
then toString d
else hexDigits . ${ toString d } ;
in i : lib . concatMapStrings toHexDigit ( toBaseDigits 16 i ) ;
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
/* *
` toBaseDigits base i ` converts the positive integer i to a list of its
digits in the given base . For example :
toBaseDigits 10 123 = > [ 1 2 3 ]
toBaseDigits 2 6 = > [ 1 1 0 ]
toBaseDigits 16 250 = > [ 15 10 ]
# Inputs
` base `
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
: 1 \ . Function argument
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
` i `
2020-04-20 10:00:23 +00:00
2024-03-20 02:04:14 +00:00
: 2 \ . Function argument
2020-04-20 10:00:23 +00:00
* /
2020-07-20 11:14:19 +00:00
toBaseDigits = base : i :
2020-04-20 10:00:23 +00:00
let
go = i :
if i < base
then [ i ]
else
let
r = i - ( ( i / base ) * base ) ;
q = ( i - r ) / base ;
in
[ r ] ++ go q ;
in
2022-11-11 09:30:23 +00:00
assert ( isInt base ) ;
assert ( isInt i ) ;
2020-04-20 10:00:23 +00:00
assert ( base >= 2 ) ;
assert ( i >= 0 ) ;
lib . reverseList ( go i ) ;
2009-02-09 16:51:03 +00:00
}