Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at fix-function-merge 148 lines 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 13 # Inputs 14 15 `options` 16 17 : How to format the arguments, see `toGNUCommandLine` 18 19 `attrs` 20 21 : The attributes to transform into arguments. 22 23 24 # Examples 25 :::{.example} 26 ## `lib.cli.toGNUCommandLineShell` usage example 27 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 ``` 40 41 ::: 42 */ 43 toGNUCommandLineShell = 44 options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs); 45 46 /** 47 Automatically convert an attribute set to a list of command-line options. 48 49 `toGNUCommandLine` returns a list of string arguments. 50 51 52 # Inputs 53 54 `options` 55 56 : How to format the arguments, see below. 57 58 `attrs` 59 60 : The attributes to transform into arguments. 61 62 # Options 63 64 `mkOptionName` 65 66 : How to string-format the option name; 67 By default one character is a short option (`-`), more than one characters a long option (`--`). 68 69 `mkBool` 70 71 : How to format a boolean value to a command list; 72 By default its a flag option (only the option name if true, left out completely if false). 73 74 `mkList` 75 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. 78 79 80 `mkOption` 81 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. 85 86 `optionValueSeparator` 87 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`. 91 92 93 # Examples 94 :::{.example} 95 ## `lib.cli.toGNUCommandLine` usage example 96 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 ``` 116 117 ::: 118 */ 119 toGNUCommandLine = { 120 mkOptionName ? 121 k: if builtins.stringLength k == 1 122 then "-${k}" 123 else "--${k}", 124 125 mkBool ? k: v: lib.optional v (mkOptionName k), 126 127 mkList ? k: v: lib.concatMap (mkOption k) v, 128 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}" ], 136 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; 145 146 in 147 builtins.concatLists (lib.mapAttrsToList render options); 148}