Skip to content

Commit 5f9af47

Browse files
committed
misc tidy
1 parent 9f4c235 commit 5f9af47

File tree

1 file changed

+85
-117
lines changed

1 file changed

+85
-117
lines changed

shtab/__init__.py

Lines changed: 85 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,14 @@ def wordify(string):
143143

144144
def get_bash_commands(root_parser, root_prefix, choice_functions=None):
145145
"""
146-
Recursive subcommand parser traversal, printing bash helper syntax.
146+
Recursive subcommand parser traversal, returning lists of information on
147+
commands (formatted for output to the completions script).
148+
printing bash helper syntax.
147149
148150
Returns:
149-
commands : list of subparsers for each parser
151+
subparsers : list of subparsers for each parser
150152
option_strings : list of options strings for each parser
151-
compgens : list of shtab completion functions corresponding to actions
153+
compgens : list of shtab `.complete` functions corresponding to actions
152154
choices : list of choices corresponding to actions
153155
nargs : list of number of args allowed for each action (if not 0 or 1)
154156
"""
@@ -167,35 +169,29 @@ def get_option_strings(parser):
167169
[],
168170
)
169171

170-
# For the given parser, return a tuple of lists of information on commands,
171-
# option strings, compgens, choices, and nargs values (where applicable)
172-
# formatted for output to the completions script.
173-
# Also recurse through any subparsers, adding their results to the lists.
174172
def recurse(parser, prefix):
173+
"""recurse through subparsers, appending to the return lists"""
175174
subparsers = []
176175
option_strings = []
177176
compgens = []
178177
choices = []
179178
nargs = []
180179

181-
# These lists are generated from recursive calls to subparsers but aren't
182-
# added to the main list until just before returning, so that the order in
183-
# output makes sense with the structure of the argparser object.
180+
# temp lists for recursion results
184181
sub_subparsers = []
185182
sub_option_strings = []
186183
sub_compgens = []
187184
sub_choices = []
188185
sub_nargs = []
189186

190-
# Add relevant information for all the positional arguments (where applicable).
187+
# positional arguments
191188
discovered_subparsers = []
192189
for i, positional in enumerate(parser._get_positional_actions()):
193-
194190
if positional.help == SUPPRESS:
195191
continue
196192

197-
# Check for shtab completion functions.
198193
if hasattr(positional, "complete"):
194+
# shtab `.complete = ...` functions
199195
compgens.append(
200196
u"{}_pos_{}_COMPGEN={}".format(
201197
prefix,
@@ -204,18 +200,15 @@ def recurse(parser, prefix):
204200
)
205201
)
206202

207-
# Check for choices (including calls to subparsers and shtab
208-
# completion functions)
209203
if positional.choices:
204+
# choices (including subparsers & shtab `.complete` functions)
210205
log.debug("choices:{}:{}".format(prefix, sorted(positional.choices)))
211206

212207
this_positional_choices = []
213208
for choice in positional.choices:
214-
# If the choice is a special completion type, add its info to
215-
# compgens.
216-
# NOTE: if compgens were specified in the "complete" attribute,
217-
# this will overwrite them.
218209
if isinstance(choice, Choice):
210+
# append special completion type to `compgens`
211+
# NOTE: overrides `.complete` attribute
219212
log.debug(
220213
"Choice.{}:{}:{}".format(
221214
choice.type, prefix, positional.dest
@@ -226,9 +219,8 @@ def recurse(parser, prefix):
226219
prefix, i, choice_type2fn[choice.type]
227220
)
228221
)
229-
# If the choice is a dict, it represents a call to a subparser,
230-
# so add to the list of subparsers & recursively call the subparser
231222
elif isinstance(positional.choices, dict):
223+
# subparser, so append to list of subparsers & recurse
232224
log.debug("subcommand:%s", choice)
233225
if positional.choices[choice].add_help:
234226
discovered_subparsers.append(str(choice))
@@ -250,8 +242,8 @@ def recurse(parser, prefix):
250242
sub_nargs.extend(new_nargs)
251243
else:
252244
log.debug("skip:subcommand:%s", choice)
253-
# Otherwise, it's just a simple choice.
254245
else:
246+
# simple choice
255247
this_positional_choices.append(str(choice))
256248

257249
if this_positional_choices:
@@ -261,7 +253,7 @@ def recurse(parser, prefix):
261253
)
262254
)
263255

264-
# Lastly, skip default `nargs` values
256+
# skip default `nargs` values
265257
if positional.nargs not in (None, "1", "?"):
266258
nargs.append(u"{}_pos_{}_nargs={}".format(prefix, i, positional.nargs))
267259

@@ -273,72 +265,68 @@ def recurse(parser, prefix):
273265
)
274266
log.debug("subcommands:{}:{}".format(prefix, discovered_subparsers))
275267

