Hi,

I’m attaching a bash completion script which performs completion for many, but
not all options and commands.

Specifically, it autocompletes the most common subcommands, but only provides
arguments autocompletion for only two of them, import-dsc and rpush, for
practical reasons.

For dgit options, it provides two-level completion for the most popular options,
excluding rarely used or dangerous ("use when you know what you’re doing") 
options.
The two-levels work in a way to not overwhelm the user with options when they 
Tab
twice, so only some but not all arguments to e.g. --quilt= are shown:

$ dgit --
--baredebian                                 --force-import-gitapply-no-absurd
--baredebian+git                             --force-reusing-version
--baredebian+tarball                         --force-unrepresentable
--build-products-dir=                        --force-unsupported-source-format
--clean                                      --force-uploading-binaries
--clean=dpkg-source                          --force-uploading-source-only
--clean=git                                  --gbp
--clean=git-ff                               --include-dirty
--damp-run                                   --new
--delayed=                                   --no-rm-on-error
--deliberately-fresh-repo                    --no-sign
--deliberately-include-questionable-history  --overwrite
--deliberately-not-fast-forward              --package
--dep14tag                                   --quilt
--distro=                                    --quilt=auto
--dpm                                        --quilt=linear
--dry-run                                    --rm-old-changes
--force-changes-origs-exactly                --save-dgit-view=
--force-dsc-changes-mismatch                 --split-view=
--force-import-dsc-with-dgit-field           --upstream-commitish=
--force-import-gitapply-absurd               

However, when the user types --quilt=, the rest of them is shown:

$ dgit --quilt=
auto            baredebian+git      dpm      linear       nofix      unapplied
baredebian      baredebian+tarball  gbp      nocheck      smash

For --upstream-commitish= the script autocompletes some tags, starting with tags
with the matching version, and the rest sorted by version:

$ dgit --upstream-commitish=upstream/1.
upstream/1.11.0  upstream/1.6.0

For options accepting both = and space (--quilt, --clean, --package) the 
completion
is performed for both versions; the list of all options above shows the 
"spaced" (--clean)
version and a couple of commonly used versions with = and an argument. For 
options
only accepting =, the option ends with = to allow the user to start typing the 
argument
directly after that.

-- 
Cheers,
  Andrej
# /usr/share/bash-completion/completions/dgit
# Bash command completion for ‘dgit(1)’.
# Documentation: ‘bash(1)’, section “Programmable Completion”.

# Author: Andrej Shadura <[email protected]>

# This file is in public domain when available or, alternatively,
# can be redistributed under the terms of CC0 1.0 Universal license.

# On Debian systems, the text of CC0 1.0 Universal can be found at
# /usr/share/common-licenses/CC0-1.0

