aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
authorJack Nagel2012-01-21 00:08:35 -0600
committerJack Nagel2012-01-25 23:04:08 -0600
commitba69e170734cf561b63fc309fd7ca15c0a221d53 (patch)
treefc60fda10c1283dd450a73fa2917fcffbc8178fd /Library
parentab19242d0484a91ca2b9dac28c8a131be08758d6 (diff)
downloadbrew-ba69e170734cf561b63fc309fd7ca15c0a221d53.tar.bz2
Refactor the bash completion script
The script was lacking structure and had grown a number of one-off hacks that would be better as reusable functions. So, - give each subcommand that has completions it's own function - move completion of formulae, installed brews, and outdated brews into reusable functions - introduce a general __brewcomp() function that takes a string of tab, space, and/or newline separated items and converts all seperators to newlines, and then generates a reply with compgen(). These changes should allow for easier addition of new features in the future. As a bonus, completion for `brew log` will include git-log options if the git completion script is also loaded. _brew_to_completion() is kept around for compatiblity. Signed-off-by: Jack Nagel <jacknagel@gmail.com>
Diffstat (limited to 'Library')
-rw-r--r--Library/Contributions/brew_bash_completion.sh617
1 files changed, 403 insertions, 214 deletions
diff --git a/Library/Contributions/brew_bash_completion.sh b/Library/Contributions/brew_bash_completion.sh
index 52e008910..de0228bd0 100644
--- a/Library/Contributions/brew_bash_completion.sh
+++ b/Library/Contributions/brew_bash_completion.sh
@@ -1,236 +1,335 @@
# Bash completion script for brew(1)
#
-# To use, edit your .bashrc and add:
-# source `brew --prefix`/Library/Contributions/brew_bash_completion.sh
+# To use, add the following to your .bashrc:
+#
+# . $(brew --repository)/Library/Contributions/brew_bash_completion.sh
+#
+# Alternatively, if you have installed the bash-completion package,
+# you can create a symlink to this file in one of the following directories:
+#
+# $(brew --prefix)/etc/bash_completion.d
+# $(brew --prefix)/share/bash-completion/completions
+#
+# and bash-completion will source it automatically.
#
# The __brew_ps1() function can be used to annotate your PS1 with
# Homebrew debugging information; it behaves similarly to the __git_ps1()
# function provided by the git's bash completion script.
#
# For example, the prompt string
+#
# PS1='\u@\h \W $(__brew_ps1 "(%s)") $'
#
# would result in a prompt like
+#
# user@hostname cwd $
#
# but if you are currently engaged in an interactive or debug install,
# (i.e., you invoked `brew install` with either '-i' or '-d'), then the
# prompt would look like
-# user@hostname cwd (formula_name|DEBUG) $
+#
+# user@hostname cwd (<formula_name>|DEBUG) $
#
# You can customize the output string, e.g. $(__brew_ps1 "[%s]") would
-# output "[formula_name|DEBUG]". The default (if you do not provide a
-# format argument) is to print "(formula_name|DEBUG)" prefixed with a
+# output "[<formula_name>|DEBUG]". The default (if you do not provide a
+# format argument) is to print "(<formula_name>|DEBUG)" prefixed with a
# single space.
-_brew_to_completion()
-{
- local cur="${COMP_WORDS[COMP_CWORD]}"
-
- # Subcommand list
- [[ ${COMP_CWORD} -eq 1 ]] && {
- local actions="--cache --cellar --config --env --prefix --repository audit cat cleanup
- configure create deps diy doctor edit fetch help home info install link list log options
- outdated prune remove search test uninstall unlink update upgrade uses versions"
- local ext=$(\ls $(brew --repository)/Library/Contributions/examples 2> /dev/null |
- sed -e "s/\.rb//g" -e "s/brew-//g")
- COMPREPLY=( $(compgen -W "${actions} ${ext}" -- ${cur}) )
- return
- }
-
- # some flags take arguments
- # kind of pointless to use a case statement here, but it's cleaner
- # than a bunch of string comparisons and leaves room for future
- # expansion
- case "${COMP_WORDS[1]}" in
- # flags that take a formula
- --cache|--cellar|--prefix)
- local ff=$(\ls $(brew --repository)/Library/Formula 2> /dev/null | sed "s/\.rb//g")
- local af=$(\ls $(brew --repository)/Library/Aliases 2> /dev/null | sed "s/\.rb//g")
- COMPREPLY=( $(compgen -W "${ff} ${af}" -- ${cur}) )
- return
- ;;
- esac
-
- # Find the previous non-switch word
- local prev_index=$((COMP_CWORD - 1))
- local prev="${COMP_WORDS[prev_index]}"
- while [[ $prev == -* ]]; do
- prev_index=$((--prev_index))
- prev="${COMP_WORDS[prev_index]}"
- done
-
- # handle subcommand options
- if [[ "$cur" == --* ]]; then
- case "${COMP_WORDS[1]}" in
- cleanup)
- local opts=$([[ "${COMP_WORDS[*]}" =~ "--force" ]] || echo "--force")
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- create)
- local opts=$(
- local opts=(--autotools --cmake --no-fetch)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- deps)
- local opts=$(
- local opts=(--1 --all --tree)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- diy|configure)
- local opts=$(
- local opts=(--set-version --set-name)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- fetch)
- local opts=$(
- local opts=(--deps --force --HEAD)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- info|abv)
- local opts=$(
- local opts=(--all --github)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- install)
- local opts=$(
- local opts=(--force --verbose --debug --use-clang --use-gcc
- --use-llvm --ignore-dependencies --build-from-source --HEAD
- --interactive --fresh --devel $(brew options --compact "$prev"))
-
- # options that make sense with '--interactive'
- if [[ "${COMP_WORDS[*]}" =~ "--interactive" ]]; then
- opts=(--force --git --use-clang --use-gcc --use-llvm --HEAD --devel)
- fi
-
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- list|ls)
- local opts=$(
- local opts=(--unbrewed --verbose --versions)
-
- # the three options for list are mutually exclusive
- for o in ${opts[*]}; do
- if [[ "${COMP_WORDS[*]}" =~ "$o" ]]; then
- opts=()
- else
- echo "$o"
- fi
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- options)
- local opts=$(
- local opts=(--all --compact --installed)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- outdated)
- local opts=$([[ "${COMP_WORDS[*]}" =~ "--quiet" ]] || echo "--quiet")
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- search|-S)
- local opts=$(
- local opts=(--fink --macports)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- uninstall|remove|rm)
- local opts=$([[ "${COMP_WORDS[*]}" =~ "--force" ]] || echo "--force")
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- update)
- local opts=$(
- local opts=(--rebase --verbose)
- for o in ${opts[*]}; do
- [[ "${COMP_WORDS[*]}" =~ "$o" ]] || echo "$o"
- done
- )
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- uses)
- local opts=$([[ "${COMP_WORDS[*]}" =~ "--installed" ]] || echo "--installed")
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- versions)
- local opts=$([[ "${COMP_WORDS[*]}" =~ "--compact" ]] || echo "--compact")
- COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
- return
- ;;
- esac
- fi
-
- # find the index of the *first* non-switch word
- # we can use this to allow completion for multiple formula arguments
- local cmd_index=1
- while [[ ${COMP_WORDS[cmd_index]} == -* ]]; do
- cmd_index=$((++cmd_index))
- done
-
- case "${COMP_WORDS[cmd_index]}" in
- # Commands that take a formula
- audit|cat|deps|edit|fetch|home|homepage|info|install|log|missing|options|uses|versions)
- local ff=$(\ls $(brew --repository)/Library/Formula 2> /dev/null | sed "s/\.rb//g")
- local af=$(\ls $(brew --repository)/Library/Aliases 2> /dev/null | sed "s/\.rb//g")
- COMPREPLY=( $(compgen -W "${ff} ${af}" -- ${cur}) )
- return
- ;;
- # Commands that take an existing brew
- abv|cleanup|link|list|ln|ls|remove|rm|test|uninstall|unlink)
- COMPREPLY=( $(compgen -W "$(\ls $(brew --cellar))" -- ${cur}) )
- return
- ;;
- # Commands that take an outdated brew
- upgrade)
- COMPREPLY=( $(compgen -W "$(brew outdated --quiet)" -- ${cur}) )
- return
- ;;
- esac
+__brewcomp_words_include ()
+{
+ local i=1
+ while [[ $i -lt $COMP_CWORD ]]; do
+ if [[ "${COMP_WORDS[i]}" = "$1" ]]; then
+ return 0
+ fi
+ i=$((++i))
+ done
+ return 1
+}
+
+# Find the previous non-switch word
+__brewcomp_prev ()
+{
+ local idx=$((COMP_CWORD - 1))
+ local prv="${COMP_WORDS[idx]}"
+ while [[ $prv == -* ]]; do
+ idx=$((--idx))
+ prv="${COMP_WORDS[idx]}"
+ done
+ echo "$prv"
+}
+
+__brewcomp ()
+{
+ # break $1 on space, tab, and newline characters,
+ # and turn it into a newline separated list of words
+ local list s sep=$'\n' IFS=$' '$'\t'$'\n'
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+
+ for s in $1; do
+ __brewcomp_words_include "$s" && continue
+ list="$list$s$sep"
+ done
+
+ IFS=$sep
+ COMPREPLY=($(compgen -W "$list" -- "$cur"))
+}
+
+# Don't use __brewcomp() in any of the __brew_complete_foo functions, as
+# it is too slow and is not worth it just for duplicate elimination.
+__brew_complete_formulae ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ local ff=$(\ls $(brew --repository)/Library/Formula 2>/dev/null | sed 's/\.rb//g')
+ local af=$(\ls $(brew --repository)/Library/Aliases 2>/dev/null | sed 's/\.rb//g')
+ COMPREPLY=($(compgen -W "$ff $af" -- "$cur"))
+}
+
+__brew_complete_installed ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ local inst=$(\ls $(brew --cellar))
+ COMPREPLY=($(compgen -W "$inst" -- "$cur"))
+}
+
+__brew_complete_outdated ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ local od=$(brew outdated --quiet)
+ COMPREPLY=($(compgen -W "$od" -- "$cur"))
+}
+
+_brew_cleanup ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--force"
+ return
+ ;;
+ esac
+ __brew_complete_installed
+}
+
+_brew_create ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--autotools --cmake --no-fetch"
+ return
+ ;;
+ esac
+}
+
+_brew_deps ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--1 --all --tree"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_diy ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--set-name --set-version"
+ return
+ ;;
+ esac
+}
+
+_brew_fetch ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--deps --force --HEAD"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_info ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--all --github"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_install ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ local prv=$(__brewcomp_prev)
+
+ case "$cur" in
+ --*)
+ if __brewcomp_words_include "--interactive"; then
+ __brewcomp "
+ --devel
+ --force
+ --git
+ --HEAD
+ --use-clang
+ --use-gcc
+ --use-llvm
+ "
+ else
+ __brewcomp "
+ --build-from-source
+ --debug
+ --devel
+ --force
+ --fresh
+ --HEAD
+ --ignore-dependencies
+ --interactive
+ --use-clang
+ --use-gcc
+ --use-llvm
+ --verbose
+ $(brew options --compact "$prv")
+ "
+ fi
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_list ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ # options to brew-list are mutually exclusive
+ if __brewcomp_words_include "--unbrewed"; then
+ return
+ elif __brewcomp_words_include "--verbose"; then
+ return
+ elif __brewcomp_words_include "--versions"; then
+ return
+ else
+ __brewcomp "--unbrewed --verbose --versions"
+ return
+ fi
+ ;;
+ esac
+ __brew_complete_installed
+}
+
+_brew_log ()
+{
+ # if git-completion is loaded, then we complete git-log options
+ declare -F _git_log >/dev/null || return
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "
+ $__git_log_common_options
+ $__git_log_shortlog_options
+ $__git_log_gitk_options
+ $__git_diff_common_options
+ --walk-reflogs --graph --decorate
+ --abbrev-commit --oneline --reverse
+ "
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_options ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--all --compact --installed"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_outdated ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--quiet"
+ return
+ ;;
+ esac
+}
+
+_brew_search ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--fink --macports"
+ return
+ ;;
+ esac
+}
+
+_brew_uninstall ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--force"
+ return
+ ;;
+ esac
+ __brew_complete_installed
+}
+
+_brew_update ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--rebase --verbose"
+ return
+ ;;
+ esac
+}
+
+_brew_uses ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--installed"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
+}
+
+_brew_versions ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __brewcomp "--compact"
+ return
+ ;;
+ esac
+ __brew_complete_formulae
}
__brew_ps1 ()
@@ -239,4 +338,94 @@ __brew_ps1 ()
printf "${1:- (%s)}" "$HOMEBREW_DEBUG_INSTALL|DEBUG"
}
-complete -o bashdefault -o default -F _brew_to_completion brew
+_brew ()
+{
+ local i=1 cmd
+
+ # find the subcommand
+ while [[ $i -lt $COMP_CWORD ]]; do
+ local s="${COMP_WORDS[i]}"
+ case "$s" in
+ --*) cmd="$s"
+ break
+ ;;
+ -*) ;;
+ *) cmd="$s"
+ break
+ ;;
+ esac
+ i=$((++i))
+ done
+
+ if [[ $i -eq $COMP_CWORD ]]; then
+ local ext=$(\ls $(brew --repository)/Library/Contributions/examples \
+ 2>/dev/null | sed -e "s/\.rb//g" -e "s/brew-//g")
+ __brewcomp "
+ --cache --cellar --config
+ --env --prefix --repository
+ audit
+ cat
+ cleanup
+ create
+ deps
+ diy configure
+ doctor
+ edit
+ fetch
+ help
+ home
+ info abv
+ install
+ link ln
+ list ls
+ log
+ options
+ outdated
+ prune
+ search
+ test
+ uninstall remove rm
+ unlink
+ update
+ upgrade
+ uses
+ versions
+ $ext
+ "
+ return
+ fi
+
+ # subcommands have their own completion functions
+ case "$cmd" in
+ --cache|--cellar|--prefix)
+ __brew_complete_formulae ;;
+ audit|cat|edit|home) __brew_complete_formulae ;;
+ link|ln|test|unlink) __brew_complete_installed ;;
+ upgrade) __brew_complete_outdated ;;
+ cleanup) _brew_cleanup ;;
+ create) _brew_create ;;
+ deps) _brew_deps ;;
+ diy|configure) _brew_diy ;;
+ fetch) _brew_fetch ;;
+ info|abv) _brew_info ;;
+ install) _brew_install ;;
+ list|ls) _brew_list ;;
+ log) _brew_log ;;
+ options) _brew_options ;;
+ outdated) _brew_outdated ;;
+ search|-S) _brew_search ;;
+ uninstall|remove|rm) _brew_uninstall ;;
+ update) _brew_update ;;
+ uses) _brew_uses ;;
+ versions) _brew_versions ;;
+ *) ;;
+ esac
+}
+
+# keep around for compatibility
+_brew_to_completion ()
+{
+ _brew
+}
+
+complete -o bashdefault -o default -F _brew brew