summary refs log tree commit diff
path: root/lib/cli.nix
blob: f47625d2f5370565fb6487f847dc0669cf0daac4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{ lib }:

rec {
  /* Automatically convert an attribute set to command-line options.

     This helps protect against malformed command lines and also to reduce
     boilerplate related to command-line construction for simple use cases.

     Example:
       encodeGNUCommandLine
         { }
         { 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'"
  */
  encodeGNUCommandLine =
    options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs);

  toGNUCommandLine =
    { renderKey ?
        key: if builtins.stringLength key == 1 then "-${key}" else "--${key}"

    , renderOption ?
        key: value:
          if value == null
          then []
          else [ (renderKey key) (builtins.toString value) ]

    , renderBool ? key: value: lib.optional value (renderKey key)

    , renderList ? key: value: lib.concatMap (renderOption key) value
    }:
    options:
      let
        render = key: value:
                 if builtins.isBool value
            then renderBool key value
            else if builtins.isList value
            then renderList key value
            else renderOption key value;

      in
        builtins.concatLists (lib.mapAttrsToList render options);
}