Skip to content

add default_complete option (Sourcery refactored) #84

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 84 additions & 55 deletions shtab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ def get_option_strings(parser):
def recurse(parser, prefix):
"""recurse through subparsers, appending to the return lists"""
subparsers = []
option_strings = []
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function get_bash_commands.recurse refactored with the following changes:

This removes the following comments ( why? ):

# optional arguments

compgens = []
choices = []
nargs = []
Expand All @@ -180,24 +179,26 @@ def recurse(parser, prefix):
if positional.help == SUPPRESS:
continue

positional_complete = getattr(positional, "complete", {"bash": default_complete})
if positional_complete:
if positional_complete := getattr(
positional, "complete", {"bash": default_complete}
):
# shtab `.complete = ...` functions
compgens.append(u"{}_pos_{}_COMPGEN={}".format(
prefix, i, complete2pattern(positional_complete, "bash", choice_type2fn)))
compgens.append(
f'{prefix}_pos_{i}_COMPGEN={complete2pattern(positional_complete, "bash", choice_type2fn)}'
)


if positional.choices:
# choices (including subparsers & shtab `.complete` functions)
log.debug("choices:{}:{}".format(prefix, sorted(positional.choices)))
log.debug(f"choices:{prefix}:{sorted(positional.choices)}")

this_positional_choices = []
for choice in positional.choices:
if isinstance(choice, Choice):
# append special completion type to `compgens`
# NOTE: overrides `.complete` attribute
log.debug("Choice.{}:{}:{}".format(choice.type, prefix, positional.dest))
compgens.append(u"{}_pos_{}_COMPGEN={}".format(
prefix, i, choice_type2fn[choice.type]))
log.debug(f"Choice.{choice.type}:{prefix}:{positional.dest}")
compgens.append(f"{prefix}_pos_{i}_COMPGEN={choice_type2fn[choice.type]}")
elif isinstance(positional.choices, dict):
# subparser, so append to list of subparsers & recurse
log.debug("subcommand:%s", choice)
Expand All @@ -213,8 +214,9 @@ def recurse(parser, prefix):
new_nargs,
) = recurse(
positional.choices[choice],
prefix + "_" + wordify(choice),
f"{prefix}_{wordify(choice)}",
)

sub_subparsers.extend(new_subparsers)
sub_option_strings.extend(new_option_strings)
sub_compgens.extend(new_compgens)
Expand All @@ -232,26 +234,30 @@ def recurse(parser, prefix):

# skip default `nargs` values
if positional.nargs not in (None, "1", "?"):
nargs.append(u"{}_pos_{}_nargs={}".format(prefix, i, positional.nargs))
nargs.append(f"{prefix}_pos_{i}_nargs={positional.nargs}")

if discovered_subparsers:
subparsers.append(u"{}_subparsers=('{}')".format(prefix,
"' '".join(discovered_subparsers)))
log.debug("subcommands:{}:{}".format(prefix, discovered_subparsers))
log.debug(f"subcommands:{prefix}:{discovered_subparsers}")

option_strings = [
u"{}_option_strings=('{}')".format(
prefix, "' '".join(get_option_strings(parser))
)
]

# optional arguments
option_strings.append(u"{}_option_strings=('{}')".format(
prefix, "' '".join(get_option_strings(parser))))
for optional in parser._get_optional_actions():
if optional == SUPPRESS:
continue

for option_string in optional.option_strings:
if hasattr(optional, "complete"):
# shtab `.complete = ...` functions
compgens.append(u"{}_{}_COMPGEN={}".format(
prefix, wordify(option_string),
complete2pattern(optional.complete, "bash", choice_type2fn)))
compgens.append(
f'{prefix}_{wordify(option_string)}_COMPGEN={complete2pattern(optional.complete, "bash", choice_type2fn)}'
)


if optional.choices:
# choices (including shtab `.complete` functions)
Expand All @@ -260,9 +266,11 @@ def recurse(parser, prefix):
# append special completion type to `compgens`
# NOTE: overrides `.complete` attribute
if isinstance(choice, Choice):
log.debug("Choice.{}:{}:{}".format(choice.type, prefix, optional.dest))
compgens.append(u"{}_{}_COMPGEN={}".format(
prefix, wordify(option_string), choice_type2fn[choice.type]))
log.debug(f"Choice.{choice.type}:{prefix}:{optional.dest}")
compgens.append(
f"{prefix}_{wordify(option_string)}_COMPGEN={choice_type2fn[choice.type]}"
)

else:
# simple choice
this_optional_choices.append(str(choice))
Expand All @@ -273,8 +281,7 @@ def recurse(parser, prefix):

# Check for nargs.
if optional.nargs is not None and optional.nargs != 1:
nargs.append(u"{}_{}_nargs={}".format(prefix, wordify(option_string),
optional.nargs))
nargs.append(f"{prefix}_{wordify(option_string)}_nargs={optional.nargs}")

