42
42
"directory" : {"bash" : "_shtab_compgen_dirs" , "zsh" : "_files -/" , "tcsh" : "d" }}
43
43
FILE = CHOICE_FUNCTIONS ["file" ]
44
44
DIRECTORY = DIR = CHOICE_FUNCTIONS ["directory" ]
45
+ DEFAULT_FUNCTIONS = {"bash" : FILE ["bash" ], "zsh" : "_default" , "tcsh" : FILE ["tcsh" ]}
45
46
FLAG_OPTION = (
46
47
_StoreConstAction ,
47
48
_HelpAction ,
@@ -134,7 +135,7 @@ def get_public_subcommands(sub):
134
135
return {k for k , v in sub .choices .items () if id (v ) in public_parsers }
135
136
136
137
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 ):
138
139
"""
139
140
Recursive subcommand parser traversal, returning lists of information on
140
141
commands (formatted for output to the completions script).
@@ -179,10 +180,11 @@ def recurse(parser, prefix):
179
180
if positional .help == SUPPRESS :
180
181
continue
181
182
182
- if hasattr (positional , "complete" ):
183
+ positional_complete = getattr (positional , "complete" , {"bash" : default_complete })
184
+ if positional_complete :
183
185
# shtab `.complete = ...` functions
184
186
compgens .append (u"{}_pos_{}_COMPGEN={}" .format (
185
- prefix , i , complete2pattern (positional . complete , "bash" , choice_type2fn )))
187
+ prefix , i , complete2pattern (positional_complete , "bash" , choice_type2fn )))
186
188
187
189
if positional .choices :
188
190
# choices (including subparsers & shtab `.complete` functions)
@@ -287,15 +289,16 @@ def recurse(parser, prefix):
287
289
288
290
289
291
@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 ):
291
294
"""
292
295
Returns bash syntax autocompletion script.
293
296
294
297
See `complete` for arguments.
295
298
"""
296
299
root_prefix = wordify ("_shtab_" + (root_prefix or parser .prog ))
297
300
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 )
299
302
300
303
# References:
301
304
# - https://www.gnu.org/software/bash/manual/html_node/
@@ -448,7 +451,8 @@ def escape_zsh(string):
448
451
449
452
450
453
@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 ):
452
456
"""
453
457
Returns zsh syntax autocompletion script.
454
458
@@ -484,7 +488,7 @@ def format_positional(opt):
484
488
pattern = complete2pattern (opt .complete , "zsh" , choice_type2fn ) if hasattr (
485
489
opt , "complete" ) else
486
490
(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 ,
488
492
)
489
493
490
494
# {cmd: {"help": help, "arguments": [arguments]}}
@@ -634,7 +638,8 @@ def command_list(prefix, options):
634
638
635
639
636
640
@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 ):
638
643
"""
639
644
Return tcsh syntax autocompletion script.
640
645
@@ -657,14 +662,12 @@ def get_specials(arg, arg_type, arg_sel):
657
662
arg_sel ,
658
663
choice_strs ,
659
664
)
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 )
668
671
669
672
def recurse_parser (cparser , positional_idx , requirements = None ):
670
673
log_prefix = '| ' * positional_idx
@@ -737,7 +740,8 @@ def recurse_parser(cparser, positional_idx, requirements=None):
737
740
738
741
739
742
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 :
741
745
"""
742
746
parser : argparse.ArgumentParser
743
747
shell : str (bash/zsh)
@@ -746,26 +750,33 @@ def complete(parser: ArgumentParser, shell: str = "bash", root_prefix: Opt[str]
746
750
preamble : dict or str
747
751
mapping shell to text to prepend to generated script
748
752
(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
749
755
choice_functions : deprecated
750
756
751
757
N.B. `parser.add_argument().complete = ...` can be used to define custom
752
758
completions (e.g. filenames). See <../examples/pathcomplete.py>.
753
759
"""
754
760
if isinstance (preamble , dict ):
755
761
preamble = preamble .get (shell , "" )
762
+ if isinstance (default_complete , dict ):
763
+ default_complete = default_complete .get (shell , "" )
756
764
completer = get_completer (shell )
757
765
return completer (
758
766
parser ,
759
767
root_prefix = root_prefix ,
760
768
preamble = preamble ,
769
+ default_complete = default_complete ,
761
770
choice_functions = choice_functions ,
762
771
)
763
772
764
773
765
- def completion_action (parent = None , preamble = "" ):
774
+ def completion_action (parent = None , preamble = "" , default_complete = "" ):
766
775
class PrintCompletionAction (Action ):
767
776
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 ))
769
780
parser .exit (0 )
770
781
771
782
return PrintCompletionAction
@@ -777,6 +788,7 @@ def add_argument_to(
777
788
help = "print shell completion script" ,
778
789
parent = None ,
779
790
preamble = "" ,
791
+ default_complete = "" ,
780
792
):
781
793
"""
782
794
parser : argparse.ArgumentParser
@@ -794,7 +806,7 @@ def add_argument_to(
794
806
option_string = [option_string ]
795
807
kwargs = {
796
808
"choices" : SUPPORTED_SHELLS , "default" : None , "help" : help ,
797
- "action" : completion_action (parent , preamble )}
809
+ "action" : completion_action (parent , preamble , default_complete )}
798
810
if option_string [0 ][0 ] != "-" : # subparser mode
799
811
kwargs .update (default = SUPPORTED_SHELLS [0 ], nargs = "?" )
800
812
assert parent is not None , "subcommand mode: parent required"
0 commit comments