feat(users/sterni/nix/string): very simple printf implementation
This is mostly to yet another silly idea which turns out to be possible. This may be actually useful should I implement more sophisticated format specifiers like "%xd" or "%f". Change-Id: Ia56cd6f5793a09fe5e19c91a8e8f9098f3244d57 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3537 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
2f750e4a14
commit
e507b84291
2 changed files with 45 additions and 0 deletions
|
@ -59,6 +59,43 @@ let
|
|||
# pattern matching for strings only
|
||||
match = val: matcher: matcher."${val}";
|
||||
|
||||
/* Bare-bones printf implementation. Supported format specifiers:
|
||||
|
||||
* `%%` escapes `%`
|
||||
* `%s` is substituted by a string
|
||||
|
||||
As expected, the first argument is a format string and the values
|
||||
for its format specifiers need to provided as the next arguments
|
||||
in order.
|
||||
|
||||
Type: string -> (printfVal : either string (a -> printfVal))
|
||||
*/
|
||||
printf = formatString:
|
||||
let
|
||||
specifierWithArg = token: builtins.elem token [
|
||||
"%s"
|
||||
];
|
||||
isSpecifier = lib.hasPrefix "%";
|
||||
|
||||
tokens = lib.flatten (builtins.split "(%.)" formatString);
|
||||
argsNeeded = builtins.length (builtins.filter specifierWithArg tokens);
|
||||
|
||||
format = args: (builtins.foldl' ({ out ? "", argIndex ? 0 }: token: {
|
||||
argIndex = argIndex + (if specifierWithArg token then 1 else 0);
|
||||
out =
|
||||
/**/ if token == "%s" then out + builtins.elemAt args argIndex
|
||||
else if token == "%%" then out + "%"
|
||||
else if isSpecifier token then throw "Unsupported format specifier ${token}"
|
||||
else out + token;
|
||||
}) {} tokens).out;
|
||||
|
||||
accumulateArgs = argCount: args:
|
||||
if argCount > 0
|
||||
then arg: accumulateArgs (argCount - 1) (args ++ [ arg ])
|
||||
else format args;
|
||||
in
|
||||
accumulateArgs argsNeeded [];
|
||||
|
||||
in {
|
||||
inherit
|
||||
take
|
||||
|
@ -72,5 +109,6 @@ in {
|
|||
pad
|
||||
fit
|
||||
match
|
||||
printf
|
||||
;
|
||||
}
|
||||
|
|
|
@ -56,10 +56,17 @@ let
|
|||
}))
|
||||
];
|
||||
|
||||
f = "f";
|
||||
testPrintf = it "prints f" [
|
||||
(assertEq "basic %s usage" "print ${f}" (string.printf "print %s" f))
|
||||
(assertEq "% escaping" "100%" (string.printf "100%%"))
|
||||
];
|
||||
|
||||
in
|
||||
runTestsuite "nix.string" [
|
||||
testTakeDrop
|
||||
testIndexing
|
||||
testFinding
|
||||
testMatch
|
||||
testPrintf
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue