nixos/tests/forgejo: fix after git v2.47 bump
[NixPkgs.git] / lib / cli.nix
blobb65131ac1a1b476bf815841680f7c5d4aa51430e
1 { lib }:
3 rec {
4   /**
5     Automatically convert an attribute set to command-line options.
7     This helps protect against malformed command lines and also to reduce
8     boilerplate related to command-line construction for simple use cases.
10     `toGNUCommandLineShell` returns an escaped shell string.
13     # Inputs
15     `options`
17     : How to format the arguments, see `toGNUCommandLine`
19     `attrs`
21     : The attributes to transform into arguments.
24     # Examples
25     :::{.example}
26     ## `lib.cli.toGNUCommandLineShell` usage example
28     ```nix
29     cli.toGNUCommandLineShell {} {
30       data = builtins.toJSON { id = 0; };
31       X = "PUT";
32       retry = 3;
33       retry-delay = null;
34       url = [ "https://example.com/foo" "https://example.com/bar" ];
35       silent = false;
36       verbose = true;
37     }
38     => "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
39     ```
41     :::
42   */
43   toGNUCommandLineShell =
44     options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
46   /**
47     Automatically convert an attribute set to a list of command-line options.
49     `toGNUCommandLine` returns a list of string arguments.
52     # Inputs
54     `options`
56     : How to format the arguments, see below.
58     `attrs`
60     : The attributes to transform into arguments.
62     # Options
64     `mkOptionName`
66     : How to string-format the option name;
67     By default one character is a short option (`-`), more than one characters a long option (`--`).
69     `mkBool`
71     : How to format a boolean value to a command list;
72     By default it’s a flag option (only the option name if true, left out completely if false).
74     `mkList`
76     : How to format a list value to a command list;
77     By default the option name is repeated for each value and `mkOption` is applied to the values themselves.
80     `mkOption`
82     : How to format any remaining value to a command list;
83     On the toplevel, booleans and lists are handled by `mkBool` and `mkList`, though they can still appear as values of a list.
84     By default, everything is printed verbatim and complex types are forbidden (lists, attrsets, functions). `null` values are omitted.
86     `optionValueSeparator`
88     : How to separate an option from its flag;
89     By default, there is no separator, so option `-c` and value `5` would become ["-c" "5"].
90     This is useful if the command requires equals, for example, `-c=5`.
93     # Examples
94     :::{.example}
95     ## `lib.cli.toGNUCommandLine` usage example
97     ```nix
98     cli.toGNUCommandLine {} {
99       data = builtins.toJSON { id = 0; };
100       X = "PUT";
101       retry = 3;
102       retry-delay = null;
103       url = [ "https://example.com/foo" "https://example.com/bar" ];
104       silent = false;
105       verbose = true;
106     }
107     => [
108       "-X" "PUT"
109       "--data" "{\"id\":0}"
110       "--retry" "3"
111       "--url" "https://example.com/foo"
112       "--url" "https://example.com/bar"
113       "--verbose"
114     ]
115     ```
117     :::
118   */
119   toGNUCommandLine = {
120     mkOptionName ?
121       k: if builtins.stringLength k == 1
122           then "-${k}"
123           else "--${k}",
125     mkBool ? k: v: lib.optional v (mkOptionName k),
127     mkList ? k: v: lib.concatMap (mkOption k) v,
129     mkOption ?
130       k: v: if v == null
131             then []
132             else if optionValueSeparator == null then
133               [ (mkOptionName k) (lib.generators.mkValueStringDefault {} v) ]
134             else
135               [ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault {} v}" ],
137     optionValueSeparator ? null
138     }:
139     options:
140       let
141         render = k: v:
142           if      builtins.isBool v then mkBool k v
143           else if builtins.isList v then mkList k v
144           else mkOption k v;
146       in
147         builtins.concatLists (lib.mapAttrsToList render options);