| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | { lib }: | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-05 13:03:00 -08:00
										 |  |  |  | rec { | 
					
						
							|  |  |  |  |   /* Automatically convert an attribute set to command-line options.
 | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |      This helps protect against malformed command lines and also to reduce | 
					
						
							|  |  |  |  |      boilerplate related to command-line construction for simple use cases. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 23:24:06 +01:00
										 |  |  |  |      `toGNUCommandLine` returns a list of nix strings. | 
					
						
							|  |  |  |  |      `toGNUCommandLineShell` returns an escaped shell string. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  |      Example: | 
					
						
							| 
									
										
										
										
											2020-01-22 23:37:10 +01:00
										 |  |  |  |        cli.toGNUCommandLine {} { | 
					
						
							|  |  |  |  |          data = builtins.toJSON { id = 0; }; | 
					
						
							|  |  |  |  |          X = "PUT"; | 
					
						
							|  |  |  |  |          retry = 3; | 
					
						
							|  |  |  |  |          retry-delay = null; | 
					
						
							|  |  |  |  |          url = [ "https://example.com/foo" "https://example.com/bar" ]; | 
					
						
							|  |  |  |  |          silent = false; | 
					
						
							|  |  |  |  |          verbose = true; | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  |        => [ | 
					
						
							|  |  |  |  |          "-X" "PUT" | 
					
						
							|  |  |  |  |          "--data" "{\"id\":0}" | 
					
						
							|  |  |  |  |          "--retry" "3" | 
					
						
							|  |  |  |  |          "--url" "https://example.com/foo" | 
					
						
							|  |  |  |  |          "--url" "https://example.com/bar" | 
					
						
							|  |  |  |  |          "--verbose" | 
					
						
							|  |  |  |  |        ] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |        cli.toGNUCommandLineShell {} { | 
					
						
							|  |  |  |  |          data = builtins.toJSON { id = 0; }; | 
					
						
							|  |  |  |  |          X = "PUT"; | 
					
						
							|  |  |  |  |          retry = 3; | 
					
						
							|  |  |  |  |          retry-delay = null; | 
					
						
							|  |  |  |  |          url = [ "https://example.com/foo" "https://example.com/bar" ]; | 
					
						
							|  |  |  |  |          silent = false; | 
					
						
							|  |  |  |  |          verbose = true; | 
					
						
							|  |  |  |  |        } | 
					
						
							|  |  |  |  |        => "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'"; | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2020-01-22 23:24:06 +01:00
										 |  |  |  |   toGNUCommandLineShell = | 
					
						
							| 
									
										
										
										
											2020-01-05 13:03:00 -08:00
										 |  |  |  |     options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-23 01:09:55 +01:00
										 |  |  |  |   toGNUCommandLine = { | 
					
						
							|  |  |  |  |     # how to string-format the option name; | 
					
						
							|  |  |  |  |     # by default one character is a short option (`-`), | 
					
						
							|  |  |  |  |     # more than one characters a long option (`--`). | 
					
						
							|  |  |  |  |     mkOptionName ? | 
					
						
							|  |  |  |  |       k: if builtins.stringLength k == 1 | 
					
						
							|  |  |  |  |           then "-${k}" | 
					
						
							|  |  |  |  |           else "--${k}", | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-23 01:09:55 +01:00
										 |  |  |  |     # how to format a boolean value to a command list; | 
					
						
							|  |  |  |  |     # by default it’s a flag option | 
					
						
							|  |  |  |  |     # (only the option name if true, left out completely if false). | 
					
						
							|  |  |  |  |     mkBool ? k: v: lib.optional v (mkOptionName k), | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-23 01:09:55 +01:00
										 |  |  |  |     # how to format a list value to a command list; | 
					
						
							|  |  |  |  |     # by default the option name is repeated for each value | 
					
						
							|  |  |  |  |     # and `mkOption` is applied to the values themselves. | 
					
						
							|  |  |  |  |     mkList ? k: v: lib.concatMap (mkOption k) v, | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-23 01:09:55 +01:00
										 |  |  |  |     # how to format any remaining value to a command list; | 
					
						
							|  |  |  |  |     # on the toplevel, booleans and lists are handled by `mkBool` and `mkList`, | 
					
						
							|  |  |  |  |     # though they can still appear as values of a list. | 
					
						
							|  |  |  |  |     # By default, everything is printed verbatim and complex types | 
					
						
							|  |  |  |  |     # are forbidden (lists, attrsets, functions). `null` values are omitted. | 
					
						
							|  |  |  |  |     mkOption ? | 
					
						
							|  |  |  |  |       k: v: if v == null | 
					
						
							|  |  |  |  |             then [] | 
					
						
							|  |  |  |  |             else [ (mkOptionName k) (lib.generators.mkValueStringDefault {} v) ] | 
					
						
							| 
									
										
										
										
											2019-12-13 18:25:52 -08:00
										 |  |  |  |     }: | 
					
						
							|  |  |  |  |     options: | 
					
						
							|  |  |  |  |       let | 
					
						
							| 
									
										
										
										
											2020-01-22 23:55:42 +01:00
										 |  |  |  |         render = k: v: | 
					
						
							|  |  |  |  |           if      builtins.isBool v then mkBool k v | 
					
						
							|  |  |  |  |           else if builtins.isList v then mkList k v | 
					
						
							|  |  |  |  |           else mkOption k v; | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       in | 
					
						
							| 
									
										
										
										
											2020-01-05 13:03:00 -08:00
										 |  |  |  |         builtins.concatLists (lib.mapAttrsToList render options); | 
					
						
							| 
									
										
										
										
											2019-12-11 16:30:05 -08:00
										 |  |  |  | } |