Skip to content

Commit

Permalink
lib: add defaultTo
Browse files Browse the repository at this point in the history
  • Loading branch information
szlend committed Dec 1, 2024
1 parent 2468db7 commit 23d8372
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 48 deletions.
2 changes: 1 addition & 1 deletion lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ let
# these are the only ones that are currently not
inherit (builtins) addErrorContext isPath trace typeOf unsafeGetAttrPos;
inherit (self.trivial) id const pipe concat or and xor bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
bitNot boolToString mergeAttrs flip defaultTo mapNullable inNixShell isFloat min max
importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum
info showWarnings nixpkgsVersion version isInOldestRelease oldestSupportedReleaseIsAtLeast
mod compare splitByAndCompare seq deepSeq lessThan add sub
Expand Down
135 changes: 88 additions & 47 deletions lib/trivial.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ let
inherit (lib)
isString
;
in {
in
{

## Simple (higher order) functions

Expand Down Expand Up @@ -316,6 +317,40 @@ in {
*/
flip = f: a: b: f b a;

/**
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 "default" null
=> "default"
defaultTo "default" "foo"
=> "foo"
defaultTo "default" false
=> false
```
:::
*/
defaultTo = default: maybeValue:
if maybeValue != null then maybeValue
else default;

/**
Apply function if the supplied argument is non-null.
Expand Down Expand Up @@ -399,15 +434,15 @@ in {
isInOldestRelease =
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2411)
"lib.isInOldestRelease is deprecated. Use lib.oldestSupportedReleaseIsAtLeast instead."
lib.oldestSupportedReleaseIsAtLeast;
lib.oldestSupportedReleaseIsAtLeast;

/**
Alias for `isInOldestRelease` introduced in 24.11.
Use `isInOldestRelease` in expressions outside of Nixpkgs for greater compatibility.
*/
oldestSupportedReleaseIsAtLeast =
release:
release <= lib.trivial.oldestSupportedRelease;
release <= lib.trivial.oldestSupportedRelease;

/**
Returns the current nixpkgs release code name.
Expand Down Expand Up @@ -447,11 +482,12 @@ in {
default:
let
revisionFile = "${toString ./..}/.git-revision";
gitRepo = "${toString ./..}/.git";
in if lib.pathIsGitRepo gitRepo
then lib.commitIdFromGitRepo gitRepo
else if lib.pathExists revisionFile then lib.fileContents revisionFile
else default;
gitRepo = "${toString ./..}/.git";
in
if lib.pathIsGitRepo gitRepo
then lib.commitIdFromGitRepo gitRepo
else if lib.pathExists revisionFile then lib.fileContents revisionFile
else default;

nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;

Expand Down Expand Up @@ -569,8 +605,8 @@ in {
if a < b
then -1
else if a > b
then 1
else 0;
then 1
else 0;

/**
Split type into two subtypes by predicate `p`, take all elements
Expand Down Expand Up @@ -758,15 +794,15 @@ in {
warn =
# Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
builtins.warn or (
let mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"];
let mustAbort = lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ "1" "true" "yes" ];
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
then builtins.trace "[1;31mevaluation warning:[0m ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
else builtins.trace "[1;35mevaluation warning:[0m ${msg}" v
# 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
then builtins.trace "[1;31mevaluation warning:[0m ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
else builtins.trace "[1;35mevaluation warning:[0m ${msg}" v
);

/**
Expand Down Expand Up @@ -930,8 +966,8 @@ in {
let
unexpected = lib.subtractLists valid given;
in
lib.throwIfNot (unexpected == [])
"${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
lib.throwIfNot (unexpected == [ ])
"${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";

info = msg: builtins.trace "INFO: ${msg}";

Expand Down Expand Up @@ -962,7 +998,8 @@ in {
: 2\. Function argument
*/
setFunctionArgs = f: args:
{ # TODO: Should we add call-time "type" checking like built in?
{
# TODO: Should we add call-time "type" checking like built in?
__functor = self: f;
__functionArgs = args;
};
Expand Down Expand Up @@ -1105,11 +1142,13 @@ in {
```
*/
fromHexString = value:
let
noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower value);
in let
parsed = builtins.fromTOML "v=0x${noPrefix}";
in parsed.v;
let
noPrefix = lib.strings.removePrefix "0x" (lib.strings.toLower value);
in
let
parsed = builtins.fromTOML "v=0x${noPrefix}";
in
parsed.v;

/**
Convert the given positive integer to a string of its hexadecimal
Expand All @@ -1121,20 +1160,22 @@ in {
toHexString 250 => "FA"
*/
toHexString = let
hexDigits = {
"10" = "A";
"11" = "B";
"12" = "C";
"13" = "D";
"14" = "E";
"15" = "F";
};
toHexDigit = d:
if d < 10
then toString d
else hexDigits.${toString d};
in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
toHexString =
let
hexDigits = {
"10" = "A";
"11" = "B";
"12" = "C";
"13" = "D";
"14" = "E";
"15" = "F";
};
toHexDigit = d:
if d < 10
then toString d
else hexDigits.${toString d};
in
i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);

/**
`toBaseDigits base i` converts the positive integer i to a list of its
Expand All @@ -1161,17 +1202,17 @@ in {
let
go = i:
if i < base
then [i]
then [ i ]
else
let
r = i - ((i / base) * base);
q = (i - r) / base;
in
[r] ++ go q;
[ r ] ++ go q;
in
assert (isInt base);
assert (isInt i);
assert (base >= 2);
assert (i >= 0);
lib.reverseList (go i);
assert (isInt base);
assert (isInt i);
assert (base >= 2);
assert (i >= 0);
lib.reverseList (go i);
}

0 comments on commit 23d8372

Please sign in to comment.