Merge pull request #300257 from mschwaig/fix-mivisionx
[NixPkgs.git] / lib / trivial.nix
blob5b7a1ee30f7ad3190dc6006698989c6080031a45
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 in {
17   ## Simple (higher order) functions
19   /**
20     The identity function
21     For when you need a function that does “nothing”.
24     # Inputs
26     `x`
28     : The value to return
30     # Type
32     ```
33     id :: a -> a
34     ```
35   */
36   id = x: x;
38   /**
39     The constant function
41     Ignores the second argument. If called with only one argument,
42     constructs a function that always returns a static value.
45     # Inputs
47     `x`
49     : Value to return
51     `y`
53     : Value to ignore
55     # Type
57     ```
58     const :: a -> b -> a
59     ```
61     # Examples
62     :::{.example}
63     ## `lib.trivial.const` usage example
65     ```nix
66     let f = const 5; in f 10
67     => 5
68     ```
70     :::
71   */
72   const =
73     x:
74     y: x;
76   /**
77     Pipes a value through a list of functions, left to right.
79     # Inputs
81     `value`
83     : Value to start piping.
85     `fns`
87     : List of functions to apply sequentially.
89     # Type
91     ```
92     pipe :: a -> [<functions>] -> <return type of last function>
93     ```
95     # Examples
96     :::{.example}
97     ## `lib.trivial.pipe` usage example
99     ```nix
100     pipe 2 [
101         (x: x + 2)  # 2 + 2 = 4
102         (x: x * 2)  # 4 * 2 = 8
103       ]
104     => 8
106     # ideal to do text transformations
107     pipe [ "a/b" "a/c" ] [
109       # create the cp command
110       (map (file: ''cp "${src}/${file}" $out\n''))
112       # concatenate all commands into one string
113       lib.concatStrings
115       # make that string into a nix derivation
116       (pkgs.runCommand "copy-to-out" {})
118     ]
119     => <drv which copies all files to $out>
121     The output type of each function has to be the input type
122     of the next function, and the last function returns the
123     final value.
124     ```
126     :::
127   */
128   pipe = builtins.foldl' (x: f: f x);
130   # note please don’t add a function like `compose = flip pipe`.
131   # This would confuse users, because the order of the functions
132   # in the list is not clear. With pipe, it’s obvious that it
133   # goes first-to-last. With `compose`, not so much.
135   ## Named versions corresponding to some builtin operators.
137   /**
138     Concatenate two lists
141     # Inputs
143     `x`
145     : 1\. Function argument
147     `y`
149     : 2\. Function argument
151     # Type
153     ```
154     concat :: [a] -> [a] -> [a]
155     ```
157     # Examples
158     :::{.example}
159     ## `lib.trivial.concat` usage example
161     ```nix
162     concat [ 1 2 ] [ 3 4 ]
163     => [ 1 2 3 4 ]
164     ```
166     :::
167   */
168   concat = x: y: x ++ y;
170   /**
171     boolean “or”
174     # Inputs
176     `x`
178     : 1\. Function argument
180     `y`
182     : 2\. Function argument
183   */
184   or = x: y: x || y;
186   /**
187     boolean “and”
190     # Inputs
192     `x`
194     : 1\. Function argument
196     `y`
198     : 2\. Function argument
199   */
200   and = x: y: x && y;
202   /**
203     boolean “exclusive or”
206     # Inputs
208     `x`
210     : 1\. Function argument
212     `y`
214     : 2\. Function argument
215   */
216   # We explicitly invert the arguments purely as a type assertion.
217   # This is invariant under XOR, so it does not affect the result.
218   xor = x: y: (!x) != (!y);
220   /**
221     bitwise “not”
222   */
223   bitNot = builtins.sub (-1);
225   /**
226     Convert a boolean to a string.
228     This function uses the strings "true" and "false" to represent
229     boolean values. Calling `toString` on a bool instead returns "1"
230     and "" (sic!).
233     # Inputs
235     `b`
237     : 1\. Function argument
239     # Type
241     ```
242     boolToString :: bool -> string
243     ```
244   */
245   boolToString = b: if b then "true" else "false";
247   /**
248     Merge two attribute sets shallowly, right side trumps left
250     mergeAttrs :: attrs -> attrs -> attrs
253     # Inputs
255     `x`
257     : Left attribute set
259     `y`
261     : Right attribute set (higher precedence for equal keys)
264     # Examples
265     :::{.example}
266     ## `lib.trivial.mergeAttrs` usage example
268     ```nix
269     mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
270     => { a = 1; b = 3; c = 4; }
271     ```
273     :::
274   */
275   mergeAttrs =
276     x:
277     y: x // y;
279   /**
280     Flip the order of the arguments of a binary function.
283     # Inputs
285     `f`
287     : 1\. Function argument
289     `a`
291     : 2\. Function argument
293     `b`
295     : 3\. Function argument
297     # Type
299     ```
300     flip :: (a -> b -> c) -> (b -> a -> c)
301     ```
303     # Examples
304     :::{.example}
305     ## `lib.trivial.flip` usage example
307     ```nix
308     flip concat [1] [2]
309     => [ 2 1 ]
310     ```
312     :::
313   */
314   flip = f: a: b: f b a;
316   /**
317     Apply function if the supplied argument is non-null.
320     # Inputs
322     `f`
324     : Function to call
326     `a`
328     : Argument to check for null before passing it to `f`
331     # Examples
332     :::{.example}
333     ## `lib.trivial.mapNullable` usage example
335     ```nix
336     mapNullable (x: x+1) null
337     => null
338     mapNullable (x: x+1) 22
339     => 23
340     ```
342     :::
343   */
344   mapNullable =
345     f:
346     a: if a == null then a else f a;
348   # Pull in some builtins not included elsewhere.
349   inherit (builtins)
350     pathExists readFile isBool
351     isInt isFloat add sub lessThan
352     seq deepSeq genericClosure
353     bitAnd bitOr bitXor;
355   ## nixpkgs version strings
357   /**
358     Returns the current full nixpkgs version number.
359   */
360   version = release + versionSuffix;
362   /**
363     Returns the current nixpkgs release number as string.
364   */
365   release = lib.strings.fileContents ./.version;
367   /**
368     The latest release that is supported, at the time of release branch-off,
369     if applicable.
371     Ideally, out-of-tree modules should be able to evaluate cleanly with all
372     supported Nixpkgs versions (master, release and old release until EOL).
373     So if possible, deprecation warnings should take effect only when all
374     out-of-tree expressions/libs/modules can upgrade to the new way without
375     losing support for supported Nixpkgs versions.
377     This release number allows deprecation warnings to be implemented such that
378     they take effect as soon as the oldest release reaches end of life.
379   */
380   oldestSupportedRelease =
381     # Update on master only. Do not backport.
382     2311;
384   /**
385     Whether a feature is supported in all supported releases (at the time of
386     release branch-off, if applicable). See `oldestSupportedRelease`.
389     # Inputs
391     `release`
393     : Release number of feature introduction as an integer, e.g. 2111 for 21.11.
394     Set it to the upcoming release, matching the nixpkgs/.version file.
395   */
396   isInOldestRelease =
397     release:
398       release <= lib.trivial.oldestSupportedRelease;
400   /**
401     Returns the current nixpkgs release code name.
403     On each release the first letter is bumped and a new animal is chosen
404     starting with that new letter.
405   */
406   codeName = "Uakari";
408   /**
409     Returns the current nixpkgs version suffix as string.
410   */
411   versionSuffix =
412     let suffixFile = ../.version-suffix;
413     in if pathExists suffixFile
414     then lib.strings.fileContents suffixFile
415     else "pre-git";
417   /**
418     Attempts to return the the current revision of nixpkgs and
419     returns the supplied default value otherwise.
422     # Inputs
424     `default`
426     : Default value to return if revision can not be determined
428     # Type
430     ```
431     revisionWithDefault :: string -> string
432     ```
433   */
434   revisionWithDefault =
435     default:
436     let
437       revisionFile = "${toString ./..}/.git-revision";
438       gitRepo      = "${toString ./..}/.git";
439     in if lib.pathIsGitRepo gitRepo
440        then lib.commitIdFromGitRepo gitRepo
441        else if lib.pathExists revisionFile then lib.fileContents revisionFile
442        else default;
444   nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
446   /**
447     Determine whether the function is being called from inside a Nix
448     shell.
450     # Type
452     ```
453     inNixShell :: bool
454     ```
455   */
456   inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
458   /**
459     Determine whether the function is being called from inside pure-eval mode
460     by seeing whether `builtins` contains `currentSystem`. If not, we must be in
461     pure-eval mode.
463     # Type
465     ```
466     inPureEvalMode :: bool
467     ```
468   */
469   inPureEvalMode = ! builtins ? currentSystem;
471   ## Integer operations
473   /**
474     Return minimum of two numbers.
477     # Inputs
479     `x`
481     : 1\. Function argument
483     `y`
485     : 2\. Function argument
486   */
487   min = x: y: if x < y then x else y;
489   /**
490     Return maximum of two numbers.
493     # Inputs
495     `x`
497     : 1\. Function argument
499     `y`
501     : 2\. Function argument
502   */
503   max = x: y: if x > y then x else y;
505   /**
506     Integer modulus
509     # Inputs
511     `base`
513     : 1\. Function argument
515     `int`
517     : 2\. Function argument
520     # Examples
521     :::{.example}
522     ## `lib.trivial.mod` usage example
524     ```nix
525     mod 11 10
526     => 1
527     mod 1 10
528     => 1
529     ```
531     :::
532   */
533   mod = base: int: base - (int * (builtins.div base int));
536   ## Comparisons
538   /**
539     C-style comparisons
541     a < b,  compare a b => -1
542     a == b, compare a b => 0
543     a > b,  compare a b => 1
546     # Inputs
548     `a`
550     : 1\. Function argument
552     `b`
554     : 2\. Function argument
555   */
556   compare = a: b:
557     if a < b
558     then -1
559     else if a > b
560          then 1
561          else 0;
563   /**
564     Split type into two subtypes by predicate `p`, take all elements
565     of the first subtype to be less than all the elements of the
566     second subtype, compare elements of a single subtype with `yes`
567     and `no` respectively.
570     # Inputs
572     `p`
574     : Predicate
576     `yes`
578     : Comparison function if predicate holds for both values
580     `no`
582     : Comparison function if predicate holds for neither value
584     `a`
586     : First value to compare
588     `b`
590     : Second value to compare
592     # Type
594     ```
595     (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
596     ```
598     # Examples
599     :::{.example}
600     ## `lib.trivial.splitByAndCompare` usage example
602     ```nix
603     let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
605     cmp "a" "z" => -1
606     cmp "fooa" "fooz" => -1
608     cmp "f" "a" => 1
609     cmp "fooa" "a" => -1
610     # while
611     compare "fooa" "a" => 1
612     ```
614     :::
615   */
616   splitByAndCompare =
617     p: yes: no: a: b:
618     if p a
619     then if p b then yes a b else -1
620     else if p b then 1 else no a b;
623   /**
624     Reads a JSON file.
627     # Inputs
629     `path`
631     : 1\. Function argument
633     # Type
635     ```
636     importJSON :: path -> any
637     ```
638   */
639   importJSON = path:
640     builtins.fromJSON (builtins.readFile path);
642   /**
643     Reads a TOML file.
646     # Inputs
648     `path`
650     : 1\. Function argument
652     # Type
654     ```
655     importTOML :: path -> any
656     ```
657   */
658   importTOML = path:
659     builtins.fromTOML (builtins.readFile path);
661   ## Warnings
663   # See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
664   # to expand to Nix builtins that carry metadata so that Nix can filter out
665   # the INFO messages without parsing the message string.
666   #
667   # Usage:
668   # {
669   #   foo = lib.warn "foo is deprecated" oldFoo;
670   #   bar = lib.warnIf (bar == "") "Empty bar is deprecated" bar;
671   # }
672   #
673   # TODO: figure out a clever way to integrate location information from
674   # something like __unsafeGetAttrPos.
676   /**
677     Print a warning before returning the second argument. This function behaves
678     like `builtins.trace`, but requires a string message and formats it as a
679     warning, including the `warning: ` prefix.
681     To get a call stack trace and abort evaluation, set the environment variable
682     `NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
684     # Inputs
686     `msg`
688     : Warning message to print.
690     `val`
692     : Value to return as-is.
694     # Type
696     ```
697     string -> a -> a
698     ```
699   */
700   warn =
701     if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
702     then msg: builtins.trace "\e[1;31mwarning: ${msg}\e[0m" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
703     else msg: builtins.trace "\e[1;31mwarning: ${msg}\e[0m";
705   /**
706     Like warn, but only warn when the first argument is `true`.
709     # Inputs
711     `cond`
713     : 1\. Function argument
715     `msg`
717     : 2\. Function argument
719     `val`
721     : Value to return as-is.
723     # Type
725     ```
726     bool -> string -> a -> a
727     ```
728   */
729   warnIf = cond: msg: if cond then warn msg else x: x;
731   /**
732     Like warnIf, but negated (warn if the first argument is `false`).
735     # Inputs
737     `cond`
739     : 1\. Function argument
741     `msg`
743     : 2\. Function argument
745     `val`
747     : Value to return as-is.
749     # Type
751     ```
752     bool -> string -> a -> a
753     ```
754   */
755   warnIfNot = cond: msg: if cond then x: x else warn msg;
757   /**
758     Like the `assert b; e` expression, but with a custom error message and
759     without the semicolon.
761     If true, return the identity function, `r: r`.
763     If false, throw the error message.
765     Calls can be juxtaposed using function application, as `(r: r) a = a`, so
766     `(r: r) (r: r) a = a`, and so forth.
769     # Inputs
771     `cond`
773     : 1\. Function argument
775     `msg`
777     : 2\. Function argument
779     # Type
781     ```
782     bool -> string -> a -> a
783     ```
785     # Examples
786     :::{.example}
787     ## `lib.trivial.throwIfNot` usage example
789     ```nix
790     throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
791     lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
792     pkgs
793     ```
795     :::
796   */
797   throwIfNot = cond: msg: if cond then x: x else throw msg;
799   /**
800     Like throwIfNot, but negated (throw if the first argument is `true`).
803     # Inputs
805     `cond`
807     : 1\. Function argument
809     `msg`
811     : 2\. Function argument
813     # Type
815     ```
816     bool -> string -> a -> a
817     ```
818   */
819   throwIf = cond: msg: if cond then throw msg else x: x;
821   /**
822     Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
825     # Inputs
827     `msg`
829     : 1\. Function argument
831     `valid`
833     : 2\. Function argument
835     `given`
837     : 3\. Function argument
839     # Type
841     ```
842     String -> List ComparableVal -> List ComparableVal -> a -> a
843     ```
845     # Examples
846     :::{.example}
847     ## `lib.trivial.checkListOfEnum` usage example
849     ```nix
850     let colorVariants = ["bright" "dark" "black"]
851     in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
852     =>
853     error: color variants: bright, black unexpected; valid ones: standard, light, dark
854     ```
856     :::
857   */
858   checkListOfEnum = msg: valid: given:
859     let
860       unexpected = lib.subtractLists valid given;
861     in
862       lib.throwIfNot (unexpected == [])
863         "${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
865   info = msg: builtins.trace "INFO: ${msg}";
867   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
869   ## Function annotations
871   /**
872     Add metadata about expected function arguments to a function.
873     The metadata should match the format given by
874     builtins.functionArgs, i.e. a set from expected argument to a bool
875     representing whether that argument has a default or not.
876     setFunctionArgs : (a → b) → Map String Bool → (a → b)
878     This function is necessary because you can't dynamically create a
879     function of the { a, b ? foo, ... }: format, but some facilities
880     like callPackage expect to be able to query expected arguments.
883     # Inputs
885     `f`
887     : 1\. Function argument
889     `args`
891     : 2\. Function argument
892   */
893   setFunctionArgs = f: args:
894     { # TODO: Should we add call-time "type" checking like built in?
895       __functor = self: f;
896       __functionArgs = args;
897     };
899   /**
900     Extract the expected function arguments from a function.
901     This works both with nix-native { a, b ? foo, ... }: style
902     functions and functions with args set with 'setFunctionArgs'. It
903     has the same return type and semantics as builtins.functionArgs.
904     setFunctionArgs : (a → b) → Map String Bool.
907     # Inputs
909     `f`
911     : 1\. Function argument
912   */
913   functionArgs = f:
914     if f ? __functor
915     then f.__functionArgs or (functionArgs (f.__functor f))
916     else builtins.functionArgs f;
918   /**
919     Check whether something is a function or something
920     annotated with function args.
923     # Inputs
925     `f`
927     : 1\. Function argument
928   */
929   isFunction = f: builtins.isFunction f ||
930     (f ? __functor && isFunction (f.__functor f));
932   /**
933     `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
934     but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
937     # Inputs
939     `f`
941     : Function to provide the argument metadata
943     `g`
945     : Function to set the argument metadata to
947     # Type
949     ```
950     mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
951     ```
953     # Examples
954     :::{.example}
955     ## `lib.trivial.mirrorFunctionArgs` usage example
957     ```nix
958     addab = {a, b}: a + b
959     addab { a = 2; b = 4; }
960     => 6
961     lib.functionArgs addab
962     => { a = false; b = false; }
963     addab1 = attrs: addab attrs + 1
964     addab1 { a = 2; b = 4; }
965     => 7
966     lib.functionArgs addab1
967     => { }
968     addab1' = lib.mirrorFunctionArgs addab addab1
969     addab1' { a = 2; b = 4; }
970     => 7
971     lib.functionArgs addab1'
972     => { a = false; b = false; }
973     ```
975     :::
976   */
977   mirrorFunctionArgs =
978     f:
979     let
980       fArgs = functionArgs f;
981     in
982     g:
983     setFunctionArgs g fArgs;
985   /**
986     Turns any non-callable values into constant functions.
987     Returns callable values as is.
990     # Inputs
992     `v`
994     : Any value
997     # Examples
998     :::{.example}
999     ## `lib.trivial.toFunction` usage example
1001     ```nix
1002     nix-repl> lib.toFunction 1 2
1003     1
1005     nix-repl> lib.toFunction (x: x + 1) 2
1006     3
1007     ```
1009     :::
1010   */
1011   toFunction =
1012     v:
1013     if isFunction v
1014     then v
1015     else k: v;
1017   /**
1018     Convert the given positive integer to a string of its hexadecimal
1019     representation. For example:
1021     toHexString 0 => "0"
1023     toHexString 16 => "10"
1025     toHexString 250 => "FA"
1026   */
1027   toHexString = let
1028     hexDigits = {
1029       "10" = "A";
1030       "11" = "B";
1031       "12" = "C";
1032       "13" = "D";
1033       "14" = "E";
1034       "15" = "F";
1035     };
1036     toHexDigit = d:
1037       if d < 10
1038       then toString d
1039       else hexDigits.${toString d};
1040   in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
1042   /**
1043     `toBaseDigits base i` converts the positive integer i to a list of its
1044     digits in the given base. For example:
1046     toBaseDigits 10 123 => [ 1 2 3 ]
1048     toBaseDigits 2 6 => [ 1 1 0 ]
1050     toBaseDigits 16 250 => [ 15 10 ]
1053     # Inputs
1055     `base`
1057     : 1\. Function argument
1059     `i`
1061     : 2\. Function argument
1062   */
1063   toBaseDigits = base: i:
1064     let
1065       go = i:
1066         if i < base
1067         then [i]
1068         else
1069           let
1070             r = i - ((i / base) * base);
1071             q = (i - r) / base;
1072           in
1073             [r] ++ go q;
1074     in
1075       assert (isInt base);
1076       assert (isInt i);
1077       assert (base >= 2);
1078       assert (i >= 0);
1079       lib.reverseList (go i);