lib/cli: add toCommandLine
This commit is contained in:
@@ -360,3 +360,5 @@
|
|||||||
See the neovim help page [`:help startup`](https://neovim.io/doc/user/starting.html#startup) for more information, as well as [the nixpkgs neovim wrapper documentation](#neovim-custom-configuration).
|
See the neovim help page [`:help startup`](https://neovim.io/doc/user/starting.html#startup) for more information, as well as [the nixpkgs neovim wrapper documentation](#neovim-custom-configuration).
|
||||||
|
|
||||||
- `cloudflare-ddns`: Added package cloudflare-ddns.
|
- `cloudflare-ddns`: Added package cloudflare-ddns.
|
||||||
|
|
||||||
|
- `lib.cli.toCommandLine`, `lib.cli.toCommandLineShell`, `lib.cli.toCommandLineGNU` and `lib.cli.toCommandLineShellGNU` have been added to address multiple issues in `lib.cli.toGNUCommandLine` and `lib.cli.toGNUCommandLineShell`.
|
||||||
|
|||||||
191
lib/cli.nix
191
lib/cli.nix
@@ -1,6 +1,6 @@
|
|||||||
{ lib }:
|
{ lib }:
|
||||||
|
|
||||||
rec {
|
{
|
||||||
/**
|
/**
|
||||||
Automatically convert an attribute set to command-line options.
|
Automatically convert an attribute set to command-line options.
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ rec {
|
|||||||
: The attributes to transform into arguments.
|
: The attributes to transform into arguments.
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
:::{.example}
|
:::{.example}
|
||||||
## `lib.cli.toGNUCommandLineShell` usage example
|
## `lib.cli.toGNUCommandLineShell` usage example
|
||||||
|
|
||||||
@@ -38,7 +39,8 @@ rec {
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
*/
|
*/
|
||||||
toGNUCommandLineShell = options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
|
toGNUCommandLineShell =
|
||||||
|
options: attrs: lib.escapeShellArgs (lib.cli.toGNUCommandLine options attrs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Automatically convert an attribute set to a list of command-line options.
|
Automatically convert an attribute set to a list of command-line options.
|
||||||
@@ -55,7 +57,7 @@ rec {
|
|||||||
|
|
||||||
: The attributes to transform into arguments.
|
: The attributes to transform into arguments.
|
||||||
|
|
||||||
# Options
|
## Options
|
||||||
|
|
||||||
`mkOptionName`
|
`mkOptionName`
|
||||||
|
|
||||||
@@ -85,6 +87,7 @@ rec {
|
|||||||
This is useful if the command requires equals, for example, `-c=5`.
|
This is useful if the command requires equals, for example, `-c=5`.
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
:::{.example}
|
:::{.example}
|
||||||
## `lib.cli.toGNUCommandLine` usage example
|
## `lib.cli.toGNUCommandLine` usage example
|
||||||
|
|
||||||
@@ -145,4 +148,186 @@ rec {
|
|||||||
|
|
||||||
in
|
in
|
||||||
builtins.concatLists (lib.mapAttrsToList render options);
|
builtins.concatLists (lib.mapAttrsToList render options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts the given attributes into a single shell-escaped command-line string.
|
||||||
|
Similar to `toCommandLineGNU`, but returns a single escaped string instead of an array of arguments.
|
||||||
|
For further reference see: [`lib.cli.toCommandLineGNU`](#function-library-lib.cli.toCommandLineGNU)
|
||||||
|
*/
|
||||||
|
toCommandLineShellGNU =
|
||||||
|
options: attrs: lib.escapeShellArgs (lib.cli.toCommandLineGNU options attrs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an attribute set into a list of GNU-style command line options.
|
||||||
|
|
||||||
|
`toCommandLineGNU` returns a list of string arguments.
|
||||||
|
|
||||||
|
# Inputs
|
||||||
|
|
||||||
|
`options`
|
||||||
|
|
||||||
|
: Options, see below.
|
||||||
|
|
||||||
|
`attrs`
|
||||||
|
|
||||||
|
: The attributes to transform into arguments.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
`isLong`
|
||||||
|
|
||||||
|
: A function that determines whether an option is long or short.
|
||||||
|
|
||||||
|
`explicitBool`
|
||||||
|
|
||||||
|
: Whether or not boolean option arguments should be formatted explicitly.
|
||||||
|
|
||||||
|
`formatArg`
|
||||||
|
|
||||||
|
: A function that turns the option argument into a string.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
:::{.example}
|
||||||
|
## `lib.cli.toCommandLineGNU` usage example
|
||||||
|
|
||||||
|
```nix
|
||||||
|
lib.cli.toCommandLineGNU {} {
|
||||||
|
v = true;
|
||||||
|
verbose = [true true false null];
|
||||||
|
i = ".bak";
|
||||||
|
testsuite = ["unit" "integration"];
|
||||||
|
e = ["s/a/b/" "s/b/c/"];
|
||||||
|
n = false;
|
||||||
|
data = builtins.toJSON {id = 0;};
|
||||||
|
}
|
||||||
|
=> [
|
||||||
|
"--data={\"id\":0}"
|
||||||
|
"-es/a/b/"
|
||||||
|
"-es/b/c/"
|
||||||
|
"-i.bak"
|
||||||
|
"--testsuite=unit"
|
||||||
|
"--testsuite=integration"
|
||||||
|
"-v"
|
||||||
|
"--verbose"
|
||||||
|
"--verbose"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
*/
|
||||||
|
toCommandLineGNU =
|
||||||
|
{
|
||||||
|
isLong ? optionName: builtins.stringLength optionName > 1,
|
||||||
|
explicitBool ? false,
|
||||||
|
formatArg ? lib.generators.mkValueStringDefault { },
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
optionFormat = optionName: {
|
||||||
|
option = if isLong optionName then "--${optionName}" else "-${optionName}";
|
||||||
|
sep = if isLong optionName then "=" else "";
|
||||||
|
inherit explicitBool formatArg;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.cli.toCommandLine optionFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts the given attributes into a single shell-escaped command-line string.
|
||||||
|
Similar to `toCommandLine`, but returns a single escaped string instead of an array of arguments.
|
||||||
|
For further reference see: [`lib.cli.toCommandLine`](#function-library-lib.cli.toCommandLine)
|
||||||
|
*/
|
||||||
|
toCommandLineShell =
|
||||||
|
optionFormat: attrs: lib.escapeShellArgs (lib.cli.toCommandLine optionFormat attrs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an attribute set into a list of command line options.
|
||||||
|
|
||||||
|
`toCommandLine` returns a list of string arguments.
|
||||||
|
|
||||||
|
# Inputs
|
||||||
|
|
||||||
|
`optionFormat`
|
||||||
|
|
||||||
|
: The option format that describes how options and their arguments should be formatted.
|
||||||
|
|
||||||
|
`attrs`
|
||||||
|
|
||||||
|
: The attributes to transform into arguments.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
:::{.example}
|
||||||
|
## `lib.cli.toCommandLine` usage example
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
optionFormat = optionName: {
|
||||||
|
option = "-${optionName}";
|
||||||
|
sep = "=";
|
||||||
|
explicitBool = true;
|
||||||
|
};
|
||||||
|
in lib.cli.toCommandLine optionFormat {
|
||||||
|
v = true;
|
||||||
|
verbose = [true true false null];
|
||||||
|
i = ".bak";
|
||||||
|
testsuite = ["unit" "integration"];
|
||||||
|
e = ["s/a/b/" "s/b/c/"];
|
||||||
|
n = false;
|
||||||
|
data = builtins.toJSON {id = 0;};
|
||||||
|
}
|
||||||
|
=> [
|
||||||
|
"-data={\"id\":0}"
|
||||||
|
"-e=s/a/b/"
|
||||||
|
"-e=s/b/c/"
|
||||||
|
"-i=.bak"
|
||||||
|
"-n=false"
|
||||||
|
"-testsuite=unit"
|
||||||
|
"-testsuite=integration"
|
||||||
|
"-v=true"
|
||||||
|
"-verbose=true"
|
||||||
|
"-verbose=true"
|
||||||
|
"-verbose=false"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
*/
|
||||||
|
toCommandLine =
|
||||||
|
optionFormat: attrs:
|
||||||
|
let
|
||||||
|
handlePair =
|
||||||
|
k: v:
|
||||||
|
if k == "" then
|
||||||
|
lib.throw "lib.cli.toCommandLine only accepts non-empty option names."
|
||||||
|
else if builtins.isList v then
|
||||||
|
builtins.concatMap (handleOption k) v
|
||||||
|
else
|
||||||
|
handleOption k v;
|
||||||
|
|
||||||
|
handleOption = k: renderOption (optionFormat k) k;
|
||||||
|
|
||||||
|
renderOption =
|
||||||
|
{
|
||||||
|
option,
|
||||||
|
sep,
|
||||||
|
explicitBool,
|
||||||
|
formatArg ? lib.generators.mkValueStringDefault { },
|
||||||
|
}:
|
||||||
|
k: v:
|
||||||
|
if v == null || (!explicitBool && v == false) then
|
||||||
|
[ ]
|
||||||
|
else if !explicitBool && v == true then
|
||||||
|
[ option ]
|
||||||
|
else
|
||||||
|
let
|
||||||
|
arg = formatArg v;
|
||||||
|
in
|
||||||
|
if sep != null then
|
||||||
|
[ "${option}${sep}${arg}" ]
|
||||||
|
else
|
||||||
|
[
|
||||||
|
option
|
||||||
|
arg
|
||||||
|
];
|
||||||
|
in
|
||||||
|
builtins.concatLists (lib.mapAttrsToList handlePair attrs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3106,6 +3106,86 @@ runTests {
|
|||||||
expected = "-X PUT --data '{\"id\":0}' --retry 3 --url https://example.com/foo --url https://example.com/bar --verbose";
|
expected = "-X PUT --data '{\"id\":0}' --retry 3 --url https://example.com/foo --url https://example.com/bar --verbose";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testToCommandLine = {
|
||||||
|
expr =
|
||||||
|
let
|
||||||
|
optionFormat = optionName: {
|
||||||
|
option = "-${optionName}";
|
||||||
|
sep = "=";
|
||||||
|
explicitBool = true;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
cli.toCommandLine optionFormat {
|
||||||
|
v = true;
|
||||||
|
verbose = [
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
null
|
||||||
|
];
|
||||||
|
i = ".bak";
|
||||||
|
testsuite = [
|
||||||
|
"unit"
|
||||||
|
"integration"
|
||||||
|
];
|
||||||
|
e = [
|
||||||
|
"s/a/b/"
|
||||||
|
"s/b/c/"
|
||||||
|
];
|
||||||
|
n = false;
|
||||||
|
data = builtins.toJSON { id = 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
"-data={\"id\":0}"
|
||||||
|
"-e=s/a/b/"
|
||||||
|
"-e=s/b/c/"
|
||||||
|
"-i=.bak"
|
||||||
|
"-n=false"
|
||||||
|
"-testsuite=unit"
|
||||||
|
"-testsuite=integration"
|
||||||
|
"-v=true"
|
||||||
|
"-verbose=true"
|
||||||
|
"-verbose=true"
|
||||||
|
"-verbose=false"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testToCommandLineGNU = {
|
||||||
|
expr = cli.toCommandLineGNU { } {
|
||||||
|
v = true;
|
||||||
|
verbose = [
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
null
|
||||||
|
];
|
||||||
|
i = ".bak";
|
||||||
|
testsuite = [
|
||||||
|
"unit"
|
||||||
|
"integration"
|
||||||
|
];
|
||||||
|
e = [
|
||||||
|
"s/a/b/"
|
||||||
|
"s/b/c/"
|
||||||
|
];
|
||||||
|
n = false;
|
||||||
|
data = builtins.toJSON { id = 0; };
|
||||||
|
};
|
||||||
|
|
||||||
|
expected = [
|
||||||
|
"--data={\"id\":0}"
|
||||||
|
"-es/a/b/"
|
||||||
|
"-es/b/c/"
|
||||||
|
"-i.bak"
|
||||||
|
"--testsuite=unit"
|
||||||
|
"--testsuite=integration"
|
||||||
|
"-v"
|
||||||
|
"--verbose"
|
||||||
|
"--verbose"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName {
|
testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName {
|
||||||
name = "..foo";
|
name = "..foo";
|
||||||
expected = "foo";
|
expected = "foo";
|
||||||
|
|||||||
Reference in New Issue
Block a user