276-
# Add relevant information for the optional arguments.
268+
# optional arguments
277269
option_strings.append(
278270
u"{}_option_strings=('{}')".format(
279271
prefix, "' '".join(get_option_strings(parser))
280272
)
281273
)
282274
for optional in parser._get_optional_actions():
283-
if optional != SUPPRESS:
284-
for option_string in optional.option_strings:
275+
if optional == SUPPRESS:
276+
continue
285277

286-
# Check for shtab completion functions.
287-
if hasattr(optional, "complete"):
288-
compgens.append(
289-
u"{}_{}_COMPGEN={}".format(
290-
prefix,
291-
wordify(option_string),
292-
complete2pattern(
293-
optional.complete, "bash", choice_type2fn
294-
),
295-
)
278+
for option_string in optional.option_strings:
279+
if hasattr(optional, "complete"):
280+
# shtab `.complete = ...` functions
281+
compgens.append(
282+
u"{}_{}_COMPGEN={}".format(
283+
prefix,
284+
wordify(option_string),
285+
complete2pattern(optional.complete, "bash", choice_type2fn),
296286
)
287+
)
297288

298-
# Check for choices.
299-
if optional.choices:
300-
this_optional_choices = []
301-
for choice in optional.choices:
302-
# If the choice is a special completion type,
303-
# add its info to compgens.
304-
# NOTE: if compgens were specified in the "complete"
305-
# attribute, this will overwrite them.
306-
if isinstance(choice, Choice):
307-
log.debug(
308-
"Choice.{}:{}:{}".format(
309-
choice.type, prefix, optional.dest
310-
)
311-
)
312-
compgens.append(
313-
u"{}_{}_COMPGEN={}".format(
314-
prefix,
315-
wordify(option_string),
316-
choice_type2fn[choice.type],
317-
)
289+
if optional.choices:
290+
# choices (including shtab `.complete` functions)
291+
this_optional_choices = []
292+
for choice in optional.choices:
293+
# append special completion type to `compgens`
294+
# NOTE: overrides `.complete` attribute
295+
if isinstance(choice, Choice):
296+
log.debug(
297+
"Choice.{}:{}:{}".format(
298+
choice.type, prefix, optional.dest
318299
)
319-
320-
# Otherwise, it's just a simple choice.
321-
else:
322-
this_optional_choices.append(str(choice))
323-
324-
if this_optional_choices:
325-
choices.append(
326-
u"{}_{}_choices='{}'".format(
300+
)
301+
compgens.append(
302+
u"{}_{}_COMPGEN={}".format(
327303
prefix,
328304
wordify(option_string),
329-
" ".join(this_optional_choices),
305+
choice_type2fn[choice.type],
330306
)
331307
)
308+
else:
309+
# simple choice
310+
this_optional_choices.append(str(choice))
332311

333-
# Check for nargs.
334-
if optional.nargs is not None and optional.nargs != 1:
335-
nargs.append(
336-
u"{}_{}_nargs={}".format(
337-
prefix, wordify(option_string), optional.nargs
312+
if this_optional_choices:
313+
choices.append(
314+
u"{}_{}_choices='{}'".format(
315+
prefix,
316+
wordify(option_string),
317+
" ".join(this_optional_choices),
338318
)
339319
)
340320

341-
# Add on the information obtained from subparsers.
321+
# Check for nargs.
322+
if optional.nargs is not None and optional.nargs != 1:
323+
nargs.append(
324+
u"{}_{}_nargs={}".format(
325+
prefix, wordify(option_string), optional.nargs
326+
)
327+
)
328+
329+
# append recursion results
342330
subparsers.extend(sub_subparsers)
343331
option_strings.extend(sub_option_strings)
344332
compgens.extend(sub_compgens)
@@ -351,9 +339,7 @@ def recurse(parser, prefix):
351339

352340

353341
@mark_completer("bash")
354-
def complete_bash(
355-
parser, root_prefix=None, preamble="", choice_functions=None,
356-
):
342+
def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None):
357343
"""
358344
Returns bash syntax autocompletion script.
359345
@@ -400,8 +386,7 @@ def complete_bash(
400386
echo "${1//[^[:word:]]/_}"
401387
}
402388
403-
# This function is called for the initial parser and any
404-
# subparsers that are found, to set default values.
389+
# set default values (called for the initial parser & any subparsers)
405390
_set_parser_defaults() {
406391
local subparsers_var="${prefix}_subparsers[@]"
407392
subparsers=${!subparsers_var}
@@ -415,9 +400,8 @@ def complete_bash(
415400
}
416401
417402
# $1=action identifier
418-
# $2=is positional action (boolean)
419-
# This function is called when a new action is encountered
420-
# to set all the identifiers for that action's parameters.
403+
# $2=positional action (bool)
404+
# set all identifiers for an action's parameters
421405
_set_new_action() {
422406
current_action="${prefix}_$(_shtab_replace_nonword $1)"
423407
@@ -434,19 +418,18 @@ def complete_bash(
434418
current_action_nargs=1
435419
fi
436420
437-
current_action_args_start_index=$(($word_index+1))
421+
current_action_args_start_index=$(( $word_index + 1 ))
438422
439423
current_action_is_positional=$2
440424
}
441425
442426
# Notes:
443-
# `COMPREPLY` contains what will be rendered after completion is triggered
444-
# `completing_word` refers to the currently typed word to generate completions for
445-
# `${!var}` is to evaluate the content of `var`
446-
# and expand its content as a variable
447-
# hello="world"
448-
# x="hello"
449-
# ${!x} -> ${hello} -> "world"
427+
# `COMPREPLY`: what will be rendered after completion is triggered
428+
# `completing_word`: currently typed word to generate completions for
429+
# `${!var}`: evaluates the content of `var` and expand its content as a variable
430+
# hello="world"
431+
# x="hello"
432+
# ${!x} -> ${hello} -> "world"
450433
{root_prefix}() {
451434
local completing_word="${COMP_WORDS[COMP_CWORD]}"
452435
COMPREPLY=()
@@ -456,34 +439,30 @@ def complete_bash(
456439
_set_parser_defaults
457440
word_index=1
458441
459-
# determined what arguments are appropriate for the current state
442+
# determine what arguments are appropriate for the current state
460443
# of the arg parser
461-
while [ $word_index -ne $COMP_CWORD ]
462-
do
463-
444+
while [ $word_index -ne $COMP_CWORD ]; do
464445
local this_word="${COMP_WORDS[$word_index]}"
465446
466-
# If we encounter a valid subcommand,
467-
# add it to the prefix and reset the current action
468447
if [[ -n $subparsers && " ${subparsers[@]} " =~ " ${this_word} " ]]; then
448+
# valid subcommand: add it to the prefix & reset the current action
469449
prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
470450
_set_parser_defaults
471451
fi
472452
473-
# Check to see if a new action should be acquired,
474-
# either because an option string is recognized,
475-
# or because no more input is expected from the current action,
476-
# indicating that the next positional action can fill in here.
477453
if [[ " ${current_option_strings[@]} " =~ " ${this_word} " ]]; then
454+
# a new action should be acquired (due to recognised option string or
455+
# no more input expected from current action);
456+
# the next positional action can fill in here
478457
_set_new_action $this_word false
479458
fi
480459
481460
if [[ "$current_action_nargs" != "*" ]] && \\
482461
[[ "$current_action_nargs" != "+" ]] && \\
483462
[[ "$current_action_nargs" != *"..." ]] && \\
484-
(( $word_index+1-$current_action_args_start_index >= \\
485-
$current_action_nargs )); then
486-
$current_action_is_positional && let "completed_positional_actions+=1"
463+
(( $word_index + 1 - $current_action_args_start_index >= \\
464+
$current_action_nargs )); then
465+
$current_action_is_positional && let "completed_positional_actions += 1"
487466
_set_new_action "pos_${completed_positional_actions}" true
488467
fi
489468
@@ -492,25 +471,14 @@ def complete_bash(
492471
493472
# Generate the completions
494473
495-
# Uncomment below for debugging.
496-
# echo ""
497-
# echo "Current subparsers: ${subparsers[@]}"
498-
# echo "Current option strings: ${current_option_strings[@]}"
499-
# echo "Current action: ${current_action}"
500-
# echo "Current action nargs: ${current_action_nargs}"
501-
# echo "Current action completed arguments:"
502-
# echo " $(( $word_index-$current_action_args_start_index ))"
503-
# echo "Current action choices: ${current_action_choices}"
504-
# echo "Current action compgen: ${current_action_compgen}"
505-
506-
# If an optional argument has started, use option strings
507474
if [[ "${completing_word}" == -* ]]; then
475+
# optional argument started: use option strings
508476
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
509-
# Otherwise, use choices and compgen
510477
else
478+
# use choices & compgen
511479
COMPREPLY=( $(compgen -W "${current_action_choices}" -- "${completing_word}"; \\
512-
[ -n "${current_action_compgen}" ] \\
513-
&& "${current_action_compgen}" "${completing_word}") )
480+
[ -n "${current_action_compgen}" ] \\
481+
&& "${current_action_compgen}" "${completing_word}") )
514482
fi
515483
516484
return 0
@@ -701,7 +669,7 @@ def format_positional(opt):
701669
),
702670
commands_case="\n ".join(
703671
"{cmd_orig}) _arguments ${root_prefix}_{cmd} ;;".format(
704-
cmd_orig=cmd, cmd=wordify(cmd), root_prefix=root_prefix,
672+
cmd_orig=cmd, cmd=wordify(cmd), root_prefix=root_prefix
705673
)
706674
for cmd in sorted(subcommands)
707675
),
@@ -725,7 +693,7 @@ def format_positional(opt):
725693

726694

727695
def complete(
728-
parser, shell="bash", root_prefix=None, preamble="", choice_functions=None,
696+
parser, shell="bash", root_prefix=None, preamble="", choice_functions=None
729697
):
730698
"""
731699
parser : argparse.ArgumentParser

0 commit comments

Comments
 (0)