Skip to content

Commit 345fd0d

Browse files
committed
add default_complete option
- fixes #65
1 parent 60a8525 commit 345fd0d

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

shtab/__init__.py

+32-20
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"directory": {"bash": "_shtab_compgen_dirs", "zsh": "_files -/", "tcsh": "d"}}
4343
FILE = CHOICE_FUNCTIONS["file"]
4444
DIRECTORY = DIR = CHOICE_FUNCTIONS["directory"]
45+
DEFAULT_FUNCTIONS = {"bash": FILE["bash"], "zsh": "_default", "tcsh": FILE["tcsh"]}
4546
FLAG_OPTION = (
4647
_StoreConstAction,
4748
_HelpAction,
@@ -134,7 +135,7 @@ def get_public_subcommands(sub):
134135
return {k for k, v in sub.choices.items() if id(v) in public_parsers}
135136

136137

137-
def get_bash_commands(root_parser, root_prefix, choice_functions=None):
138+
def get_bash_commands(root_parser, root_prefix, default_complete, choice_functions=None):
138139
"""
139140
Recursive subcommand parser traversal, returning lists of information on
140141
commands (formatted for output to the completions script).
@@ -179,10 +180,11 @@ def recurse(parser, prefix):
179180
if positional.help == SUPPRESS:
180181
continue
181182

182-
if hasattr(positional, "complete"):
183+
positional_complete = getattr(positional, "complete", {"bash": default_complete})
184+
if positional_complete:
183185
# shtab `.complete = ...` functions
184186
compgens.append(u"{}_pos_{}_COMPGEN={}".format(
185-
prefix, i, complete2pattern(positional.complete, "bash", choice_type2fn)))
187+
prefix, i, complete2pattern(positional_complete, "bash", choice_type2fn)))
186188

187189
if positional.choices:
188190
# choices (including subparsers & shtab `.complete` functions)
@@ -287,15 +289,16 @@ def recurse(parser, prefix):
287289

288290

289291
@mark_completer("bash")
290-
def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None):
292+
def complete_bash(parser, root_prefix=None, preamble="", default_complete="",
293+
choice_functions=None):
291294
"""
292295
Returns bash syntax autocompletion script.
293296
294297
See `complete` for arguments.
295298
"""
296299
root_prefix = wordify("_shtab_" + (root_prefix or parser.prog))
297300
subparsers, option_strings, compgens, choices, nargs = get_bash_commands(
298-
parser, root_prefix, choice_functions=choice_functions)
301+
parser, root_prefix, default_complete, choice_functions=choice_functions)
299302

300303
# References:
301304
# - https://www.gnu.org/software/bash/manual/html_node/
@@ -448,7 +451,8 @@ def escape_zsh(string):
448451

449452

450453
@mark_completer("zsh")
451-
def complete_zsh(parser, root_prefix=None, preamble="", choice_functions=None):
454+
def complete_zsh(parser, root_prefix=None, preamble="", default_complete="",
455+
choice_functions=None):
452456
"""
453457
Returns zsh syntax autocompletion script.
454458
@@ -484,7 +488,7 @@ def format_positional(opt):
484488
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn) if hasattr(
485489
opt, "complete") else
486490
(choice_type2fn[opt.choices[0].type] if isinstance(opt.choices[0], Choice) else
487-
"({})".format(" ".join(map(str, opt.choices)))) if opt.choices else "",
491+
"({})".format(" ".join(map(str, opt.choices)))) if opt.choices else default_complete,
488492
)
489493

490494
# {cmd: {"help": help, "arguments": [arguments]}}
@@ -634,7 +638,8 @@ def command_list(prefix, options):
634638

635639

