diff --git a/shtab/__init__.py b/shtab/__init__.py index e29a2e9..a8b09bb 100644 --- a/shtab/__init__.py +++ b/shtab/__init__.py @@ -745,13 +745,15 @@ def recurse_parser(cparser, positional_idx, requirements=None): elif optional_str.startswith('-'): optionals_single.add(optional_str[1:]) specials.extend(get_specials(optional, 'n', optional_str)) + if optional.nargs != 0: + specials.extend(get_specials(optional, 'c', optional_str + '=')) for positional in cparser._get_positional_actions(): if positional.help != SUPPRESS: positional_idx += 1 log.debug("%s| Positional #%d: %s", log_prefix, positional_idx, positional.dest) index_choices[positional_idx][tuple(requirements)] = positional - if not requirements and isinstance(positional.choices, dict): + if isinstance(positional.choices, dict): for subcmd, subparser in positional.choices.items(): log.debug("%s| | SubParser: %s", log_prefix, subcmd) recurse_parser(subparser, positional_idx, requirements + [subcmd]) @@ -767,14 +769,25 @@ def recurse_parser(cparser, positional_idx, requirements=None): # Multiple requirements nlist = [] for nn, arg in ndict.items(): + max_idx = len(nn) + 1 + checks = [f'("$cmd[{iidx}]" == "{n}")' for iidx, n in enumerate(nn, start=2)] + condition = f"$#cmd >= {max_idx} && " + " && ".join(checks) if 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}`@'") + choices_str = ' '.join(map(str, arg.choices)) + nlist.append(f"if ( {condition} ) echo {choices_str}") + elif hasattr(arg, "complete"): + complete_fn = complete2pattern(arg.complete, "tcsh", choice_type2fn) + if complete_fn: + if complete_fn.startswith("`") and complete_fn.endswith("`"): + func_name = complete_fn.strip("`") + nlist.append(f"if ( {condition} ) eval {func_name}") + else: + nlist.append(f"if ( {condition} ) {complete_fn}") + if nlist: + nlist_str = "; ".join(nlist) + padding = '"" "" "" "" "" "" "" "" ""' + specials.append( + f"'p@{str(idx)}@`set cmd=(\"$COMMAND_LINE\" {padding}); {nlist_str}`@'") if optionals_double: if optionals_single: @@ -783,6 +796,9 @@ def recurse_parser(cparser, positional_idx, requirements=None): # Don't add a space after completing "--" from "-" optionals_single = ('-', '-') + # removes duplicates from list, preserves order + specials = list(dict.fromkeys(specials)) + return Template("""\ # AUTOMATICALLY GENERATED by `shtab`