chromium,chromedriver: 128.0.6613.137 -> 129.0.6668.58 (#342721)
[NixPkgs.git] / lib / trivial.nix
blobf0afbf609fcab3c1d515c7c29f465c6b466d9948
1 { lib }:
3 let
4   inherit (lib.trivial)
5     isFunction
6     isInt
7     functionArgs
8     pathExists
9     release
10     setFunctionArgs
11     toBaseDigits
12     version
13     versionSuffix
14     warn;
15   inherit (lib)
16     isString
17     ;
18 in {
20   ## Simple (higher order) functions
22   /**
23     The identity function
24     For when you need a function that does “nothing”.
27     # Inputs
29     `x`
31     : The value to return
33     # Type
35     ```
36     id :: a -> a
37     ```
38   */
39   id = x: x;
41   /**
42     The constant function
44     Ignores the second argument. If called with only one argument,
45     constructs a function that always returns a static value.
48     # Inputs
50     `x`
52     : Value to return
54     `y`
56     : Value to ignore
58     # Type
60     ```
61     const :: a -> b -> a
62     ```
64     # Examples
65     :::{.example}
66     ## `lib.trivial.const` usage example
68     ```nix
69     let f = const 5; in f 10
70     => 5
71     ```
73     :::
74   */
75   const =
76     x:
77     y: x;
79   /**
80     Pipes a value through a list of functions, left to right.
82     # Inputs
84     `value`
86     : Value to start piping.
88     `fns`
90     : List of functions to apply sequentially.
92     # Type
94     ```
95     pipe :: a -> [<functions>] -> <return type of last function>
96     ```
98     # Examples
99     :::{.example}
100     ## `lib.trivial.pipe` usage example
102     ```nix
103     pipe 2 [
104         (x: x + 2)  # 2 + 2 = 4
105         (x: x * 2)  # 4 * 2 = 8
106       ]
107     => 8
109     # ideal to do text transformations
110     pipe [ "a/b" "a/c" ] [
112       # create the cp command
113       (map (file: ''cp "${src}/${file}" $out\n''))
115       # concatenate all commands into one string
116       lib.concatStrings
118       # make that string into a nix derivation
119       (pkgs.runCommand "copy-to-out" {})
121     ]
122     => <drv which copies all files to $out>
124     The output type of each function has to be the input type
125     of the next function, and the last function returns the
126     final value.
127     ```
129     :::
130   */
131   pipe = builtins.foldl' (x: f: f x);
133   # note please don’t add a function like `compose = flip pipe`.
134   # This would confuse users, because the order of the functions
135   # in the list is not clear. With pipe, it’s obvious that it
136   # goes first-to-last. With `compose`, not so much.
138   ## Named versions corresponding to some builtin operators.
140   /**
141     Concatenate two lists
144     # Inputs
146     `x`
148     : 1\. Function argument
150     `y`
152     : 2\. Function argument
154     # Type
156     ```
157     concat :: [a] -> [a] -> [a]
158     ```
160     # Examples
161     :::{.example}
162     ## `lib.trivial.concat` usage example
164     ```nix
165     concat [ 1 2 ] [ 3 4 ]
166     => [ 1 2 3 4 ]
167     ```
169     :::
170   */
171   concat = x: y: x ++ y;
173   /**
174     boolean “or”
177     # Inputs
179     `x`
181     : 1\. Function argument
183     `y`
185     : 2\. Function argument
186   */
187   or = x: y: x || y;
189   /**
190     boolean “and”
193     # Inputs
195     `x`
197     : 1\. Function argument
199     `y`
201     : 2\. Function argument
202   */
203   and = x: y: x && y;
205   /**
206     boolean “exclusive or”
209     # Inputs
211     `x`
213     : 1\. Function argument
215     `y`
217     : 2\. Function argument
218   */
219   # We explicitly invert the arguments purely as a type assertion.
220   # This is invariant under XOR, so it does not affect the result.
221   xor = x: y: (!x) != (!y);
223   /**
224     bitwise “not”
225   */
226   bitNot = builtins.sub (-1);
228   /**
229     Convert a boolean to a string.
231     This function uses the strings "true" and "false" to represent
232     boolean values. Calling `toString` on a bool instead returns "1"
233     and "" (sic!).
236     # Inputs
238     `b`
240     : 1\. Function argument
242     # Type
244     ```
245     boolToString :: bool -> string
246     ```
247   */
248   boolToString = b: if b then "true" else "false";
250   /**
251     Merge two attribute sets shallowly, right side trumps left
253     mergeAttrs :: attrs -> attrs -> attrs
256     # Inputs
258     `x`
260     : Left attribute set
262     `y`
264     : Right attribute set (higher precedence for equal keys)
267     # Examples
268     :::{.example}
269     ## `lib.trivial.mergeAttrs` usage example
271     ```nix
272     mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
273     => { a = 1; b = 3; c = 4; }
274     ```
276     :::
277   */
278   mergeAttrs =
279     x:
280     y: x // y;
282   /**
283     Flip the order of the arguments of a binary function.
286     # Inputs
288     `f`
290     : 1\. Function argument
292     `a`
294     : 2\. Function argument
296     `b`
298     : 3\. Function argument
300     # Type
302     ```
303     flip :: (a -> b -> c) -> (b -> a -> c)
304     ```
306     # Examples
307     :::{.example}
308     ## `lib.trivial.flip` usage example
310     ```nix
311     flip concat [1] [2]
312     => [ 2 1 ]
313     ```
315     :::
316   */
317   flip = f: a: b: f b a;
319   /**
320     Apply function if the supplied argument is non-null.
323     # Inputs
325     `f`
327     : Function to call
329     `a`
331     : Argument to check for null before passing it to `f`
334     # Examples
335     :::{.example}
336     ## `lib.trivial.mapNullable` usage example
338     ```nix
339     mapNullable (x: x+1) null
340     => null
341     mapNullable (x: x+1) 22
342     => 23
343     ```
345     :::
346   */
347   mapNullable =
348     f:
349     a: if a == null then a else f a;
351   # Pull in some builtins not included elsewhere.
352   inherit (builtins)
353     pathExists readFile isBool
354     isInt isFloat add sub lessThan
355     seq deepSeq genericClosure
356     bitAnd bitOr bitXor;
358   ## nixpkgs version strings
360   /**
361     Returns the current full nixpkgs version number.
362   */
363   version = release + versionSuffix;
365   /**
366     Returns the current nixpkgs release number as string.
367   */
368   release = lib.strings.fileContents ./.version;
370   /**
371     The latest release that is supported, at the time of release branch-off,
372     if applicable.
374     Ideally, out-of-tree modules should be able to evaluate cleanly with all
375     supported Nixpkgs versions (master, release and old release until EOL).
376     So if possible, deprecation warnings should take effect only when all
377     out-of-tree expressions/libs/modules can upgrade to the new way without
378     losing support for supported Nixpkgs versions.
380     This release number allows deprecation warnings to be implemented such that
381     they take effect as soon as the oldest release reaches end of life.
382   */
383   oldestSupportedRelease =
384     # Update on master only. Do not backport.
385     2405;
387   /**
388     Whether a feature is supported in all supported releases (at the time of
389     release branch-off, if applicable). See `oldestSupportedRelease`.
392     # Inputs
394     `release`
396     : Release number of feature introduction as an integer, e.g. 2111 for 21.11.
397     Set it to the upcoming release, matching the nixpkgs/.version file.
398   */
399   isInOldestRelease =
400     release:
401       release <= lib.trivial.oldestSupportedRelease;
403   /**
404     Returns the current nixpkgs release code name.
406     On each release the first letter is bumped and a new animal is chosen
407     starting with that new letter.
408   */
409   codeName = "Vicuna";
411   /**
412     Returns the current nixpkgs version suffix as string.
413   */
414   versionSuffix =
415     let suffixFile = ../.version-suffix;
416     in if pathExists suffixFile
417     then lib.strings.fileContents suffixFile
418     else "pre-git";
420   /**
421     Attempts to return the the current revision of nixpkgs and
422     returns the supplied default value otherwise.
425     # Inputs
427     `default`
429     : Default value to return if revision can not be determined
431     # Type
433     ```
434     revisionWithDefault :: string -> string
435     ```
436   */
437   revisionWithDefault =
438     default:
439     let
440       revisionFile = "${toString ./..}/.git-revision";
441       gitRepo      = "${toString ./..}/.git";
442     in if lib.pathIsGitRepo gitRepo
443        then lib.commitIdFromGitRepo gitRepo
444        else if lib.pathExists revisionFile then lib.fileContents revisionFile
445        else default;
447   nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
449   /**
450     Determine whether the function is being called from inside a Nix
451     shell.
453     # Type
455     ```
456     inNixShell :: bool
457     ```
458   */
459   inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
461   /**
462     Determine whether the function is being called from inside pure-eval mode
463     by seeing whether `builtins` contains `currentSystem`. If not, we must be in
464     pure-eval mode.
466     # Type
468     ```
469     inPureEvalMode :: bool
470     ```
471   */
472   inPureEvalMode = ! builtins ? currentSystem;
474   ## Integer operations
476   /**
477     Return minimum of two numbers.
480     # Inputs
482     `x`
484     : 1\. Function argument
486     `y`
488     : 2\. Function argument
489   */
490   min = x: y: if x < y then x else y;
492   /**
493     Return maximum of two numbers.
496     # Inputs
498     `x`
500     : 1\. Function argument
502     `y`
504     : 2\. Function argument
505   */
506   max = x: y: if x > y then x else y;
508   /**
509     Integer modulus
512     # Inputs
514     `base`
516     : 1\. Function argument
518     `int`
520     : 2\. Function argument
523     # Examples
524     :::{.example}
525     ## `lib.trivial.mod` usage example
527     ```nix
528     mod 11 10
529     => 1
530     mod 1 10
531     => 1
532     ```
534     :::
535   */
536   mod = base: int: base - (int * (builtins.div base int));
539   ## Comparisons
541   /**
542     C-style comparisons
544     a < b,  compare a b => -1
545     a == b, compare a b => 0
546     a > b,  compare a b => 1
549     # Inputs
551     `a`
553     : 1\. Function argument
555     `b`
557     : 2\. Function argument
558   */
559   compare = a: b:
560     if a < b
561     then -1
562     else if a > b
563          then 1
564          else 0;
566   /**
567     Split type into two subtypes by predicate `p`, take all elements
568     of the first subtype to be less than all the elements of the
569     second subtype, compare elements of a single subtype with `yes`
570     and `no` respectively.
573     # Inputs
575     `p`
577     : Predicate
579     `yes`
581     : Comparison function if predicate holds for both values
583     `no`
585     : Comparison function if predicate holds for neither value
587     `a`
589     : First value to compare
591     `b`
593     : Second value to compare
595     # Type
597     ```
598     (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
599     ```
601     # Examples
602     :::{.example}
603     ## `lib.trivial.splitByAndCompare` usage example
605     ```nix
606     let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
608     cmp "a" "z" => -1
609     cmp "fooa" "fooz" => -1
611     cmp "f" "a" => 1
612     cmp "fooa" "a" => -1
613     # while
614     compare "fooa" "a" => 1
615     ```
617     :::
618   */
619   splitByAndCompare =
620     p: yes: no: a: b:
621     if p a
622     then if p b then yes a b else -1
623     else if p b then 1 else no a b;
626   /**
627     Reads a JSON file.
629     # Examples
630     :::{.example}
631     ## `lib.trivial.importJSON` usage example
633     example.json
634     ```json
635     {
636       "title": "Example JSON",
637       "hello": {
638         "world": "foo",
639         "bar": {
640           "foobar": true
641         }
642       }
643     }
644     ```
646     ```nix
647     importJSON ./example.json
648     => {
649       title = "Example JSON";
650       hello = {
651         world = "foo";
652         bar = {
653           foobar = true;
654         };
655       };
656     }
657     ```
659     :::
661     # Inputs
663     `path`
665     : 1\. Function argument
667     # Type
669     ```
670     importJSON :: path -> any
671     ```
672   */
673   importJSON = path:
674     builtins.fromJSON (builtins.readFile path);
676   /**
677     Reads a TOML file.
679     # Examples
680     :::{.example}
681     ## `lib.trivial.importTOML` usage example
683     example.toml
684     ```toml
685     title = "TOML Example"
687     [hello]
688     world = "foo"
690     [hello.bar]
691     foobar = true
692     ```
694     ```nix
695     importTOML ./example.toml
696     => {
697       title = "TOML Example";
698       hello = {
699         world = "foo";
700         bar = {
701           foobar = true;
702         };
703       };
704     }
705     ```
707     :::
709     # Inputs
711     `path`
713     : 1\. Function argument
715     # Type
717     ```
718     importTOML :: path -> any
719     ```
720   */
721   importTOML = path:
722     builtins.fromTOML (builtins.readFile path);
724   /**
726     `warn` *`message`* *`value`*
728     Print a warning before returning the second argument.
730     See [`builtins.warn`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn) (Nix >= 2.23).
731     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.
733     # Inputs
735     *`message`* (String)
737     : Warning message to print before evaluating *`value`*.
739     *`value`* (any value)
741     : Value to return as-is.
743     # Type
745     ```
746     String -> a -> a
747     ```
748   */
749   warn =
750     # Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
751     builtins.warn or (
752       let mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"];
753       in
754         # Do not eta reduce v, so that we have the same strictness as `builtins.warn`.
755         msg: v:
756           # `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions.
757           assert isString msg;
758           if mustAbort
759           then builtins.trace "\e[1;31mevaluation warning:\e[0m ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
760           else builtins.trace "\e[1;35mevaluation warning:\e[0m ${msg}" v
761     );
763   /**
765     `warnIf` *`condition`* *`message`* *`value`*
767     Like `warn`, but only warn when the first argument is `true`.
769     # Inputs
771     *`condition`* (Boolean)
773     : `true` to trigger the warning before continuing with *`value`*.
775     *`message`* (String)
777     : Warning message to print before evaluating
779     *`value`* (any value)
781     : Value to return as-is.
783     # Type
785     ```
786     Bool -> String -> a -> a
787     ```
788   */
789   warnIf = cond: msg: if cond then warn msg else x: x;
791   /**
793     `warnIfNot` *`condition`* *`message`* *`value`*
795     Like `warnIf`, but negated: warn if the first argument is `false`.
797     # Inputs
799     *`condition`*
801     : `false` to trigger the warning before continuing with `val`.
803     *`message`*
805     : Warning message to print before evaluating *`value`*.
807     *`value`*
809     : Value to return as-is.
811     # Type
813     ```
814     Boolean -> String -> a -> a
815     ```
816   */
817   warnIfNot = cond: msg: if cond then x: x else warn msg;
819   /**
820     Like the `assert b; e` expression, but with a custom error message and
821     without the semicolon.
823     If true, return the identity function, `r: r`.
825     If false, throw the error message.
827     Calls can be juxtaposed using function application, as `(r: r) a = a`, so
828     `(r: r) (r: r) a = a`, and so forth.
831     # Inputs
833     `cond`
835     : 1\. Function argument
837     `msg`
839     : 2\. Function argument
841     # Type
843     ```
844     bool -> string -> a -> a
845     ```
847     # Examples
848     :::{.example}
849     ## `lib.trivial.throwIfNot` usage example
851     ```nix
852     throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
853     lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
854     pkgs
855     ```
857     :::
858   */
859   throwIfNot = cond: msg: if cond then x: x else throw msg;
861   /**
862     Like throwIfNot, but negated (throw if the first argument is `true`).
865     # Inputs
867     `cond`
869     : 1\. Function argument
871     `msg`
873     : 2\. Function argument
875     # Type
877     ```
878     bool -> string -> a -> a
879     ```
880   */
881   throwIf = cond: msg: if cond then throw msg else x: x;
883   /**
884     Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
887     # Inputs
889     `msg`
891     : 1\. Function argument
893     `valid`
895     : 2\. Function argument
897     `given`
899     : 3\. Function argument
901     # Type
903     ```
904     String -> List ComparableVal -> List ComparableVal -> a -> a
905     ```
907     # Examples
908     :::{.example}
909     ## `lib.trivial.checkListOfEnum` usage example
911     ```nix
912     let colorVariants = ["bright" "dark" "black"]
913     in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
914     =>
915     error: color variants: bright, black unexpected; valid ones: standard, light, dark
916     ```
918     :::
919   */
920   checkListOfEnum = msg: valid: given:
921     let
922       unexpected = lib.subtractLists valid given;
923     in
924       lib.throwIfNot (unexpected == [])
925         "${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
927   info = msg: builtins.trace "INFO: ${msg}";
929   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
931   ## Function annotations
933   /**
934     Add metadata about expected function arguments to a function.
935     The metadata should match the format given by
936     builtins.functionArgs, i.e. a set from expected argument to a bool
937     representing whether that argument has a default or not.
938     setFunctionArgs : (a → b) → Map String Bool → (a → b)
940     This function is necessary because you can't dynamically create a
941     function of the { a, b ? foo, ... }: format, but some facilities
942     like callPackage expect to be able to query expected arguments.
945     # Inputs
947     `f`
949     : 1\. Function argument
951     `args`
953     : 2\. Function argument
954   */
955   setFunctionArgs = f: args:
956     { # TODO: Should we add call-time "type" checking like built in?
957       __functor = self: f;
958       __functionArgs = args;
959     };
961   /**
962     Extract the expected function arguments from a function.
963     This works both with nix-native { a, b ? foo, ... }: style
964     functions and functions with args set with 'setFunctionArgs'. It
965     has the same return type and semantics as builtins.functionArgs.
966     setFunctionArgs : (a → b) → Map String Bool.
969     # Inputs
971     `f`
973     : 1\. Function argument
974   */
975   functionArgs = f:
976     if f ? __functor
977     then f.__functionArgs or (functionArgs (f.__functor f))
978     else builtins.functionArgs f;
980   /**
981     Check whether something is a function or something
982     annotated with function args.
985     # Inputs
987     `f`
989     : 1\. Function argument
990   */
991   isFunction = f: builtins.isFunction f ||
992     (f ? __functor && isFunction (f.__functor f));
994   /**
995     `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
996     but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
999     # Inputs
1001     `f`
1003     : Function to provide the argument metadata
1005     `g`
1007     : Function to set the argument metadata to
1009     # Type
1011     ```
1012     mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
1013     ```
1015     # Examples
1016     :::{.example}
1017     ## `lib.trivial.mirrorFunctionArgs` usage example
1019     ```nix
1020     addab = {a, b}: a + b
1021     addab { a = 2; b = 4; }
1022     => 6
1023     lib.functionArgs addab
1024     => { a = false; b = false; }
1025     addab1 = attrs: addab attrs + 1
1026     addab1 { a = 2; b = 4; }
1027     => 7
1028     lib.functionArgs addab1
1029     => { }
1030     addab1' = lib.mirrorFunctionArgs addab addab1
1031     addab1' { a = 2; b = 4; }
1032     => 7
1033     lib.functionArgs addab1'
1034     => { a = false; b = false; }
1035     ```
1037     :::
1038   */
1039   mirrorFunctionArgs =
1040     f:
1041     let
1042       fArgs = functionArgs f;
1043     in
1044     g:
1045     setFunctionArgs g fArgs;
1047   /**
1048     Turns any non-callable values into constant functions.
1049     Returns callable values as is.
1052     # Inputs
1054     `v`
1056     : Any value
1059     # Examples
1060     :::{.example}
1061     ## `lib.trivial.toFunction` usage example
1063     ```nix
1064     nix-repl> lib.toFunction 1 2
1065     1
1067     nix-repl> lib.toFunction (x: x + 1) 2
1068     3
1069     ```
1071     :::
1072   */
1073   toFunction =
1074     v:
1075     if isFunction v
1076     then v
1077     else k: v;
1079   /**
1080     Convert a hexadecimal string to it's integer representation.
1082     # Type
1084     ```
1085     fromHexString :: String -> [ String ]
1086     ```
1088     # Examples
1090     ```nix
1091     fromHexString "FF"
1092     => 255
1094     fromHexString (builtins.hashString "sha256" "test")
1095     => 9223372036854775807
1096     ```
1097   */
1098   fromHexString = value:
1099   let
1100     noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower value);
1101   in let
1102     parsed = builtins.fromTOML "v=0x${noPrefix}";
1103   in parsed.v;
1105   /**
1106     Convert the given positive integer to a string of its hexadecimal
1107     representation. For example:
1109     toHexString 0 => "0"
1111     toHexString 16 => "10"
1113     toHexString 250 => "FA"
1114   */
1115   toHexString = let
1116     hexDigits = {
1117       "10" = "A";
1118       "11" = "B";
1119       "12" = "C";
1120       "13" = "D";
1121       "14" = "E";
1122       "15" = "F";
1123     };
1124     toHexDigit = d:
1125       if d < 10
1126       then toString d
1127       else hexDigits.${toString d};
1128   in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
1130   /**
1131     `toBaseDigits base i` converts the positive integer i to a list of its
1132     digits in the given base. For example:
1134     toBaseDigits 10 123 => [ 1 2 3 ]
1136     toBaseDigits 2 6 => [ 1 1 0 ]
1138     toBaseDigits 16 250 => [ 15 10 ]
1141     # Inputs
1143     `base`
1145     : 1\. Function argument
1147     `i`
1149     : 2\. Function argument
1150   */
1151   toBaseDigits = base: i:
1152     let
1153       go = i:
1154         if i < base
1155         then [i]
1156         else
1157           let
1158             r = i - ((i / base) * base);
1159             q = (i - r) / base;
1160           in
1161             [r] ++ go q;
1162     in
1163       assert (isInt base);
1164       assert (isInt i);
1165       assert (base >= 2);
1166       assert (i >= 0);
1167       lib.reverseList (go i);