kislyuk / argcomplete

Python and tab completion, better together.
https://kislyuk.github.io/argcomplete/
Apache License 2.0
1.39k stars 129 forks source link

Messes with default zsh completion for redirects. #454

Closed jmcantrell closed 8 months ago

jmcantrell commented 8 months ago

I recently installed pipx and this was a required dependency. Some time after that, I discovered that zsh completion after the redirect operator was not working. After some assistance from #zsh, it seems like argcomplete may be the culprit.

Here's the completion trace after trying to complete an empty redirection (>./<tab>) from zsh (with no configuration, and just compinit run):

+_complete_debug:24> : zsh 5.9
+_complete_debug:25> _main_complete
+_main_complete:11> local IFS=$' \t\n\C-@'
+_main_complete:25> eval $'local -A _comp_caller_options;\n             _comp_caller_options=(${(kv)options[@]});\n             setopt localoptions localtraps localpatterns ${_comp_options[@]};\n             local IFS=$\' \\t\\r\\n\\0\';\n             builtin enable -p \\| \\~ \\( \\? \\* \\[ \\< \\^ \\# 2>&-;\n             exec </dev/null;\n             trap - ZERR;\n             local -a reply;\n             local REPLY;\n             local REPORTTIME;\n             unset REPORTTIME'
 +(eval):1> local -A _comp_caller_options
 +(eval):2> _comp_caller_options=( posixargzero off autolist on shortrepeat off printexitvalue off kshzerosubscript off histreduceblanks off chaselinks off extendedglob on localloops off histnostore off automenu on globcomplete off unset on listpacked off promptsubst off shwordsplit off pathdirs off kshtypeset off listtypes on warncreateglobal off promptbang off dotglob off braceexpand on listbeep on correctall off privileged off numericglobsort off histverify off trackall on histsubstpattern off globstarshort off cbases off rcquotes off posixaliases off histfindnodups off bashautolist off sharehistory off overstrike off kshautoload off incappendhistory off appendcreate off promptcr on mailwarn off pushdignoredups off interactive on ignoreeof off globsubst off rematchpcre off monitor on histsavebycopy on clobberempty off histbeep on debugbeforecmd on magicequalsubst off rmstarsilent off posixjobs off hashcmds on posixtraps off extendedhistory off notify on kshoptionprint off histexpiredupsfirst off glob on posixcd off braceccl off badpattern on longlistjobs off banghist on dvorak off alwaystoend off hashall on warnnestedvar off globalexport on ksharrays off correct off cdsilent off autonamedirs off histexpand on typesetsilent off rmstarwait off histnofunctions off autoparamslash on trapsasync off sunkeyboardhack off promptsp on histsavenodups off autocd off allexport off posixidentifiers off cshjunkiehistory off autopushd off completeinword off completealiases off aliases off autocontinue off appendhistory on aliasfuncdef off singlelinezle off hashlistall on ignoreclosebraces off recexact off localoptions on interactivecomments off errexit off cshjunkiequotes off markdirs off hashdirs on cdablevars off rcexpandparam on vi off printeightbit off multifuncdef on xtrace on login off cshjunkieloops off histappend on histignorespace off evallineno on shfileexpansion off rcs off functionargzero on errreturn off combiningchars off histignoredups off histfcntllock off beep on autoremoveslash on hup on globdots off checkrunningjobs on autoparamkeys on shnullcmd off multibyte on zle on promptpercent on flowcontrol on continueonerror off incappendhistorytime off autoresume off globassign off caseglob on shortloops on bsdecho off cprecedences off log on transientrprompt off verbose off localpatterns on ignorebraces off pipefail off equals on menucomplete off cshnullglob off casematch on promptvars off histallowclobber off bareglobqual on shinstdin on restricted off pushdminus off nullglob on chasedots off mailwarning off listambiguous on cshnullcmd off bashrematch off octalzeroes off forcefloat off exec on multios on emacs off nomatch on pathscript off localtraps on stdin on onecmd off kshglob off clobber on posixbuiltins off alwayslastprompt on pushdtohome off histignorealldups off hashexecutablesonly off pushdsilent off casepaths off shoptionletters off physical off sourcetrace off typesettounset off histlexwords off bgnice on globalrcs on posixstrings off checkjobs on shglob off singlecommand off listrowsfirst off ) 
 +(eval):3> setopt localoptions localtraps localpatterns bareglobqual extendedglob glob multibyte multifuncdef nullglob rcexpandparam unset NO_allexport NO_aliases NO_cshnullglob NO_cshjunkiequotes NO_errexit NO_errreturn NO_globassign NO_globsubst NO_histsubstpattern NO_ignorebraces NO_ignoreclosebraces NO_kshglob NO_ksharrays NO_kshtypeset NO_markdirs NO_octalzeroes NO_posixbuiltins NO_posixidentifiers NO_shwordsplit NO_shglob NO_typesettounset NO_warnnestedvar NO_warncreateglobal
 +(eval):4> local IFS=$' \t\C-M\n\C-@'
 +(eval):5> enable -p '|' '~' '(' '?' '*' '[' '<' '^' '#'
 +(eval):7> trap - ZERR
 +(eval):8> local -a reply
 +(eval):9> local REPLY
 +(eval):10> local REPORTTIME
 +(eval):11> unset REPORTTIME
