iterative / shtab

↔️ Automagic shell tab completion for Python CLI applications
https://docs.iterative.ai/shtab
Other
362 stars 35 forks source link

[bug] REMAINDER miss a `:` #125

Open Freed-Wu opened 1 year ago

Freed-Wu commented 1 year ago

The following example comes from /usr/share/zsh/functions/Completion/Unix/_sudo

file a:

#!/usr/bin/env python
from argparse import ArgumentParser
import shtab

parser = ArgumentParser()
shtab.add_argument_to(parser)
parser.add_argument("command", nargs=1).complete = {"zsh": "{_command_names -e}"}
parser.add_argument("args", nargs="...").complete = {"zsh": "_normal"}
parser.parse_args()
$ ./a --print-completion zsh | sudo tee /usr/share/zsh/site-functions/_a
#compdef a

# AUTOMATICALLY GENERATED by `shtab`

_shtab_a_commands() {
  local _commands=(

  )
  _describe 'a commands' _commands
}

_shtab_a_options=(
  "(- : *)"{-h,--help}"[show this help message and exit]"
  "(- : *)--print-completion[print shell completion script]:print_completion:(bash zsh tcsh)"
  ":command:{_command_names -e}"
  "(-)*:args:_normal"
)

_shtab_a() {
  local context state line curcontext="$curcontext" one_or_more='(-)*' remainder='(*)'

  if ((${_shtab_a_options[(I)${(q)one_or_more}*]} + ${_shtab_a_options[(I)${(q)remainder}*]} == 0)); then  # noqa: E501
    _shtab_a_options+=(': :_shtab_a_commands' '*::: :->a')
  fi
  _arguments -C $_shtab_a_options

  case $state in
    a)
      words=($line[1] "${words[@]}")
      (( CURRENT += 1 ))
      curcontext="${curcontext%:*:*}:_shtab_a-$line[1]:"
      case $line[1] in

      esac
  esac
}

typeset -A opt_args
_shtab_a "$@"

command will complete all executable command, and normal will complete its arguments

We got error:

$ a ls <TAB>
_tags:comptags:60: nesting level too deep

If we change

  "(-)*:args:_normal"

to

  "(-)*::args:_normal"

The nested bug can disappear. Refer https://github.com/zsh-users/zsh/blob/a9386df5581487e5e34ecb3ce422bacf62d10c3d/Completion/Unix/Command/_sudo#L61-L62:

    "(-)1: :{ $cpp; _command_names -e }"
    "*:: :{ $cpp; _normal }"

It is https://github.com/iterative/shtab/blob/main/shtab/__init__.py#L497 REAMINDER can be *: or (-)*:.