at 24.11-pre 19 kB view raw
1{ lib }: 2 3let 4 inherit (lib.trivial) 5 isFunction 6 isInt 7 functionArgs 8 pathExists 9 release 10 setFunctionArgs 11 toBaseDigits 12 version 13 versionSuffix 14 warn; 15in { 16 17 ## Simple (higher order) functions 18 19 /** 20 The identity function 21 For when you need a function that does nothing. 22 23 24 # Inputs 25 26 `x` 27 28 : The value to return 29 30 # Type 31 32 ``` 33 id :: a -> a 34 ``` 35 */ 36 id = x: x; 37 38 /** 39 The constant function 40 41 Ignores the second argument. If called with only one argument, 42 constructs a function that always returns a static value. 43 44 45 # Inputs 46 47 `x` 48 49 : Value to return 50 51 `y` 52 53 : Value to ignore 54 55 # Type 56 57 ``` 58 const :: a -> b -> a 59 ``` 60 61 # Examples 62 :::{.example} 63 ## `lib.trivial.const` usage example 64 65 ```nix 66 let f = const 5; in f 10 67 => 5 68 ``` 69 70 ::: 71 */ 72 const = 73 x: 74 y: x; 75 76 /** 77 Pipes a value through a list of functions, left to right. 78 79 # Inputs 80 81 `value` 82 83 : Value to start piping. 84 85 `fns` 86 87 : List of functions to apply sequentially. 88 89 # Type 90 91 ``` 92 pipe :: a -> [<functions>] -> <return type of last function> 93 ``` 94 95 # Examples 96 :::{.example} 97 ## `lib.trivial.pipe` usage example 98 99 ```nix 100 pipe 2 [ 101 (x: x + 2) # 2 + 2 = 4 102 (x: x * 2) # 4 * 2 = 8 103 ] 104 => 8 105 106 # ideal to do text transformations 107 pipe [ "a/b" "a/c" ] [ 108 109 # create the cp command 110 (map (file: ''cp "${src}/${file}" $out\n'')) 111 112 # concatenate all commands into one string 113 lib.concatStrings 114 115 # make that string into a nix derivation 116 (pkgs.runCommand "copy-to-out" {}) 117 118 ] 119 => <drv which copies all files to $out> 120 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 ``` 125 126 ::: 127 */ 128 pipe = builtins.foldl' (x: f: f x); 129 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. 134 135 ## Named versions corresponding to some builtin operators. 136 137 /** 138 Concatenate two lists 139 140 141 # Inputs 142 143 `x` 144 145 : 1\. Function argument 146 147 `y` 148 149 : 2\. Function argument 150 151 # Type 152 153 ``` 154 concat :: [a] -> [a] -> [a] 155 ``` 156 157 # Examples 158 :::{.example} 159 ## `lib.trivial.concat` usage example 160 161 ```nix 162 concat [ 1 2 ] [ 3 4 ] 163 => [ 1 2 3 4 ] 164 ``` 165 166 ::: 167 */ 168 concat = x: y: x ++ y; 169 170 /** 171 boolean or 172 173 174 # Inputs 175 176 `x` 177 178 : 1\. Function argument 179 180 `y` 181 182 : 2\. Function argument 183 */ 184 or = x: y: x || y; 185 186 /** 187 boolean and 188 189 190 # Inputs 191 192 `x` 193 194 : 1\. Function argument 195 196 `y` 197 198 : 2\. Function argument 199 */ 200 and = x: y: x && y; 201 202 /** 203 boolean exclusive or 204 205 206 # Inputs 207 208 `x` 209 210 : 1\. Function argument 211 212 `y` 213 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); 219 220 /** 221 bitwise not 222 */ 223 bitNot = builtins.sub (-1); 224 225 /** 226 Convert a boolean to a string. 227 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!). 231 232 233 # Inputs 234 235 `b` 236 237 : 1\. Function argument 238 239 # Type 240 241 ``` 242 boolToString :: bool -> string 243 ``` 244 */ 245 boolToString = b: if b then "true" else "false"; 246 247 /** 248 Merge two attribute sets shallowly, right side trumps left 249 250 mergeAttrs :: attrs -> attrs -> attrs 251 252 253 # Inputs 254 255 `x` 256 257 : Left attribute set 258 259 `y` 260 261 : Right attribute set (higher precedence for equal keys) 262 263 264 # Examples 265 :::{.example} 266 ## `lib.trivial.mergeAttrs` usage example 267 268 ```nix 269 mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; } 270 => { a = 1; b = 3; c = 4; } 271 ``` 272 273 ::: 274 */ 275 mergeAttrs = 276 x: 277 y: x // y; 278 279 /** 280 Flip the order of the arguments of a binary function. 281 282 283 # Inputs 284 285 `f` 286 287 : 1\. Function argument 288 289 `a` 290 291 : 2\. Function argument 292 293 `b` 294 295 : 3\. Function argument 296 297 # Type 298 299 ``` 300 flip :: (a -> b -> c) -> (b -> a -> c) 301 ``` 302 303 # Examples 304 :::{.example} 305 ## `lib.trivial.flip` usage example 306 307 ```nix 308 flip concat [1] [2] 309 => [ 2 1 ] 310 ``` 311 312 ::: 313 */ 314 flip = f: a: b: f b a; 315 316 /** 317 Apply function if the supplied argument is non-null. 318 319 320 # Inputs 321 322 `f` 323 324 : Function to call 325 326 `a` 327 328 : Argument to check for null before passing it to `f` 329 330 331 # Examples 332 :::{.example} 333 ## `lib.trivial.mapNullable` usage example 334 335 ```nix 336 mapNullable (x: x+1) null 337 => null 338 mapNullable (x: x+1) 22 339 => 23 340 ``` 341 342 ::: 343 */ 344 mapNullable = 345 f: 346 a: if a == null then a else f a; 347 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; 354 355 ## nixpkgs version strings 356 357 /** 358 Returns the current full nixpkgs version number. 359 */ 360 version = release + versionSuffix; 361 362 /** 363 Returns the current nixpkgs release number as string. 364 */ 365 release = lib.strings.fileContents ./.version; 366 367 /** 368 The latest release that is supported, at the time of release branch-off, 369 if applicable. 370 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. 376 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; 383 384 /** 385 Whether a feature is supported in all supported releases (at the time of 386 release branch-off, if applicable). See `oldestSupportedRelease`. 387 388 389 # Inputs 390 391 `release` 392 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; 399 400 /** 401 Returns the current nixpkgs release code name. 402 403 On each release the first letter is bumped and a new animal is chosen 404 starting with that new letter. 405 */ 406 codeName = "Vicuña"; 407 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"; 416 417 /** 418 Attempts to return the the current revision of nixpkgs and 419 returns the supplied default value otherwise. 420 421 422 # Inputs 423 424 `default` 425 426 : Default value to return if revision can not be determined 427 428 # Type 429 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; 443 444 nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version; 445 446 /** 447 Determine whether the function is being called from inside a Nix 448 shell. 449 450 # Type 451 452 ``` 453 inNixShell :: bool 454 ``` 455 */ 456 inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; 457 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. 462 463 # Type 464 465 ``` 466 inPureEvalMode :: bool 467 ``` 468 */ 469 inPureEvalMode = ! builtins ? currentSystem; 470 471 ## Integer operations 472 473 /** 474 Return minimum of two numbers. 475 476 477 # Inputs 478 479 `x` 480 481 : 1\. Function argument 482 483 `y` 484 485 : 2\. Function argument 486 */ 487 min = x: y: if x < y then x else y; 488 489 /** 490 Return maximum of two numbers. 491 492 493 # Inputs 494 495 `x` 496 497 : 1\. Function argument 498 499 `y` 500 501 : 2\. Function argument 502 */ 503 max = x: y: if x > y then x else y; 504 505 /** 506 Integer modulus 507 508 509 # Inputs 510 511 `base` 512 513 : 1\. Function argument 514 515 `int` 516 517 : 2\. Function argument 518 519 520 # Examples 521 :::{.example} 522 ## `lib.trivial.mod` usage example 523 524 ```nix 525 mod 11 10 526 => 1 527 mod 1 10 528 => 1 529 ``` 530 531 ::: 532 */ 533 mod = base: int: base - (int * (builtins.div base int)); 534 535 536 ## Comparisons 537 538 /** 539 C-style comparisons 540 541 a < b, compare a b => -1 542 a == b, compare a b => 0 543 a > b, compare a b => 1 544 545 546 # Inputs 547 548 `a` 549 550 : 1\. Function argument 551 552 `b` 553 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; 562 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. 568 569 570 # Inputs 571 572 `p` 573 574 : Predicate 575 576 `yes` 577 578 : Comparison function if predicate holds for both values 579 580 `no` 581 582 : Comparison function if predicate holds for neither value 583 584 `a` 585 586 : First value to compare 587 588 `b` 589 590 : Second value to compare 591 592 # Type 593 594 ``` 595 (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int) 596 ``` 597 598 # Examples 599 :::{.example} 600 ## `lib.trivial.splitByAndCompare` usage example 601 602 ```nix 603 let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in 604 605 cmp "a" "z" => -1 606 cmp "fooa" "fooz" => -1 607 608 cmp "f" "a" => 1 609 cmp "fooa" "a" => -1 610 # while 611 compare "fooa" "a" => 1 612 ``` 613 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; 621 622 623 /** 624 Reads a JSON file. 625 626 627 # Inputs 628 629 `path` 630 631 : 1\. Function argument 632 633 # Type 634 635 ``` 636 importJSON :: path -> any 637 ``` 638 */ 639 importJSON = path: 640 builtins.fromJSON (builtins.readFile path); 641 642 /** 643 Reads a TOML file. 644 645 646 # Inputs 647 648 `path` 649 650 : 1\. Function argument 651 652 # Type 653 654 ``` 655 importTOML :: path -> any 656 ``` 657 */ 658 importTOML = path: 659 builtins.fromTOML (builtins.readFile path); 660 661 ## Warnings 662 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. 675 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. 680 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` 683 684 # Inputs 685 686 `msg` 687 688 : Warning message to print. 689 690 `val` 691 692 : Value to return as-is. 693 694 # Type 695 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 "warning: ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.") 703 else msg: builtins.trace "warning: ${msg}"; 704 705 /** 706 Like warn, but only warn when the first argument is `true`. 707 708 709 # Inputs 710 711 `cond` 712 713 : 1\. Function argument 714 715 `msg` 716 717 : 2\. Function argument 718 719 `val` 720 721 : Value to return as-is. 722 723 # Type 724 725 ``` 726 bool -> string -> a -> a 727 ``` 728 */ 729 warnIf = cond: msg: if cond then warn msg else x: x; 730 731 /** 732 Like warnIf, but negated (warn if the first argument is `false`). 733 734 735 # Inputs 736 737 `cond` 738 739 : 1\. Function argument 740 741 `msg` 742 743 : 2\. Function argument 744 745 `val` 746 747 : Value to return as-is. 748 749 # Type 750 751 ``` 752 bool -> string -> a -> a 753 ``` 754 */ 755 warnIfNot = cond: msg: if cond then x: x else warn msg; 756 757 /** 758 Like the `assert b; e` expression, but with a custom error message and 759 without the semicolon. 760 761 If true, return the identity function, `r: r`. 762 763 If false, throw the error message. 764 765 Calls can be juxtaposed using function application, as `(r: r) a = a`, so 766 `(r: r) (r: r) a = a`, and so forth. 767 768 769 # Inputs 770 771 `cond` 772 773 : 1\. Function argument 774 775 `msg` 776 777 : 2\. Function argument 778 779 # Type 780 781 ``` 782 bool -> string -> a -> a 783 ``` 784 785 # Examples 786 :::{.example} 787 ## `lib.trivial.throwIfNot` usage example 788 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 ``` 794 795 ::: 796 */ 797 throwIfNot = cond: msg: if cond then x: x else throw msg; 798 799 /** 800 Like throwIfNot, but negated (throw if the first argument is `true`). 801 802 803 # Inputs 804 805 `cond` 806 807 : 1\. Function argument 808 809 `msg` 810 811 : 2\. Function argument 812 813 # Type 814 815 ``` 816 bool -> string -> a -> a 817 ``` 818 */ 819 throwIf = cond: msg: if cond then throw msg else x: x; 820 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. 823 824 825 # Inputs 826 827 `msg` 828 829 : 1\. Function argument 830 831 `valid` 832 833 : 2\. Function argument 834 835 `given` 836 837 : 3\. Function argument 838 839 # Type 840 841 ``` 842 String -> List ComparableVal -> List ComparableVal -> a -> a 843 ``` 844 845 # Examples 846 :::{.example} 847 ## `lib.trivial.checkListOfEnum` usage example 848 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 ``` 855 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)}"; 864 865 info = msg: builtins.trace "INFO: ${msg}"; 866 867 showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings; 868 869 ## Function annotations 870 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) 877 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. 881 882 883 # Inputs 884 885 `f` 886 887 : 1\. Function argument 888 889 `args` 890 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 }; 898 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. 905 906 907 # Inputs 908 909 `f` 910 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; 917 918 /** 919 Check whether something is a function or something 920 annotated with function args. 921 922 923 # Inputs 924 925 `f` 926 927 : 1\. Function argument 928 */ 929 isFunction = f: builtins.isFunction f || 930 (f ? __functor && isFunction (f.__functor f)); 931 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`). 935 936 937 # Inputs 938 939 `f` 940 941 : Function to provide the argument metadata 942 943 `g` 944 945 : Function to set the argument metadata to 946 947 # Type 948 949 ``` 950 mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c) 951 ``` 952 953 # Examples 954 :::{.example} 955 ## `lib.trivial.mirrorFunctionArgs` usage example 956 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 ``` 974 975 ::: 976 */ 977 mirrorFunctionArgs = 978 f: 979 let 980 fArgs = functionArgs f; 981 in 982 g: 983 setFunctionArgs g fArgs; 984 985 /** 986 Turns any non-callable values into constant functions. 987 Returns callable values as is. 988 989 990 # Inputs 991 992 `v` 993 994 : Any value 995 996 997 # Examples 998 :::{.example} 999 ## `lib.trivial.toFunction` usage example 1000 1001 ```nix 1002 nix-repl> lib.toFunction 1 2 1003 1 1004 1005 nix-repl> lib.toFunction (x: x + 1) 2 1006 3 1007 ``` 1008 1009 ::: 1010 */ 1011 toFunction = 1012 v: 1013 if isFunction v 1014 then v 1015 else k: v; 1016 1017 /** 1018 Convert the given positive integer to a string of its hexadecimal 1019 representation. For example: 1020 1021 toHexString 0 => "0" 1022 1023 toHexString 16 => "10" 1024 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); 1041 1042 /** 1043 `toBaseDigits base i` converts the positive integer i to a list of its 1044 digits in the given base. For example: 1045 1046 toBaseDigits 10 123 => [ 1 2 3 ] 1047 1048 toBaseDigits 2 6 => [ 1 1 0 ] 1049 1050 toBaseDigits 16 250 => [ 15 10 ] 1051 1052 1053 # Inputs 1054 1055 `base` 1056 1057 : 1\. Function argument 1058 1059 `i` 1060 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); 1080}