636640
@mark_completer("tcsh")
637-
def complete_tcsh(parser, root_prefix=None, preamble="", choice_functions=None):
641+
def complete_tcsh(parser, root_prefix=None, preamble="", default_complete="",
642+
choice_functions=None):
638643
"""
639644
Return tcsh syntax autocompletion script.
640645
@@ -657,14 +662,12 @@ def get_specials(arg, arg_type, arg_sel):
657662
arg_sel,
658663
choice_strs,
659664
)
660-
elif hasattr(arg, "complete"):
661-
complete_fn = complete2pattern(arg.complete, 'tcsh', choice_type2fn)
662-
if complete_fn:
663-
yield "'{}/{}/{}/'".format(
664-
arg_type,
665-
arg_sel,
666-
complete_fn,
667-
)
665+
else:
666+
arg_complete = getattr(arg, "complete", default_complete)
667+
if arg_complete:
668+
complete_fn = complete2pattern(arg_complete, 'tcsh', choice_type2fn)
669+
if complete_fn:
670+
yield "'{}/{}/{}/'".format(arg_type, arg_sel, complete_fn)
668671

669672
def recurse_parser(cparser, positional_idx, requirements=None):
670673
log_prefix = '| ' * positional_idx
@@ -737,7 +740,8 @@ def recurse_parser(cparser, positional_idx, requirements=None):
737740

738741

739742
def complete(parser: ArgumentParser, shell: str = "bash", root_prefix: Opt[str] = None,
740-
preamble: Union[str, Dict] = "", choice_functions: Opt[Any] = None) -> str:
743+
preamble: Union[str, Dict] = "", default_complete: Union[str, Dict] = "",
744+
choice_functions: Opt[Any] = None) -> str:
741745
"""
742746
parser : argparse.ArgumentParser
743747
shell : str (bash/zsh)
@@ -746,26 +750,33 @@ def complete(parser: ArgumentParser, shell: str = "bash", root_prefix: Opt[str]
746750
preamble : dict or str
747751
mapping shell to text to prepend to generated script
748752
(e.g. `{"bash": "_myprog_custom_function(){ echo hello }"}`)
753+
default_complete : dict or str
754+
mapping shell to text to fallback on when positional `.complete` is undefined
749755
choice_functions : deprecated
750756
751757
N.B. `parser.add_argument().complete = ...` can be used to define custom
752758
completions (e.g. filenames). See <../examples/pathcomplete.py>.
753759
"""
754760
if isinstance(preamble, dict):
755761
preamble = preamble.get(shell, "")
762+
if isinstance(default_complete, dict):
763+
default_complete = default_complete.get(shell, "")
756764
completer = get_completer(shell)
757765
return completer(
758766
parser,
759767
root_prefix=root_prefix,
760768
preamble=preamble,
769+
default_complete=default_complete,
761770
choice_functions=choice_functions,
762771
)
763772

764773

765-
def completion_action(parent=None, preamble=""):
774+
def completion_action(parent=None, preamble="", default_complete=""):
766775
class PrintCompletionAction(Action):
767776
def __call__(self, parser, namespace, values, option_string=None):
768-
print(complete(parent or parser, values, preamble=preamble))
777+
print(
778+
complete(parent or parser, values, preamble=preamble,
779+
default_complete=default_complete))
769780
parser.exit(0)
770781

771782
return PrintCompletionAction
@@ -777,6 +788,7 @@ def add_argument_to(
777788
help="print shell completion script",
778789
parent=None,
779790
preamble="",
791+
default_complete="",
780792
):
781793
"""
782794
parser : argparse.ArgumentParser
@@ -794,7 +806,7 @@ def add_argument_to(
794806
option_string = [option_string]
795807
kwargs = {
796808
"choices": SUPPORTED_SHELLS, "default": None, "help": help,
797-
"action": completion_action(parent, preamble)}
809+
"action": completion_action(parent, preamble, default_complete)}
798810
if option_string[0][0] != "-": # subparser mode
799811
kwargs.update(default=SUPPORTED_SHELLS[0], nargs="?")
800812
assert parent is not None, "subcommand mode: parent required"

0 commit comments

Comments
 (0)