# append recursion results
subparsers.extend(sub_subparsers)
Expand Down Expand Up @@ -466,29 +473,53 @@ def complete_zsh(parser, root_prefix=None, preamble="", default_complete="",
choice_type2fn.update(choice_functions)

def format_optional(opt):
return (('{nargs}{options}"[{help}]"' if isinstance(
opt, FLAG_OPTION) else '{nargs}{options}"[{help}]:{dest}:{pattern}"').format(
nargs=('"(- :)"' if isinstance(opt, OPTION_END) else
'"*"' if isinstance(opt, OPTION_MULTI) else ""),
options=("{{{}}}".format(",".join(opt.option_strings))
if len(opt.option_strings) > 1 else '"{}"'.format("".join(
opt.option_strings))),
return (
(
'{nargs}{options}"[{help}]"'
if isinstance(opt, FLAG_OPTION)
else '{nargs}{options}"[{help}]:{dest}:{pattern}"'
)
.format(
nargs=(
'"(- :)"'
if isinstance(opt, OPTION_END)
else '"*"'
if isinstance(opt, OPTION_MULTI)
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 ""),
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('""', ""))
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 f'({" ".join(map(str, opt.choices))})'
)
if opt.choices
else "",
)
.replace('""', "")
)
Comment on lines -469 to +508
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function complete_zsh.format_optional refactored with the following changes:


def format_positional(opt):
return '"{nargs}:{help}:{pattern}"'.format(
nargs={"+": "(*)", "*": "(*):"}.get(opt.nargs, ""),
help=escape_zsh((opt.help or 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
"({})".format(" ".join(map(str, opt.choices)))) if opt.choices else default_complete,
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 f'({" ".join(map(str, opt.choices))})'
)
if opt.choices
else default_complete,
Comment on lines -488 to +522
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function complete_zsh.format_positional refactored with the following changes:

)

# {cmd: {"help": help, "arguments": [arguments]}}
Expand All @@ -506,11 +537,11 @@ def recurse(parser, prefix, paths=None):
for sub in parser._get_positional_actions():
if sub.help == SUPPRESS or not sub.choices:
continue
if not sub.choices or not isinstance(sub.choices, dict):
if not isinstance(sub.choices, dict):
# positional argument
all_commands[prefix]["arguments"].append(format_positional(sub))
else: # subparser
log.debug("choices:{}:{}".format(prefix, sorted(sub.choices)))
log.debug(f"choices:{prefix}:{sorted(sub.choices)}")
Comment on lines -509 to +544
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function complete_zsh.recurse refactored with the following changes:

public_cmds = get_public_subcommands(sub)
for cmd, subparser in sub.choices.items():
if cmd not in public_cmds:
Expand All @@ -528,7 +559,7 @@ def recurse(parser, prefix, paths=None):
format_positional(opt) for opt in subparser._get_positional_actions()
if not isinstance(opt.choices, dict) if opt.help != SUPPRESS)

new_pref = prefix + "_" + wordify(cmd)
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]}
Expand Down Expand Up @@ -592,8 +623,11 @@ def command_option(prefix, options):

def command_list(prefix, options):
name = " ".join([prog, *options["paths"]])
commands = "\n ".join('"{}:{}"'.format(cmd, escape_zsh(opt["help"]))
for cmd, opt in sorted(options["commands"].items()))
commands = "\n ".join(
f'"{cmd}:{escape_zsh(opt["help"])}"'
for cmd, opt in sorted(options["commands"].items())
)

Comment on lines -595 to +630
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function complete_zsh.command_list refactored with the following changes:

return """
{prefix}_commands() {{
local _commands=(
Expand Down Expand Up @@ -657,17 +691,12 @@ def complete_tcsh(parser, root_prefix=None, preamble="", default_complete="",
def get_specials(arg, arg_type, arg_sel):
if arg.choices:
choice_strs = ' '.join(map(str, arg.choices))
yield "'{}/{}/({})/'".format(
arg_type,
arg_sel,
choice_strs,
)
else:
arg_complete = getattr(arg, "complete", default_complete)
if arg_complete:
complete_fn = complete2pattern(arg_complete, 'tcsh', choice_type2fn)
if complete_fn:
yield "'{}/{}/{}/'".format(arg_type, arg_sel, complete_fn)
yield f"'{arg_type}/{arg_sel}/({choice_strs})/'"
elif arg_complete := getattr(arg, "complete", default_complete):
if complete_fn := complete2pattern(
arg_complete, 'tcsh', choice_type2fn
):
yield f"'{arg_type}/{arg_sel}/{complete_fn}/'"
Comment on lines -660 to +699
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function complete_tcsh.get_specials refactored with the following changes:


def recurse_parser(cparser, positional_idx, requirements=None):
log_prefix = '| ' * positional_idx
Expand Down