kislyuk / argcomplete

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

zsh: external-argcomplete-script does not work on register-python-argcomplete #452

Closed dibalavs closed 8 months ago

dibalavs commented 8 months ago

Example:

test.sh:

complete_func() {
    echo "complete func called" > done.txt
}

eval "$(register-python-argcomplete -e complete_func arc_test)"

next in zsh shell do next steps:

source test.sh
arc_test <tab><tab>

Expected result: file done.txt with "complete func called" message exists

Actual result: no file

On bash - this code works.

Environment: lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy

pip show argcomplete Name: argcomplete Version: 3.1.2 Summary: Bash tab completion for argparse Home-page: https://github.com/kislyuk/argcomplete Author: Andrey Kislyuk Author-email: kislyuk@gmail.com License: Apache Software License Location: /home/dybala/.local/lib/python3.10/site-packages Requires: Required-by:

python --version Python 3.10.12

zsh --version zsh 5.8.1 (x86_64-ubuntu-linux-gnu)

bash --version GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

kislyuk commented 8 months ago

Thanks for reporting and opening a PR. Curious, what is the purpose of using argcomplete if the script supplying the completions is a shell script? Why not register that natively with the shell directly?

I appreciate that -e is not working as expected with zsh, but I'm trying to better understand how people use -e in general.

dibalavs commented 8 months ago

Hello. My use cases: 1) I have script.py and some aliases to useful commands:

alias scmd1='script.py cmd1'
alias scmd1='script.py cmd1'
...
alias scmdn='script.py cmdN'

As you know, bash does not complete aliased and zsh tries to complete them but with very strange result. I do next script:

# $1 - alias name
# $2 - target commands
__gen_completion_func() {
    eval "
    __completion_$1()
    {
        local _alias=$1
        local aliaslen=\${#_alias}
        local realcmd=\"$2\"
        local realcmdlen=\${#realcmd}
        COMP_POINT=\$(expr \$COMP_POINT - \$aliaslen + \$realcmdlen)
        COMP_LINE=\"\${realcmd}\${COMP_LINE:\$aliaslen}\"

        script.py
    }"

    eval "$(register-python-argcomplete -e __completion_$1 $1)"
}

# and call it:
__gen_completion_func scmd1  "script.py cmd1"
__gen_completion_func scmd2  "script.py cmd2"
...

for zsh you also need setopt completealias

2) I have some command: scripty.py dir which get name of component and return location of it. to make cd onto location I use next shell function:

kcd() {
    dir=$(script.py dir $1) && cd $dir;
}

# and use previous function to generate completion:
__gen_completion_func kcd  "script.py dir"