opencomposite: add meta.platforms (#357198)
[NixPkgs.git] / lib / trivial.nix
blob04fb9ffd46180b3b98cf6b92787f9e903825b48b
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     lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2411)
401       "lib.isInOldestRelease is deprecated. Use lib.oldestSupportedReleaseIsAtLeast instead."
402     lib.oldestSupportedReleaseIsAtLeast;
404   /**
405     Alias for `isInOldestRelease` introduced in 24.11.
406     Use `isInOldestRelease` in expressions outside of Nixpkgs for greater compatibility.
407    */
408   oldestSupportedReleaseIsAtLeast =
409     release:
410       release <= lib.trivial.oldestSupportedRelease;
412   /**
413     Returns the current nixpkgs release code name.
415     On each release the first letter is bumped and a new animal is chosen
416     starting with that new letter.
417   */
418   codeName = "Warbler";
420   /**
421     Returns the current nixpkgs version suffix as string.
422   */
423   versionSuffix =
424     let suffixFile = ../.version-suffix;
425     in if pathExists suffixFile
426     then lib.strings.fileContents suffixFile
427     else "pre-git";
429   /**
430     Attempts to return the the current revision of nixpkgs and
431     returns the supplied default value otherwise.
434     # Inputs
436     `default`
438     : Default value to return if revision can not be determined
440     # Type
442     ```
443     revisionWithDefault :: string -> string
444     ```
445   */
446   revisionWithDefault =
447     default:
448     let
449       revisionFile = "${toString ./..}/.git-revision";
450       gitRepo      = "${toString ./..}/.git";
451     in if lib.pathIsGitRepo gitRepo
452        then lib.commitIdFromGitRepo gitRepo
453        else if lib.pathExists revisionFile then lib.fileContents revisionFile
454        else default;
456   nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
458   /**
459     Determine whether the function is being called from inside a Nix
460     shell.
462     # Type
464     ```
465     inNixShell :: bool
466     ```
467   */
468   inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
470   /**
471     Determine whether the function is being called from inside pure-eval mode
472     by seeing whether `builtins` contains `currentSystem`. If not, we must be in
473     pure-eval mode.
475     # Type
477     ```
478     inPureEvalMode :: bool
479     ```
480   */
481   inPureEvalMode = ! builtins ? currentSystem;
483   ## Integer operations
485   /**
486     Return minimum of two numbers.
489     # Inputs
491     `x`
493     : 1\. Function argument
495     `y`
497     : 2\. Function argument
498   */
499   min = x: y: if x < y then x else y;
501   /**
502     Return maximum of two numbers.
505     # Inputs
507     `x`
509     : 1\. Function argument
511     `y`
513     : 2\. Function argument
514   */
515   max = x: y: if x > y then x else y;
517   /**
518     Integer modulus
521     # Inputs
523     `base`
525     : 1\. Function argument
527     `int`
529     : 2\. Function argument
532     # Examples
533     :::{.example}
534     ## `lib.trivial.mod` usage example
536     ```nix
537     mod 11 10
538     => 1
539     mod 1 10
540     => 1
541     ```
543     :::
544   */
545   mod = base: int: base - (int * (builtins.div base int));
548   ## Comparisons
550   /**
551     C-style comparisons
553     a < b,  compare a b => -1
554     a == b, compare a b => 0
555     a > b,  compare a b => 1
558     # Inputs
560     `a`
562     : 1\. Function argument
564     `b`
566     : 2\. Function argument
567   */
568   compare = a: b:
569     if a < b
570     then -1
571     else if a > b
572          then 1
573          else 0;
575   /**
576     Split type into two subtypes by predicate `p`, take all elements
577     of the first subtype to be less than all the elements of the
578     second subtype, compare elements of a single subtype with `yes`
579     and `no` respectively.
582     # Inputs
584     `p`
586     : Predicate
588     `yes`
590     : Comparison function if predicate holds for both values
592     `no`
594     : Comparison function if predicate holds for neither value
596     `a`
598     : First value to compare
600     `b`
602     : Second value to compare
604     # Type
606     ```
607     (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
608     ```
610     # Examples
611     :::{.example}
612     ## `lib.trivial.splitByAndCompare` usage example
614     ```nix
615     let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
617     cmp "a" "z" => -1
618     cmp "fooa" "fooz" => -1
620     cmp "f" "a" => 1
621     cmp "fooa" "a" => -1
622     # while
623     compare "fooa" "a" => 1
624     ```
626     :::
627   */
628   splitByAndCompare =
629     p: yes: no: a: b:
630     if p a
631     then if p b then yes a b else -1
632     else if p b then 1 else no a b;
635   /**
636     Reads a JSON file.
638     # Examples
639     :::{.example}
640     ## `lib.trivial.importJSON` usage example
642     example.json
643     ```json
644     {
645       "title": "Example JSON",
646       "hello": {
647         "world": "foo",
648         "bar": {
649           "foobar": true
650         }
651       }
652     }
653     ```
655     ```nix
656     importJSON ./example.json
657     => {
658       title = "Example JSON";
659       hello = {
660         world = "foo";
661         bar = {
662           foobar = true;
663         };
664       };
665     }
666     ```
668     :::
670     # Inputs
672     `path`
674     : 1\. Function argument
676     # Type
678     ```
679     importJSON :: path -> any
680     ```
681   */
682   importJSON = path:
683     builtins.fromJSON (builtins.readFile path);
685   /**
686     Reads a TOML file.
688     # Examples
689     :::{.example}
690     ## `lib.trivial.importTOML` usage example
692     example.toml
693     ```toml
694     title = "TOML Example"
696     [hello]
697     world = "foo"
699     [hello.bar]
700     foobar = true
701     ```
703     ```nix
704     importTOML ./example.toml
705     => {
706       title = "TOML Example";
707       hello = {
708         world = "foo";
709         bar = {
710           foobar = true;
711         };
712       };
713     }
714     ```
716     :::
718     # Inputs
720     `path`
722     : 1\. Function argument
724     # Type
726     ```
727     importTOML :: path -> any
728     ```
729   */
730   importTOML = path:
731     builtins.fromTOML (builtins.readFile path);
733   /**
735     `warn` *`message`* *`value`*
737     Print a warning before returning the second argument.
739     See [`builtins.warn`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn) (Nix >= 2.23).
740     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.
742     # Inputs
744     *`message`* (String)
746     : Warning message to print before evaluating *`value`*.
748     *`value`* (any value)
750     : Value to return as-is.
752     # Type
754     ```
755     String -> a -> a
756     ```
757   */
758   warn =
759     # Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
760     builtins.warn or (
761       let mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"];
762       in
763         # Do not eta reduce v, so that we have the same strictness as `builtins.warn`.
764         msg: v:
765           # `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions.
766           assert isString msg;
767           if mustAbort
768           then builtins.trace "\e[1;31mevaluation warning:\e[0m ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
769           else builtins.trace "\e[1;35mevaluation warning:\e[0m ${msg}" v
770     );
772   /**
774     `warnIf` *`condition`* *`message`* *`value`*
776     Like `warn`, but only warn when the first argument is `true`.
778     # Inputs
780     *`condition`* (Boolean)
782     : `true` to trigger the warning before continuing with *`value`*.
784     *`message`* (String)
786     : Warning message to print before evaluating
788     *`value`* (any value)
790     : Value to return as-is.
792     # Type
794     ```
795     Bool -> String -> a -> a
796     ```
797   */
798   warnIf = cond: msg: if cond then warn msg else x: x;
800   /**
802     `warnIfNot` *`condition`* *`message`* *`value`*
804     Like `warnIf`, but negated: warn if the first argument is `false`.
806     # Inputs
808     *`condition`*
810     : `false` to trigger the warning before continuing with `val`.
812     *`message`*
814     : Warning message to print before evaluating *`value`*.
816     *`value`*
818     : Value to return as-is.
820     # Type
822     ```
823     Boolean -> String -> a -> a
824     ```
825   */
826   warnIfNot = cond: msg: if cond then x: x else warn msg;
828   /**
829     Like the `assert b; e` expression, but with a custom error message and
830     without the semicolon.
832     If true, return the identity function, `r: r`.
834     If false, throw the error message.
836     Calls can be juxtaposed using function application, as `(r: r) a = a`, so
837     `(r: r) (r: r) a = a`, and so forth.
840     # Inputs
842     `cond`
844     : 1\. Function argument
846     `msg`
848     : 2\. Function argument
850     # Type
852     ```
853     bool -> string -> a -> a
854     ```
856     # Examples
857     :::{.example}
858     ## `lib.trivial.throwIfNot` usage example
860     ```nix
861     throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
862     lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
863     pkgs
864     ```
866     :::
867   */
868   throwIfNot = cond: msg: if cond then x: x else throw msg;
870   /**
871     Like throwIfNot, but negated (throw if the first argument is `true`).
874     # Inputs
876     `cond`
878     : 1\. Function argument
880     `msg`
882     : 2\. Function argument
884     # Type
886     ```
887     bool -> string -> a -> a
888     ```
889   */
890   throwIf = cond: msg: if cond then throw msg else x: x;
892   /**
893     Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
896     # Inputs
898     `msg`
900     : 1\. Function argument
902     `valid`
904     : 2\. Function argument
906     `given`
908     : 3\. Function argument
910     # Type
912     ```
913     String -> List ComparableVal -> List ComparableVal -> a -> a
914     ```
916     # Examples
917     :::{.example}
918     ## `lib.trivial.checkListOfEnum` usage example
920     ```nix
921     let colorVariants = ["bright" "dark" "black"]
922     in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
923     =>
924     error: color variants: bright, black unexpected; valid ones: standard, light, dark
925     ```
927     :::
928   */
929   checkListOfEnum = msg: valid: given:
930     let
931       unexpected = lib.subtractLists valid given;
932     in
933       lib.throwIfNot (unexpected == [])
934         "${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
936   info = msg: builtins.trace "INFO: ${msg}";
938   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
940   ## Function annotations
942   /**
943     Add metadata about expected function arguments to a function.
944     The metadata should match the format given by
945     builtins.functionArgs, i.e. a set from expected argument to a bool
946     representing whether that argument has a default or not.
947     setFunctionArgs : (a → b) → Map String Bool → (a → b)
949     This function is necessary because you can't dynamically create a
950     function of the { a, b ? foo, ... }: format, but some facilities
951     like callPackage expect to be able to query expected arguments.
954     # Inputs
956     `f`
958     : 1\. Function argument
960     `args`
962     : 2\. Function argument
963   */
964   setFunctionArgs = f: args:
965     { # TODO: Should we add call-time "type" checking like built in?
966       __functor = self: f;
967       __functionArgs = args;
968     };
970   /**
971     Extract the expected function arguments from a function.
972     This works both with nix-native { a, b ? foo, ... }: style
973     functions and functions with args set with 'setFunctionArgs'. It
974     has the same return type and semantics as builtins.functionArgs.
975     setFunctionArgs : (a → b) → Map String Bool.
978     # Inputs
980     `f`
982     : 1\. Function argument
983   */
984   functionArgs = f:
985     if f ? __functor
986     then f.__functionArgs or (functionArgs (f.__functor f))
987     else builtins.functionArgs f;
989   /**
990     Check whether something is a function or something
991     annotated with function args.
994     # Inputs
996     `f`
998     : 1\. Function argument
999   */
1000   isFunction = f: builtins.isFunction f ||
1001     (f ? __functor && isFunction (f.__functor f));
1003   /**
1004     `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
1005     but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
1008     # Inputs
1010     `f`
1012     : Function to provide the argument metadata
1014     `g`
1016     : Function to set the argument metadata to
1018     # Type
1020     ```
1021     mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
1022     ```
1024     # Examples
1025     :::{.example}
1026     ## `lib.trivial.mirrorFunctionArgs` usage example
1028     ```nix
1029     addab = {a, b}: a + b
1030     addab { a = 2; b = 4; }
1031     => 6
1032     lib.functionArgs addab
1033     => { a = false; b = false; }
1034     addab1 = attrs: addab attrs + 1
1035     addab1 { a = 2; b = 4; }
1036     => 7
1037     lib.functionArgs addab1
1038     => { }
1039     addab1' = lib.mirrorFunctionArgs addab addab1
1040     addab1' { a = 2; b = 4; }
1041     => 7
1042     lib.functionArgs addab1'
1043     => { a = false; b = false; }
1044     ```
1046     :::
1047   */
1048   mirrorFunctionArgs =
1049     f:
1050     let
1051       fArgs = functionArgs f;
1052     in
1053     g:
1054     setFunctionArgs g fArgs;
1056   /**
1057     Turns any non-callable values into constant functions.
1058     Returns callable values as is.
1061     # Inputs
1063     `v`
1065     : Any value
1068     # Examples
1069     :::{.example}
1070     ## `lib.trivial.toFunction` usage example
1072     ```nix
1073     nix-repl> lib.toFunction 1 2
1074     1
1076     nix-repl> lib.toFunction (x: x + 1) 2
1077     3
1078     ```
1080     :::
1081   */
1082   toFunction =
1083     v:
1084     if isFunction v
1085     then v
1086     else k: v;
1088   /**
1089     Convert a hexadecimal string to it's integer representation.
1091     # Type
1093     ```
1094     fromHexString :: String -> [ String ]
1095     ```
1097     # Examples
1099     ```nix
1100     fromHexString "FF"
1101     => 255
1103     fromHexString (builtins.hashString "sha256" "test")
1104     => 9223372036854775807
1105     ```
1106   */
1107   fromHexString = value:
1108   let
1109     noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower value);
1110   in let
1111     parsed = builtins.fromTOML "v=0x${noPrefix}";
1112   in parsed.v;
1114   /**
1115     Convert the given positive integer to a string of its hexadecimal
1116     representation. For example:
1118     toHexString 0 => "0"
1120     toHexString 16 => "10"
1122     toHexString 250 => "FA"
1123   */
1124   toHexString = let
1125     hexDigits = {
1126       "10" = "A";
1127       "11" = "B";
1128       "12" = "C";
1129       "13" = "D";
1130       "14" = "E";
1131       "15" = "F";
1132     };
1133     toHexDigit = d:
1134       if d < 10
1135       then toString d
1136       else hexDigits.${toString d};
1137   in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
1139   /**
1140     `toBaseDigits base i` converts the positive integer i to a list of its
1141     digits in the given base. For example:
1143     toBaseDigits 10 123 => [ 1 2 3 ]
1145     toBaseDigits 2 6 => [ 1 1 0 ]
1147     toBaseDigits 16 250 => [ 15 10 ]
1150     # Inputs
1152     `base`
1154     : 1\. Function argument
1156     `i`
1158     : 2\. Function argument
1159   */
1160   toBaseDigits = base: i:
1161     let
1162       go = i:
1163         if i < base
1164         then [i]
1165         else
1166           let
1167             r = i - ((i / base) * base);
1168             q = (i - r) / base;
1169           in
1170             [r] ++ go q;
1171     in
1172       assert (isInt base);
1173       assert (isInt i);
1174       assert (base >= 2);
1175       assert (i >= 0);
1176       lib.reverseList (go i);