Trouble with completer

I decided to play around with a very simple completer script (see minecraft-server-jdstrand from edge):

#!/usr/bin/env bash

_have minecraft-server-jdstrand.util && {
    _mcutil_complete() {
        COMPREPLY=()
        if [[ ${COMP_WORDS[COMP_CWORD]} == -* ]]; then
            return 0
        elif [ $COMP_CWORD -eq 1 ]; then
            mcutil_cmds="start backup cmd console log status help usage"
            COMPREPLY=( $(compgen -W "$mcutil_cmds" -- ${COMP_WORDS[COMP_CWORD]}) )
            return 0
        fi
        # stop completing after the first arg
        COMPREPLY=( "" )
    }
}

complete -o default -F _mcutil_complete minecraft-server-jdstrand.util mcutil

snapctaft.yaml excerpt:

name: minecraft-server-jdstrand
...
apps:
  util:
    command: command-util.wrapper
    completer: mcutil.bash
...

If I copy mcutil.bash to /etc/bash_completion.d/mcutil and open a new terminal, then completion works as expected (ie, it doesn’t do a directory listing and only outputs mcutil_cmds). If I remove that and install the snap from edge it does not on classic or Ubuntu core (snap version reports 2.30 on both). I have tried to source /usr/lib/snapd/completer.sh and /snap/core/current/usr/lib/snapd/completer.sh and it didn’t work.

I feel like I am missing something obvious since I’m running 2.30 now…

One thing that might be happen is that you’ve loaded an old complete.sh (or something that defines _complete_from_snap; I had at one point inadvertently left a file in /etc/bash_completion.d/snapd), and that’s defined _complete_from_snap and the later, newer complete.sh doesn’t overwrite it. If you set -x and try the completion you might see an error from etelpmoc.sh about its arity; if so, see if you can find what’s loading an old complete.sh and stop it.


On install, snapd should be creating /usr/share/bash-completion/completions/minecraft-server-jdstrand.util which should be a symlink to the complete.sh from core (e.g. /snap/core/current/usr/lib/snapd/complete.sh); when you create a manual alias it should symlink the alias name to the canonical name. The usual bash completion mechanism should pick that up automatically, you should no longer need to source complete.sh by hand yourself.

~$ ls -l /usr/share/bash-completion/completions/http
ls: cannot access '/usr/share/bash-completion/completions/http': No such file or directory
~$ snap install http
http 0.9.9-1 from 'chipaca' installed
~$ ls -l /usr/share/bash-completion/completions/http
lrwxrwxrwx 1 root root 44 Dec 23 16:04 /usr/share/bash-completion/completions/http -> /snap/core/current/usr/lib/snapd/complete.sh
~$ snap alias http h
Added:
  - http as h
~$ ls -l /usr/share/bash-completion/completions/h
lrwxrwxrwx 1 root root 4 Dec 23 16:04 /usr/share/bash-completion/completions/h -> http

I’m not sure where it’s falling down, but this should get you looking in the right places at least.

To debug, first see if snap run is being able to run your completer script as expected, e.g.

snap run --command=complete http 9 9 5 1 $' \n' 'http ' http ''

(those weird numbers are $COMP_TYPE, $COMP_KEY, $COMP_POINT, $COMP_CWORD; they’re explained in bash(1) as are the following but slightly less obscure $COMP_WORDBREAKS, $COMP_LINE and $COMP_WORDS)

Then you can also use complete -p <command> to see if it’s picking up the right snippet, and complete -r <command> to clear it if it’s messed up.

You can also use set -x before hitting tab to bask in the glory of it all. Wear sunscreen.

:santa:

Thanks for all of this info. I didn’t have a stray _complete_from_snap and I did have the symlinks you mentioned for the command and the manual alias. It turns out I had a bug in my script but didn’t have enough info to debug it. Your response helped me debug it. Thanks!

@chipaca - you are probably aware of this, but Ubuntu Core images’ /usr/share/bash-completion/completions is still read-only so the symlinks cannot be created there.