diff --git a/shtab/__init__.py b/shtab/__init__.py index 3564fb9..5a6c63c 100644 --- a/shtab/__init__.py +++ b/shtab/__init__.py @@ -537,7 +537,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]} @@ -655,7 +655,10 @@ def complete_tcsh(parser, root_prefix=None, preamble="", choice_functions=None): """ Return tcsh syntax autocompletion script. - See `complete` for arguments. + root_prefix: + ignored (tcsh has no support for functions) + + See `complete` for other arguments. """ optionals_single = set() optionals_double = set() @@ -716,17 +719,22 @@ def recurse_parser(cparser, positional_idx, requirements=None): # Multiple requirements nlist = [] for nn, arg in ndict.items(): - checks = [f'[ "$cmd[{iidx}]" == "{n}" ]' for iidx, n in enumerate(nn, start=2)] if arg.choices: - nlist.append('( {}echo "{}" || false )'.format( - ' && '.join(checks + ['']), # Append the separator - '\\n'.join(arg.choices), - )) - + checks = [f'[ "$cmd[{iidx}]" == "{n}" ]' for iidx, n in enumerate(nn, start=2)] + choices_str = "' '".join(arg.choices) + checks_str = ' && '.join(checks + [f"echo '{choices_str}'"]) + nlist.append(f"( {checks_str} || false )") # Ugly hack nlist_str = ' || '.join(nlist) specials.append(f"'p@{str(idx)}@`set cmd=($COMMAND_LINE); {nlist_str}`@'") + if optionals_double: + if optionals_single: + optionals_single.add('-') + else: + # Don't add a space after completing "--" from "-" + optionals_single = ('-', '-') + return Template("""\ # AUTOMATICALLY GENERATED by `shtab` @@ -734,13 +742,13 @@ def recurse_parser(cparser, positional_idx, requirements=None): complete ${prog} \\ 'c/--/(${optionals_double_str})/' \\ - 'c/-/(${optionals_single_str} -)/' \\ + 'c/-/(${optionals_single_str})/' \\ ${optionals_special_str} \\ 'p/*/()/'""").safe_substitute( preamble=("\n# Custom Preamble\n" + preamble + "\n# End Custom Preamble\n" if preamble else ""), root_prefix=root_prefix, - prog=parser.prog, optionals_double_str=' '.join(optionals_double), - optionals_single_str=' '.join(optionals_single), + prog=parser.prog, optionals_double_str=' '.join(sorted(optionals_double)), + optionals_single_str=' '.join(sorted(optionals_single)), optionals_special_str=' \\\n '.join(specials))