Skip to content

Commit

Permalink
Merge pull request #140 from FederAndInk/main
Browse files Browse the repository at this point in the history
  • Loading branch information
casperdcl authored Jul 24, 2023
2 parents f05ec32 + 749d73e commit a6f5ba9
Showing 1 changed file with 21 additions and 11 deletions.
32 changes: 21 additions & 11 deletions shtab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,24 +474,26 @@ def is_opt_end(opt):
def is_opt_multiline(opt):
return isinstance(opt, OPTION_MULTI)

def format_optional(opt):
def format_optional(opt, parser):
get_help = parser._get_formatter()._expand_help
return (('{nargs}{options}"[{help}]"' if isinstance(
opt, FLAG_OPTION) else '{nargs}{options}"[{help}]:{dest}:{pattern}"').format(
nargs=('"(- : *)"' if is_opt_end(opt) else '"*"' if is_opt_multiline(opt) else ""),
options=("{{{}}}".format(",".join(opt.option_strings)) if len(opt.option_strings)
> 1 else '"{}"'.format("".join(opt.option_strings))),
help=escape_zsh(opt.help or ""),
help=escape_zsh(get_help(opt) if opt.help else ""),
dest=opt.dest,
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn) if hasattr(
opt, "complete") else
(choice_type2fn[opt.choices[0].type] if isinstance(opt.choices[0], Choice) else
"({})".format(" ".join(map(str, opt.choices)))) if opt.choices else "",
).replace('""', ""))

def format_positional(opt):
def format_positional(opt, parser):
get_help = parser._get_formatter()._expand_help
return '"{nargs}:{help}:{pattern}"'.format(
nargs={ONE_OR_MORE: "(*)", ZERO_OR_MORE: "(*):", REMAINDER: "(-)*"}.get(opt.nargs, ""),
help=escape_zsh((opt.help or opt.dest).strip().split("\n")[0]),
help=escape_zsh((get_help(opt) if opt.help else opt.dest).strip().split("\n")[0]),
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn) if hasattr(
opt, "complete") else
(choice_type2fn[opt.choices[0].type] if isinstance(opt.choices[0], Choice) else
Expand All @@ -502,9 +504,9 @@ def format_positional(opt):
all_commands = {
root_prefix: {
"cmd": prog, "arguments": [
format_optional(opt)
format_optional(opt, parser)
for opt in parser._get_optional_actions() if opt.help != SUPPRESS] + [
format_positional(opt) for opt in parser._get_positional_actions()
format_positional(opt, parser) for opt in parser._get_positional_actions()
if opt.help != SUPPRESS and opt.choices is None],
"help": (parser.description
or "").strip().split("\n")[0], "commands": [], "paths": []}}
Expand All @@ -517,7 +519,7 @@ def recurse(parser, prefix, paths=None):
continue
if not sub.choices or not isinstance(sub.choices, dict):
# positional argument
all_commands[prefix]["arguments"].append(format_positional(sub))
all_commands[prefix]["arguments"].append(format_positional(sub, parser))
else: # subparser
log.debug(f"choices:{prefix}:{sorted(sub.choices)}")
public_cmds = get_public_subcommands(sub)
Expand All @@ -529,18 +531,26 @@ def recurse(parser, prefix, paths=None):

# optionals
arguments = [
format_optional(opt) for opt in subparser._get_optional_actions()
format_optional(opt, parser) for opt in subparser._get_optional_actions()
if opt.help != SUPPRESS]

# positionals
arguments.extend(
format_positional(opt) for opt in subparser._get_positional_actions()
format_positional(opt, parser)
for opt in subparser._get_positional_actions()
if not isinstance(opt.choices, dict) if opt.help != SUPPRESS)

# help text
formatter = subparser._get_formatter()
backup_width = formatter._width
formatter._width = 1234567 # large number to effectively disable wrapping
desc = formatter._format_text(subparser.description or "").strip()
formatter._width = backup_width

new_pref = f"{prefix}_{wordify(cmd)}"
options = all_commands[new_pref] = {
"cmd": cmd, "help": (subparser.description or "").strip().split("\n")[0],
"arguments": arguments, "paths": [*paths, cmd]}
"cmd": cmd, "help": desc.split("\n")[0], "arguments": arguments,
"paths": [*paths, cmd]}
new_subcmds = recurse(subparser, new_pref, [*paths, cmd])
options["commands"] = {
all_commands[pref]["cmd"]: all_commands[pref]
Expand Down

0 comments on commit a6f5ba9

Please sign in to comment.