+_main_complete:27> local func funcs ret=1 tmp _compskip format nm call match min max i num _completers _completer _completer_num curtag _comp_force_list _matchers _matcher _c_matcher _matcher_num _comp_tags _comp_mesg mesg str context state state_descr line opt_args val_args curcontext='' _last_nmatches=-1 _last_menu_style _def_menu_style _menu_style sel _tags_level=0 _saved_exact='' _saved_lastprompt=yes _saved_list=ambiguous _saved_insert=automenu-unambiguous _saved_colors='' _saved_colors_set=0 _ambiguous_color=''
+_main_complete:42> local _comp_priv_prefix
+_main_complete:43> unset _comp_priv_prefix
+_main_complete:46> local -a precommands
+_main_complete:52> local -ar builtin_precommands=( - builtin eval exec nocorrect noglob time )
+_main_complete:54> typeset -U _lastdescr _comp_ignore _comp_colors
+_main_complete:58> [[ -z '' ]]
+_main_complete:58> curcontext=::: 
+_main_complete:60> zstyle -s :completion::::: insert-tab tmp
+_main_complete:60> tmp=yes 
+_main_complete:62> [[ yes = *pending(|[[:blank:]]*) || yes = *pending=(#b)([0-9]##)(|[[:blank:]]*) ]]
+_main_complete:70> [[ automenu-unambiguous = tab* ]]
+_main_complete:83> [[ '' = \* ]]
+_main_complete:93> [[ -z '' ]]
+_main_complete:94> [[ -o equals ]]
+_main_complete:94> compset -P 1 '='
+_main_complete:96> [[ ./ != */* ]]
+_main_complete:114> _setup default
 +_setup:3> local val nm=0
 +_setup:5> [[ 1 -eq 1 ]]
 +_setup:5> 2=default 
 +_setup:7> zstyle -a :completion:::::default list-colors val
 +_setup:21> [[ default = default ]]
 +_setup:22> unset ZLS_COLORS ZLS_COLOURS
 +_setup:27> zstyle -s :completion:::::default show-ambiguity val
 +_setup:32> zstyle -t :completion:::::default list-packed
 +_setup:34> [[ 2 -eq 1 ]]
 +_setup:37> compstate[list]=ambiguous 
 +_setup:40> zstyle -t :completion:::::default list-rows-first
 +_setup:42> [[ 2 -eq 1 ]]
 +_setup:45> compstate[list]=ambiguous 
 +_setup:48> zstyle -t :completion:::::default last-prompt
 +_setup:50> [[ 2 -eq 1 ]]
 +_setup:53> compstate[last_prompt]=yes 
 +_setup:56> zstyle -t :completion:::::default accept-exact
 +_setup:58> [[ 2 -eq 1 ]]
 +_setup:61> compstate[exact]='' 
 +_setup:64> [[ _last_nmatches -ge 0 ]]
 +_setup:67> zstyle -a :completion:::::default menu val
 +_setup:71> _last_nmatches=-1 
 +_setup:74> [[ '' != always ]]
 +_setup:75> zstyle -s :completion:::::default force-list val
+_main_complete:115> _def_menu_style=( '' ) 
+_main_complete:124> _last_menu_style=( ) 
+_main_complete:126> zstyle -s :completion:::::default list-prompt tmp
+_main_complete:130> zstyle -s :completion:::::default select-prompt tmp
+_main_complete:134> zstyle -s :completion:::::default select-scroll tmp
+_main_complete:141> ((  0  ))
+_main_complete:153> zstyle -a :completion::::: completer _completers
+_main_complete:154> _completers=( _complete _ignored ) 
+_main_complete:159> _completer_num=1 
+_main_complete:162> integer SECONDS=0
+_main_complete:176> funcs=( ) 
+_main_complete:177> compprefuncs=( ) 
+_main_complete:182> tmp=_complete
+_main_complete:184> [[ -n '' ]]
+_main_complete:186> [[ _complete = *:-* ]]
+_main_complete:189> [[ _complete = *:* ]]
+_main_complete:193> _completer=complete 
+_main_complete:196> curcontext=:complete:: 
+_main_complete:197> zstyle -t :completion::complete::: show-completer
+_main_complete:200> zstyle -a :completion::complete::: matcher-list _matchers
+_main_complete:201> _matchers=( '' ) 
+_main_complete:203> _matcher_num=1 
+_main_complete:204> _matcher='' 
+_main_complete:205> _c_matcher=
+_main_complete:206> [[ '' == +* ]]
+_main_complete:209> _matcher='' 
+_main_complete:212> _comp_mesg='' 
+_main_complete:213> [[ -n '' ]]
+_main_complete:218> _complete
 +_complete:7> local comp name oldcontext ret=1 service
 +_complete:8> typeset -T curcontext=:complete:: ccarray
 +_complete:10> oldcontext=:complete:: 
 +_complete:14> [[ -n '' ]]
 +_complete:96> comp=_first 
 +_complete:97> [[ -n _first ]]
 +_complete:98> service=-first- 
 +_complete:99> ccarray[3]=-first- 
 +_complete:100> eval _first
  +(eval):1> _first
 +_complete:100> ret=0 
 +_complete:101> [[ '' = all ]]
 +_complete:110> [[ -n '' ]]
 +_complete:114> ret=1 
 +_complete:115> [[ redirect = command ]]
 +_complete:122> local cname=-redirect-
 +_complete:124> ccarray[3]=-redirect- 
 +_complete:126> comp=_redirect 
 +_complete:127> service=-redirect- 
 +_complete:131> [[ -z _redirect ]]
 +_complete:139> [[ -n _redirect ]]
 +_complete:139> eval _redirect
  +(eval):1> _redirect
   +_redirect:3> local strs _comp_command1 _comp_command2 _comp_command
   +_redirect:5> _set_command
    +_set_command:6> local command
    +_set_command:8> command=./ 
    +_set_command:10> [[ -z ./ ]]
    +_set_command:12> ((  0 + 0  ))
    +_set_command:15> [[ . = \= ]]
    +_set_command:19> [[ ./ = ..#/* ]]
    +_set_command:20> _comp_command1=/tmp/./ 
    +_set_command:21> _comp_command2=. 
    +_set_command:22> _comp_command=. 
   +_redirect:7> strs=( -default- ) 
   +_redirect:9> [[ 1 != 1 ]]
   +_redirect:18> _dispatch '-redirect-,>,-default-' -redirect-,-default-,-default-
    +_dispatch:3> local comp pat val name i ret=1 _compskip=''
    +_dispatch:4> local curcontext=:complete:-redirect-: service str noskip
    +_dispatch:5> local -a match mbegin mend
    +_dispatch:9> [[ '-redirect-,>,-default-' = -s ]]
    +_dispatch:14> [[ -z '' ]]
    +_dispatch:14> _compskip='' 
    +_dispatch:16> curcontext=':complete:-redirect-,>,-default-:' 
    +_dispatch:18> shift
    +_dispatch:22> [[ '' != (all|*patterns*) ]]
    +_dispatch:24> str=-redirect-,-default-,-default-
    +_dispatch:25> [[ -n -redirect-,-default-,-default- ]]
    +_dispatch:26> service=-redirect-,-default-,-default- 
    +_dispatch:45> ret=1 
    +_dispatch:46> str=-redirect-,-default-,-default-
    +_dispatch:47> [[ -n -redirect-,-default-,-default- ]]
    +_dispatch:51> str=-redirect-,-default-,-default- 
    +_dispatch:52> name=-redirect-,-default-,-default- 
    +_dispatch:53> comp=_files 
    +_dispatch:54> service=-redirect-,-default-,-default- 
    +_dispatch:56> [[ -z _files ]]
    +_dispatch:56> break
    +_dispatch:61> [[ -n _files && -redirect-,-default-,-default- != -redirect-,-default-,-default- ]]
    +_dispatch:67> [[ '' != (all|*patterns*) ]]
    +_dispatch:68> str=-redirect-,-default-,-default-
    +_dispatch:69> [[ -n -redirect-,-default-,-default- ]]
    +_dispatch:70> service=-redirect-,-default-,-default- 
    +_dispatch:71> i=_python-argcomplete
    +_dispatch:72> _compskip=default 
    +_dispatch:73> eval _python-argcomplete
     +(eval):1> _python-argcomplete
      +_python-argcomplete:232> [[ -z 5.9 ]]
      +_python-argcomplete:235> compdef _python_argcomplete_global -P '*'
       +compdef:1> local opt autol type func delete eval new i ret=0 cmd svc
       +compdef:2> local -a match mbegin mend
       +compdef:4> emulate -L zsh
       +compdef:5> setopt extendedglob
       +compdef:9> ((  ! 3  ))
       +compdef:14> getopts anpPkKde opt
       +compdef:38> shift OPTIND-1
       +compdef:40> ((  ! 3  ))
       +compdef:45> [[ -z '' ]]
       +compdef:49> [[ -z '' ]]
       +compdef:49> [[ _python_argcomplete_global = *=* ]]
       +compdef:79> func=_python_argcomplete_global 
       +compdef:80> [[ -n '' ]]
       +compdef:81> shift
       +compdef:83> case  (widgetkey)
       +compdef:83> case  (key)
       +compdef:83> case  (*)
       +compdef:131> ((  2  ))
       +compdef:132> [[ -P = -N ]]
       +compdef:134> [[ -P = -p ]]
       +compdef:136> [[ -P = -P ]]
       +compdef:137> type=postpattern 
       +compdef:169> shift
       +compdef:131> ((  1  ))
       +compdef:132> [[ '*' = -N ]]
       +compdef:134> [[ '*' = -p ]]
       +compdef:136> [[ '*' = -P ]]
       +compdef:139> case postpattern (pattern)
       +compdef:139> case postpattern (postpattern)
       +compdef:148> [[ '*' = (#b)(*)=(*) ]]
       +compdef:151> _postpatcomps[$1]=_python_argcomplete_global 
       +compdef:169> shift
       +compdef:131> ((  0  ))
    +_dispatch:73> ret=0 
    +_dispatch:74> [[ default = *patterns* ]]
    +_dispatch:76> [[ default = all ]]
    +_dispatch:84> [[ -redirect-,-default-,-default- = -redirect-,-default-,-default- && -n _files && default != (all|*default*) ]]
    +_dispatch:89> _compskip='' 
    +_dispatch:91> return ret
 +_complete:139> ret=0 
 +_complete:142> _compskip='' 
 +_complete:144> return ret
+_main_complete:219> ret=0 
+_main_complete:220> break 2
+_main_complete:229> curcontext=::: 
+_main_complete:230> [[ '' = keep ]]
+_main_complete:236> nm=0 
+_main_complete:239> [[ '' = keep || nm -gt 1 ]]
+_main_complete:354> [[ nm -lt 1 && -n '' ]]
+_main_complete:357> [[ nm -eq 0 && -z '' && 0 -ne 0 ]]
+_main_complete:377> [[ -n '' ]]
+_main_complete:384> [[ '' = always || '' = ?* ]]
+_main_complete:390> [[ '' = keep ]]
+_main_complete:396> ((  0  ))
+_main_complete:399> unset ZLS_COLORS
+_main_complete:405> funcs=( ) 
+_main_complete:406> comppostfuncs=( ) 
+_main_complete:411> _lastcomp=( list_lines 0 all_quotes '\' nmatches 0 redirect '>' restore auto context redirect vared '' unambiguous '' list_max 100 unambiguous_cursor 1 list ambiguous insert_positions '' unambiguous_positions '' exact '' to_end match last_prompt yes pattern_insert menu ignored 0 insert automenu-unambiguous ) 
+_main_complete:412> _lastcomp[nmatches]=0 
+_main_complete:413> _lastcomp[completer]=complete 
+_main_complete:414> _lastcomp[prefix]=./ 
+_main_complete:415> _lastcomp[suffix]='' 
+_main_complete:416> _lastcomp[iprefix]='' 
+_main_complete:417> _lastcomp[isuffix]='' 
+_main_complete:418> _lastcomp[qiprefix]='' 
+_main_complete:419> _lastcomp[qisuffix]='' 
+_main_complete:420> _lastcomp[tags]='' 
+_main_complete:422> return ret
+_complete_debug:26> integer ret=0
+_complete_debug:27> unsetopt xtrace

If you look through this output, you'll see the completion for argcomplete referenced.

kislyuk commented 8 months ago

OK, I have released argcomplete v3.1.4 which I believe has a fix for this issue. Please test and let me know if that works for you. Keep in mind you'll need to reinstall the global completion script by running activate-global-python-argcomplete.

jmcantrell commented 8 months ago

I'm using the homebrew formula. I've never run that before. Will it not install the completion script with the updated formula? Either way, the completion seems to be working after updating, but _python-argcomplete is still referenced in the trace. Why is this necessary? I apologize if I'm not understanding this. I only discovered it was installed after installing pipx. Is there a way to disable this feature? I'd prefer that this function not be called in this context, especially if it's not necessary.

kislyuk commented 8 months ago

You activated argcomplete global completion at some point in the past. You can read about it in this library's readme file, but yes it does get invoked as part of the default shell completion framework. You can disable global completion in zsh by locating the script:

for p in "${fpath[@]}"; do ls $p/_python-argcomplete; done

then deleting it.

jmcantrell commented 8 months ago

Ok, thanks for the fix.