pocket-casts: update electron pin; move to pkgs/by-name/ (#372095)
[NixPkgs.git] / lib / cli.nix
blob590ba691d386ae3bd9ef93b66fc9e4de7b5d1822
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.
12     # Inputs
14     `options`
16     : How to format the arguments, see `toGNUCommandLine`
18     `attrs`
20     : The attributes to transform into arguments.
22     # Examples
23     :::{.example}
24     ## `lib.cli.toGNUCommandLineShell` usage example
26     ```nix
27     cli.toGNUCommandLineShell {} {
28       data = builtins.toJSON { id = 0; };
29       X = "PUT";
30       retry = 3;
31       retry-delay = null;
32       url = [ "https://example.com/foo" "https://example.com/bar" ];
33       silent = false;
34       verbose = true;
35     }
36     => "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
37     ```
39     :::
40   */
41   toGNUCommandLineShell = options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);
43   /**
44     Automatically convert an attribute set to a list of command-line options.
46     `toGNUCommandLine` returns a list of string arguments.
48     # Inputs
50     `options`
52     : How to format the arguments, see below.
54     `attrs`
56     : The attributes to transform into arguments.
58     # Options
60     `mkOptionName`
62     : How to string-format the option name;
63     By default one character is a short option (`-`), more than one characters a long option (`--`).
65     `mkBool`
67     : How to format a boolean value to a command list;
68     By default it’s a flag option (only the option name if true, left out completely if false).
70     `mkList`
72     : How to format a list value to a command list;
73     By default the option name is repeated for each value and `mkOption` is applied to the values themselves.
75     `mkOption`
77     : How to format any remaining value to a command list;
78     On the toplevel, booleans and lists are handled by `mkBool` and `mkList`, though they can still appear as values of a list.
79     By default, everything is printed verbatim and complex types are forbidden (lists, attrsets, functions). `null` values are omitted.
81     `optionValueSeparator`
83     : How to separate an option from its flag;
84     By default, there is no separator, so option `-c` and value `5` would become ["-c" "5"].
85     This is useful if the command requires equals, for example, `-c=5`.
87     # Examples
88     :::{.example}
89     ## `lib.cli.toGNUCommandLine` usage example
91     ```nix
92     cli.toGNUCommandLine {} {
93       data = builtins.toJSON { id = 0; };
94       X = "PUT";
95       retry = 3;
96       retry-delay = null;
97       url = [ "https://example.com/foo" "https://example.com/bar" ];
98       silent = false;
99       verbose = true;
100     }
101     => [
102       "-X" "PUT"
103       "--data" "{\"id\":0}"
104       "--retry" "3"
105       "--url" "https://example.com/foo"
106       "--url" "https://example.com/bar"
107       "--verbose"
108     ]
109     ```
111     :::
112   */
113   toGNUCommandLine =
114     {
115       mkOptionName ? k: if builtins.stringLength k == 1 then "-${k}" else "--${k}",
117       mkBool ? k: v: lib.optional v (mkOptionName k),
119       mkList ? k: v: lib.concatMap (mkOption k) v,
121       mkOption ?
122         k: v:
123         if v == null then
124           [ ]
125         else if optionValueSeparator == null then
126           [
127             (mkOptionName k)
128             (lib.generators.mkValueStringDefault { } v)
129           ]
130         else
131           [ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault { } v}" ],
133       optionValueSeparator ? null,
134     }:
135     options:
136     let
137       render =
138         k: v:
139         if builtins.isBool v then
140           mkBool k v
141         else if builtins.isList v then
142           mkList k v
143         else
144           mkOption k v;
146     in
147     builtins.concatLists (lib.mapAttrsToList render options);