#!/bin/bash list_branches() { git for-each-ref refs/heads --format="%(refname:short)" } list_tracked() { git ls-tree HEAD | grep blob | awk '{print $4}'; git ls-tree HEAD | grep tree | awk '{print $4"/"}'; } list_untracked() { git ls-files --exclude-standard --other --directory --no-empty-directory } list_modified() { git ls-files --modified } list_staged() { git diff --name-only --relative --cached } _get_complete() { # Available variables: # COMP_LINE COMP_POINT COMP_KEY COMP_TYPE COMP_WORDS COMP_CWORD # $1 : name of command whose arguments are being completed # $2 : the word being completed # $3 : the word preceding the word being completed case ${COMP_CWORD} in 1) commands="branch commit diff fetch ignore reset rmbranch review stage status unstage" COMPREPLY=( $(compgen -W "${commands}" "$2") ) ;; 2) compopt -o nospace case "$3" in # branch | rmbranch | fetch) COMPREPLY=( $(compgen -W "$(list_branches)" "$2") ) ;; # stage) COMPREPLY=( $(compgen -W "$(list_modified)" "$2") ) ;; # unstage) COMPREPLY=( $(compgen -W "$(list_staged)" "$2") ) ;; rm | diff) COMPREPLY=( $(compgen -W "$(list_tracked)" "$2") ) ;; # add) compopt -o nospace COMPREPLY=( $(compgen -W "$(list_untracked)" -W "STAGE" -W "HEAD" "$2") ) ;; esac ;; 3) case "${COMP_WORDS[COMP_CWORD-2]}" in diff) compopt -o nospace COMPREPLY=( $(compgen -W "$(list_tracked)" "$2") ) ;; esac ;; *) COMPREPLY=() ;; esac } complete -F _get_complete get