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("")
);
|