_dgit()
{
    local cur prev words cword i _options special _prefix
    _init_completion -n = || return

    local clean_opts=(git{,\,always} git-ff{,\,always} check{,\,ignores} none
        dpkg-source{,\,no-check,\,all-check} 
dpkg-source-d{,\,no-check,\,all-check})
    local clean_popular_opts=(git git-ff dpkg-source)
    local standalone_quilt_opts=(gbp dpm baredebian{,+git,+tarball})
    local quilt_opts=(linear auto smash nofix nocheck unapplied 
${standalone_quilt_opts[@]})
    local quilt_popular_opts=(auto linear)
    local force_opts=(unrepresentable unsupported-source-format 
dsc-changes-mismatch
        changes-origs-exactly uploading-binaries uploading-source-only
        reusing-version import-gitapply-absurd import-gitapply-no-absurd
        import-dsc-with-dgit-field)
    local buildcommands="build sbuild gbp-build build-source pbuilder 
cowbuilder"
    local subcommands="clone fetch pull $buildcommands
        push push-source rpush setup-new-tree setup-useremail
        setup-mergechangelogs setup-gitattributes import-dsc update-vcs-git"

    for word in ${words[@]}
    do
        if [[ $word == @(${subcommands// /|}) ]]
        then
            special=$word
            break
        fi
    done

    if [ -n "$special" ] && [[ $special == @(${buildcommands// /|}) ]]
    then
        COMPREPLY=()
        return 0
    fi

    case "$prev" in
        --clean)
            COMPREPLY=($(compgen -W "${clean_opts[*]}" -- "$cur"))
            return 0
            ;;
        --quilt)
            COMPREPLY=($(compgen -W "${quilt_opts[*]}" -- "$cur"))
            return 0
            ;;
        --build-products-dir)
            COMPREPLY=($(compgen -o filenames -d -- "$cur"))
            return 0
            ;;
        -p|--package)
            COMPREPLY=()
            return 0
            ;;
        -k)
            COMPREPLY=($(compgen -W "$(gpg --list-secret-keys --with-colons | 
grep ^sec | cut -d: -f5)" -- "$cur"))
            return 0
            ;;
        import-dsc)
            COMPREPLY=($(compgen -o filenames -f -G '../*.dsc' -- "$cur"))
            return 0
            ;;
        rpush)
            _known_hosts_real -c -a -- "$cur"
            compopt -o nospace
            return 0
            ;;
    esac

    case "$cur" in
        --clean=*)
            COMPREPLY=($(compgen -W "${clean_opts[*]}" -- "${cur#*=}"))
            return 0
            ;;
        --quilt=*)
            COMPREPLY=($(compgen -W "${quilt_opts[*]}" -- "${cur#*=}"))
            return 0
            ;;
        --split-view=*)
            COMPREPLY=($(compgen -W "auto always never" -- "${cur#*=}"))
            return 0
            ;;
        --build-products-dir=*)
            COMPREPLY=($(compgen -o filenames -d -- "${cur#*=}"))
            return 0
            ;;
        --upstream-commitish=*)
            local version=$( (dpkg-parsechangelog -SVersion 2>/dev/null || 
true) | sed -e 's/-[^-]*$//' -e 's/^[0-9]*://')
            local thesetags=$([ -n "$version" ] && git tag --list "$version" 
"v$version" "upstream/$version" 2>/dev/null || true)
            local othertags=$( (git tag --list --sort version:refname '[0-9]*' 
'v[0-9]*' 'upstream/[0-9]*' 2>/dev/null || true) | grep -v -F "$version")
            COMPREPLY=($(compgen -W "$thesetags $othertags" -- "${cur#*=}"))
            compopt -o nosort
            return 0
            ;;
        --*=*)
            COMPREPLY=()
            return 0
            ;;
    esac

    if [[ "$cur" == -* ]]; then
        _options="--dry-run --damp-run --no-sign --new --include-dirty"
        _options+=" --overwrite --delayed= --save-dgit-view="
        _options+=" --deliberately-not-fast-forward"
        _options+=" --deliberately-include-questionable-history"
        _options+=" --deliberately-fresh-repo"
        _options+=" --distro= --split-view= --upstream-commitish="
        _options+=" --rm-old-changes --build-products-dir="
        _options+=" --package -p --dep14tag --no-rm-on-error -k"
        _options+=" --clean ${clean_popular_opts[*]/#/--clean=}"
        _options+=" ${standalone_quilt_opts[*]/#/--}"
        _options+=" --quilt ${quilt_popular_opts[*]/#/--quilt=}"
        _options+=" ${force_opts[*]/#/--force-}" 
        COMPREPLY=($(compgen -W "${_options}" -- "$cur"))
        # tell bash to not put a space afrer options ending with =
        # so that the user can type the argument directly after it
        if [ ${#COMPREPLY[@]} = 1 ] && [[ "${COMPREPLY[0]}" == *= ]]
        then
            compopt -o nospace
        fi
    else
        if [ -z "$special" ]
        then
            COMPREPLY=($(compgen -W "$subcommands" -- "$cur"))
        else
            # if nothing explicitly handled these commands above,
            # just don’t autocomplete at all
            COMPREPLY=()
        fi
    fi

    return 0
} &&
complete -F _dgit dgit

# vim: fileencoding=utf-8 filetype=sh expandtab shiftwidth=4 :

Reply via email to