at 23.05-pre 2.8 kB view raw
1{ lib }: 2 3rec { 4 /* Automatically convert an attribute set to command-line options. 5 6 This helps protect against malformed command lines and also to reduce 7 boilerplate related to command-line construction for simple use cases. 8 9 `toGNUCommandLine` returns a list of nix strings. 10 `toGNUCommandLineShell` returns an escaped shell string. 11 12 Example: 13 cli.toGNUCommandLine {} { 14 data = builtins.toJSON { id = 0; }; 15 X = "PUT"; 16 retry = 3; 17 retry-delay = null; 18 url = [ "https://example.com/foo" "https://example.com/bar" ]; 19 silent = false; 20 verbose = true; 21 } 22 => [ 23 "-X" "PUT" 24 "--data" "{\"id\":0}" 25 "--retry" "3" 26 "--url" "https://example.com/foo" 27 "--url" "https://example.com/bar" 28 "--verbose" 29 ] 30 31 cli.toGNUCommandLineShell {} { 32 data = builtins.toJSON { id = 0; }; 33 X = "PUT"; 34 retry = 3; 35 retry-delay = null; 36 url = [ "https://example.com/foo" "https://example.com/bar" ]; 37 silent = false; 38 verbose = true; 39 } 40 => "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'"; 41 */ 42 toGNUCommandLineShell = 43 options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs); 44 45 toGNUCommandLine = { 46 # how to string-format the option name; 47 # by default one character is a short option (`-`), 48 # more than one characters a long option (`--`). 49 mkOptionName ? 50 k: if builtins.stringLength k == 1 51 then "-${k}" 52 else "--${k}", 53 54 # how to format a boolean value to a command list; 55 # by default it’s a flag option 56 # (only the option name if true, left out completely if false). 57 mkBool ? k: v: lib.optional v (mkOptionName k), 58 59 # how to format a list value to a command list; 60 # by default the option name is repeated for each value 61 # and `mkOption` is applied to the values themselves. 62 mkList ? k: v: lib.concatMap (mkOption k) v, 63 64 # how to format any remaining value to a command list; 65 # on the toplevel, booleans and lists are handled by `mkBool` and `mkList`, 66 # though they can still appear as values of a list. 67 # By default, everything is printed verbatim and complex types 68 # are forbidden (lists, attrsets, functions). `null` values are omitted. 69 mkOption ? 70 k: v: if v == null 71 then [] 72 else [ (mkOptionName k) (lib.generators.mkValueStringDefault {} v) ] 73 }: 74 options: 75 let 76 render = k: v: 77 if builtins.isBool v then mkBool k v 78 else if builtins.isList v then mkList k v 79 else mkOption k v; 80 81 in 82 builtins.concatLists (lib.mapAttrsToList render options); 83}