at 25.11-pre 3.9 kB view raw
1{ lib }: 2 3rec { 4 /** 5 Automatically convert an attribute set to command-line options. 6 7 This helps protect against malformed command lines and also to reduce 8 boilerplate related to command-line construction for simple use cases. 9 10 `toGNUCommandLineShell` returns an escaped shell string. 11 12 # Inputs 13 14 `options` 15 16 : How to format the arguments, see `toGNUCommandLine` 17 18 `attrs` 19 20 : The attributes to transform into arguments. 21 22 # Examples 23 :::{.example} 24 ## `lib.cli.toGNUCommandLineShell` usage example 25 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 ``` 38 39 ::: 40 */ 41 toGNUCommandLineShell = options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs); 42 43 /** 44 Automatically convert an attribute set to a list of command-line options. 45 46 `toGNUCommandLine` returns a list of string arguments. 47 48 # Inputs 49 50 `options` 51 52 : How to format the arguments, see below. 53 54 `attrs` 55 56 : The attributes to transform into arguments. 57 58 # Options 59 60 `mkOptionName` 61 62 : How to string-format the option name; 63 By default one character is a short option (`-`), more than one characters a long option (`--`). 64 65 `mkBool` 66 67 : How to format a boolean value to a command list; 68 By default its a flag option (only the option name if true, left out completely if false). 69 70 `mkList` 71 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. 74 75 `mkOption` 76 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. 80 81 `optionValueSeparator` 82 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`. 86 87 # Examples 88 :::{.example} 89 ## `lib.cli.toGNUCommandLine` usage example 90 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 ``` 110 111 ::: 112 */ 113 toGNUCommandLine = 114 { 115 mkOptionName ? k: if builtins.stringLength k == 1 then "-${k}" else "--${k}", 116 117 mkBool ? k: v: lib.optional v (mkOptionName k), 118 119 mkList ? k: v: lib.concatMap (mkOption k) v, 120 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}" ], 132 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; 145 146 in 147 builtins.concatLists (lib.mapAttrsToList render options); 148}