contrib/bash_completion
author Thomas Arendsen Hein <thomas@intevation.de>
Mon, 13 Mar 2006 13:05:41 +0100
changeset 1933 7544700fd931
parent 1888 283d2ab1e020
child 2034 5e7aff1b6ae1
permissions -rw-r--r--
Use 'hg ci -d "1000000 0"' in tests to circumvent problem with leading zero. Some systems show "Thu Jan 01" instead of "Thu Jan 1", which breaks tests. Using "1000000" yields "Mon Jan 12 13:46:40 1970", which looks the same on all systems.

shopt -s extglob

_hg_option_list()
{
    "$hg" -v help $1 2>/dev/null | \
	awk '/^ *-/ {
		for (i = 1; i <= NF; i ++) {
		    if (index($i, "-") != 1)
			break;
		    print $i;
		}
	    }'
}


_hg_commands()
{
    local commands
    commands="$("$hg" debugcomplete "$cur" 2>/dev/null)" || commands=""
    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur"))
}

_hg_paths()
{
    local paths="$("$hg" paths 2>/dev/null | sed -e 's/ = .*$//')"
    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur"))
}

_hg_repos()
{
    local i
    for i in $(compgen -d -- "$cur"); do
	test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
    done
}

_hg_status()
{
    local files="$("$hg" status -n$1 . 2>/dev/null)"
    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
}

_hg_tags()
{
    local tags="$("$hg" tags 2>/dev/null |
	sed -e 's/[0-9]*:[a-f0-9]\{40\}$//; s/ *$//')"
    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
}

# this is "kind of" ugly...
_hg_count_non_option()
{
    local i count=0
    local filters="$1"

    for ((i=1; $i<=$COMP_CWORD; i++)); do
	if [[ "${COMP_WORDS[i]}" != -* ]]; then
	    if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
		continue
	    fi
	    count=$(($count + 1))
	fi
    done

    echo $(($count - 1))
}

_hg()
{
    local cur prev cmd opts i
    # global options that receive an argument
    local global_args='--cwd|-R|--repository'
    local hg="$1"

    COMPREPLY=()
    cur="$2"
    prev="$3"

    # searching for the command
    # (first non-option argument that doesn't follow a global option that
    #  receives an argument)
    for ((i=1; $i<=$COMP_CWORD; i++)); do
	if [[ ${COMP_WORDS[i]} != -* ]]; then
	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
		cmd="${COMP_WORDS[i]}"
		break
	    fi
	fi
    done

    if [[ "$cur" == -* ]]; then
	opts=$(_hg_option_list $cmd)

	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
	return
    fi

    # global options
    case "$prev" in
	-R|--repository)
	    _hg_repos
	    return
	;;
	--cwd)
	    # Stick with default bash completion
	    return
	;;
    esac

    if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
	_hg_commands
	return
    fi

    # canonicalize command name
    cmd=$("$hg" -q help "$cmd" 2>/dev/null | sed -e 's/^hg //; s/ .*//; 1q')

    if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" = --rev ]; then
	_hg_tags
	return
    fi

    case "$cmd" in
	help)
	    _hg_commands
	;;
	export|manifest|update)
	    _hg_tags
	;;
	pull|push|outgoing|incoming)
	    _hg_paths
	    _hg_repos
	;;
	paths)
	    _hg_paths
	;;
	add)
	    _hg_status "u"
	;;
	commit)
	    _hg_status "mar"
	;;
	remove)
	    _hg_status "d"
	;;
	forget)
	    _hg_status "a"
	;;
	diff)
	    _hg_status "mar"
	;;
	revert)
	    _hg_status "mard"
	;;
	clone)
	    local count=$(_hg_count_non_option)
	    if [ $count = 1 ]; then
		_hg_paths
	    fi
	    _hg_repos
	;;
	debugindex|debugindexdot)
	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
	;;
	debugdata)
	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
	;;
    esac

}

complete -o bashdefault -o default -F _hg hg 2>/dev/null \
    || complete -o default -F _hg hg