File: args.jq

package info (click to toggle)
fq 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 106,624 kB
  • sloc: xml: 2,835; makefile: 250; sh: 241; exp: 57; ansic: 21
file content (151 lines) | stat: -rw-r--r-- 4,533 bytes parent folder | download
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
include "funcs";

# TODO: refactor this mess
def _args_parse($args; $opts):
  def _parse($args; $flagmap; $r):
    def _parse_with_arg($new_args; $optname; $value; $opt):
      if $opt.object then
        ( ( $value
          | capture("^(?<key>.*?)=(?<value>.*)$")
          // error("\($value): should be key=value")
          ) as {$key, $value}
          # TODO: validate option name key
        | _parse($new_args; $flagmap; ($r | .parsed[$optname][$key] |= $value))
        )
      elif $opt.array then
        _parse($new_args; $flagmap; ($r | .parsed[$optname] += [$value]))
      elif $opt.pairs then
        _parse($new_args; $flagmap; ($r | .parsed[$optname] += [$value]))
      else
        _parse($new_args; $flagmap; ($r | .parsed[$optname] = $value))
      end;
    def _parse_without_arg($new_args; $optname):
      _parse($new_args; $flagmap; ($r | .parsed[$optname] = true));
    # this is to support --arg=VALUE
    ( ($args[0] | index("=")) as $assign_i
    | ( if $assign_i then $args[0][0:$assign_i]
        else $args[0]
        end
      ) as $arg
    | if $arg == null then
        $r
      else
        if $arg == "--" then
          $r | .rest += $args[1:]
        # \d to not see -0, -123 etc as an argument
        elif $arg | test("^--?[^-\\d]") then
          ( $flagmap[$arg] as $optname
          | ($opts[$optname]? // null) as $opt
          | if $opt == null then
              if $arg | test("^-[^-]") then
                ( $arg[0:2] as $arg
                | $flagmap[$arg] as $optname
                | ($opts[$optname]? // null) as $opt
                | if $opt == null then
                    error("\($arg): no such argument")
                  elif $opt.bool then
                    _parse_without_arg((["-"+$args[0][2:]]+$args[1:]); $optname)
                  else
                    error("\($arg): needs an argument")
                  end
                )
              else
                error("\($arg): no such argument")
              end
            elif $opt.string or $opt.array or $opt.object then
              if $assign_i then
                _parse_with_arg($args[1:]; $optname; $args[0][$assign_i+1:]; $opt)
              elif ($args | length) < 2 then
                if $opt.optional then
                  _parse_without_arg($args[1:]; $optname)
                else
                  error("\($arg): needs an argument")
                end
              else
                _parse_with_arg($args[2:]; $optname; $args[1]; $opt)
              end
            elif $opt.pairs then
              if ($args | length) > 2 then
                _parse_with_arg($args[3:]; $optname; [$args[1], $args[2]]; $opt)
              else
                error("\($arg): needs two argument")
              end
            else
              if $assign_i then error("\($arg): takes no argument")
              else _parse_without_arg($args[1:]; $optname)
              end
            end
          )
        else
          _parse($args[1:]; $flagmap; ($r | .rest += [$args[0]]))
        end
      end
    );
  # build {"-s": "name", "--long": "name", ...}
  def _flagmap:
    ( $opts
    | to_entries
    | map(
        ( . as $opt
        | [.value.short // empty] +
          [.value.long // empty] +
          (.value.aliases // [])
        | map({key: ., value: $opt.key})
        | from_entries
        )
      )
    | add
    );
  def _defaults:
    ( $opts
    | to_entries
    | map(select(.value.default))
    | map({(.key): .value.default})
    | add
    );
  _parse($args; _flagmap; {parsed: _defaults, rest: []});

def args_help_text($opts):
  def _opthelp:
    ( [ .long
      , .short
      ] | map(select(strings)) | join(",")
    ) +
    ( .string // .array // .object // .pairs
    | if . then " \(.)"
      else ""
      end
    );
  def _maxoptlen:
    [ $opts[]
    | (_opthelp | length)
    ] | max;
  def _obj_value:
      if . == null then ""
      elif (. | type) == "string" then tojson | .[1:-1]
      else .
      end;
  ( _maxoptlen as $l
  | $opts
  | to_entries
  | sort_by(.value.long)
  | .[]
  | (.value | .help_default // .default) as $default
  | [ "\(.value | _opthelp | rpad(" "; $l))  \(.value.description)"
    , if $default then
        if .value.object then
          [ "\n"
          , ( [$default | to_entries[] | "\(" "*$l)    \(.key)=\(.value | _obj_value)"]
            | join("\n")
            )
          ]
        else
          " (\($default))"
        end
      else
        empty
      end
    ]
  | flatten
  | join("")
  );