From e65c390bfa35b20653aa470fdf6eeda082e0c0e1 Mon Sep 17 00:00:00 2001 From: Toan Nguyen Date: Tue, 10 Oct 2017 18:07:01 +0700 Subject: [PATCH] Improve oh-my-bash functionality * Implement aliases, completion in oh-my-bash * Added default themes from Bash-it * Fixed few issues --- .gitignore | 5 +- aliases/general.aliases.sh | 155 + completion/apm.completion.sh | 56 + completion/awscli.completion.sh | 1 + completion/brew.completion.sh | 9 + completion/bundler.completion.sh | 55 + completion/capistrano.completion.sh | 24 + completion/composer.completion.sh | 133 + completion/conda.completion.sh | 4 + completion/defaults.completion.sh | 175 + completion/dirs.completion.sh | 15 + completion/django.completion.sh | 72 + completion/docker-compose.completion.sh | 561 ++++ completion/docker-machine.completion.sh | 252 ++ completion/docker.completion.sh | 2965 +++++++++++++++++ completion/drush.completion.sh | 37 + completion/fabric-completion.sh | 133 + completion/gem.completion.sh | 41 + completion/gh.completion.sh | 366 ++ completion/git.completion.sh | 2776 +++++++++++++++ completion/git_flow.completion.sh | 177 + completion/git_flow_avh.completion.sh | 510 +++ completion/go.completion.sh | 281 ++ completion/gradle.completion.sh | 50 + completion/grunt.completion.sh | 49 + completion/gulp.completion.sh | 23 + completion/homesick.completion.sh | 60 + completion/hub.completion.sh | 367 ++ completion/jboss7.completion.sh | 141 + completion/jungle.completion.sh | 1 + completion/kontena.completion.sh | 1 + completion/kubectl.completion.sh | 8 + completion/makefile.completion.sh | 3 + completion/maven.completion.sh | 36 + completion/npm.completion.sh | 9 + completion/nvm.completion.sh | 8 + completion/packer.completion.sh | 164 + completion/pip.completion.sh | 11 + completion/pip3.completion.sh | 11 + completion/projects.completion.sh | 39 + completion/rake.completion.sh | 17 + completion/salt.completion.sh | 329 ++ completion/sdkman.completion.sh | 61 + completion/ssh.completion.sh | 35 + completion/svn.completion.sh | 1514 +++++++++ completion/system.completion.sh | 27 + completion/terraform.completion.sh | 26 + completion/test_kitchen.completion.sh | 31 + completion/tmux.completion.sh | 188 ++ completion/todo.completion.sh | 70 + completion/vagrant.completion.sh | 147 + completion/vault.completion.sh | 51 + completion/virtualbox.completion.sh | 222 ++ custom/aliases/example.aliases.sh | 2 + custom/completion/example.completion.sh | 2 + custom/themes/example/example.theme.sh | 2 + lib/history.sh | 12 +- lib/theme-and-appearance.sh | 37 + lib/utils.sh | 16 +- oh-my-bash.sh | 59 +- plugins/battery/battery.plugin.sh | 189 ++ plugins/core/core.plugin.sh | 240 +- templates/bashrc.osh-template | 2 +- themes/90210/90210.theme.sh | 17 + themes/axin/axin.theme.sh | 42 + themes/bakke/bakke.theme.sh | 22 + themes/base.theme.sh | 521 +++ themes/binaryanomaly/binaryanomaly.theme.sh | 101 + themes/bobby-python/bobby-python.theme.sh | 19 + themes/bobby/bobby.theme.sh | 34 + themes/brainy/README.md | 123 + themes/brainy/brainy.theme.sh | 295 ++ themes/brunton/brunton.theme.sh | 36 + themes/candy/candy.theme.sh | 10 + themes/clean/clean.theme.sh | 20 + themes/colours.theme.sh | 271 ++ themes/cooperkid/cooperkid.theme.sh | 39 + themes/cupcake/cupcake.theme.sh | 79 + themes/demula/demula.theme.sh | 129 + themes/dos/dos.theme.sh | 1 + themes/doubletime/doubletime.theme.sh | 72 + .../doubletime_multiline.theme.sh | 18 + .../doubletime_multiline_pyonly.theme.sh | 18 + themes/dulcie/dulcie.theme.sh | 98 + themes/duru/duru.theme.sh | 24 + themes/emperor/emperor.theme.sh | 42 + themes/envy/envy.theme.sh | 16 + themes/font/font.theme.sh | 60 + themes/gallifrey/gallifrey.theme.sh | 41 + themes/hawaii50/hawaii50.theme.sh | 200 ++ themes/iterate/iterate.theme.sh | 59 + themes/kitsune/kitsune.theme.sh | 38 + themes/luan/luan.theme.sh | 33 + themes/mairan/mairan.theme.sh | 130 + themes/mbriggs/mbriggs.theme.sh | 34 + themes/minimal/minimal.theme.sh | 12 + themes/modern-t/modern-t.theme.sh | 56 + themes/modern/modern.theme.sh | 56 + themes/morris/morris.theme.sh | 28 + themes/n0qorg/n0qorg.theme.sh | 26 + themes/nwinkler/nwinkler.theme.sh | 47 + themes/nwinkler_random_colors/README.md | 29 + .../nwinkler_random_colors.theme.sh | 114 + themes/nwinkler_random_colors/screenshot.png | Bin 0 -> 43510 bytes themes/pete/pete.theme.sh | 20 + themes/powerline-multiline/README.md | 59 + .../powerline-multiline.base.sh | 64 + .../powerline-multiline.theme.sh | 53 + themes/powerline-naked/README.md | 58 + .../powerline-naked/powerline-naked.base.sh | 17 + .../powerline-naked/powerline-naked.theme.sh | 52 + themes/powerline-plain/README.md | 56 + .../powerline-plain/powerline-plain.base.sh | 31 + .../powerline-plain/powerline-plain.theme.sh | 48 + themes/powerline.theme.sh | 110 - themes/powerline/README.md | 60 + themes/powerline/powerline.base.sh | 165 + themes/powerline/powerline.theme.sh | 51 + themes/primer/primer.theme.sh | 11 + themes/pro/pro.theme.sh | 22 + themes/pure/pure.theme.sh | 43 + themes/purity/purity.theme.sh | 21 + themes/rainbowbrite/rainbowbrite.theme.sh | 29 + themes/rana/rana.theme.sh | 214 ++ themes/rjorgenson/rjorgenson.theme.sh | 100 + themes/roderik/roderik.theme.sh | 17 + themes/sexy/sexy.theme.sh | 46 + themes/simple/simple.theme.sh | 25 + themes/sirup/sirup.theme.sh | 22 + themes/slick/slick.theme.sh | 86 + themes/standard/standard.theme.sh | 24 + themes/tonka/tonka.theme.sh | 61 + themes/tonotdo/tonotdo.theme.sh | 13 + themes/tylenol/tylenol.theme.sh | 20 + themes/wanelo/wanelo.theme.sh | 26 + themes/zitron/zitron.theme.sh | 24 + themes/zork/zork.theme.sh | 97 + tools/git-prompt.sh | 534 +++ 138 files changed, 18119 insertions(+), 233 deletions(-) create mode 100644 aliases/general.aliases.sh create mode 100644 completion/apm.completion.sh create mode 100644 completion/awscli.completion.sh create mode 100644 completion/brew.completion.sh create mode 100644 completion/bundler.completion.sh create mode 100755 completion/capistrano.completion.sh create mode 100644 completion/composer.completion.sh create mode 100644 completion/conda.completion.sh create mode 100644 completion/defaults.completion.sh create mode 100644 completion/dirs.completion.sh create mode 100644 completion/django.completion.sh create mode 100644 completion/docker-compose.completion.sh create mode 100644 completion/docker-machine.completion.sh create mode 100644 completion/docker.completion.sh create mode 100644 completion/drush.completion.sh create mode 100644 completion/fabric-completion.sh create mode 100644 completion/gem.completion.sh create mode 100644 completion/gh.completion.sh create mode 100644 completion/git.completion.sh create mode 100644 completion/git_flow.completion.sh create mode 100644 completion/git_flow_avh.completion.sh create mode 100644 completion/go.completion.sh create mode 100644 completion/gradle.completion.sh create mode 100644 completion/grunt.completion.sh create mode 100644 completion/gulp.completion.sh create mode 100644 completion/homesick.completion.sh create mode 100644 completion/hub.completion.sh create mode 100644 completion/jboss7.completion.sh create mode 100644 completion/jungle.completion.sh create mode 100644 completion/kontena.completion.sh create mode 100644 completion/kubectl.completion.sh create mode 100644 completion/makefile.completion.sh create mode 100644 completion/maven.completion.sh create mode 100644 completion/npm.completion.sh create mode 100644 completion/nvm.completion.sh create mode 100644 completion/packer.completion.sh create mode 100644 completion/pip.completion.sh create mode 100644 completion/pip3.completion.sh create mode 100644 completion/projects.completion.sh create mode 100644 completion/rake.completion.sh create mode 100644 completion/salt.completion.sh create mode 100644 completion/sdkman.completion.sh create mode 100644 completion/ssh.completion.sh create mode 100644 completion/svn.completion.sh create mode 100644 completion/system.completion.sh create mode 100644 completion/terraform.completion.sh create mode 100644 completion/test_kitchen.completion.sh create mode 100644 completion/tmux.completion.sh create mode 100644 completion/todo.completion.sh create mode 100644 completion/vagrant.completion.sh create mode 100644 completion/vault.completion.sh create mode 100644 completion/virtualbox.completion.sh create mode 100644 custom/aliases/example.aliases.sh create mode 100644 custom/completion/example.completion.sh create mode 100644 custom/themes/example/example.theme.sh create mode 100644 lib/theme-and-appearance.sh create mode 100644 plugins/battery/battery.plugin.sh create mode 100644 themes/90210/90210.theme.sh create mode 100644 themes/axin/axin.theme.sh create mode 100644 themes/bakke/bakke.theme.sh create mode 100644 themes/base.theme.sh create mode 100644 themes/binaryanomaly/binaryanomaly.theme.sh create mode 100644 themes/bobby-python/bobby-python.theme.sh create mode 100644 themes/bobby/bobby.theme.sh create mode 100644 themes/brainy/README.md create mode 100644 themes/brainy/brainy.theme.sh create mode 100644 themes/brunton/brunton.theme.sh create mode 100644 themes/candy/candy.theme.sh create mode 100644 themes/clean/clean.theme.sh create mode 100644 themes/colours.theme.sh create mode 100644 themes/cooperkid/cooperkid.theme.sh create mode 100644 themes/cupcake/cupcake.theme.sh create mode 100644 themes/demula/demula.theme.sh create mode 100644 themes/dos/dos.theme.sh create mode 100644 themes/doubletime/doubletime.theme.sh create mode 100644 themes/doubletime_multiline/doubletime_multiline.theme.sh create mode 100644 themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.sh create mode 100644 themes/dulcie/dulcie.theme.sh create mode 100644 themes/duru/duru.theme.sh create mode 100644 themes/emperor/emperor.theme.sh create mode 100644 themes/envy/envy.theme.sh create mode 100644 themes/font/font.theme.sh create mode 100644 themes/gallifrey/gallifrey.theme.sh create mode 100644 themes/hawaii50/hawaii50.theme.sh create mode 100644 themes/iterate/iterate.theme.sh create mode 100644 themes/kitsune/kitsune.theme.sh create mode 100644 themes/luan/luan.theme.sh create mode 100644 themes/mairan/mairan.theme.sh create mode 100644 themes/mbriggs/mbriggs.theme.sh create mode 100644 themes/minimal/minimal.theme.sh create mode 100644 themes/modern-t/modern-t.theme.sh create mode 100644 themes/modern/modern.theme.sh create mode 100644 themes/morris/morris.theme.sh create mode 100644 themes/n0qorg/n0qorg.theme.sh create mode 100644 themes/nwinkler/nwinkler.theme.sh create mode 100644 themes/nwinkler_random_colors/README.md create mode 100644 themes/nwinkler_random_colors/nwinkler_random_colors.theme.sh create mode 100644 themes/nwinkler_random_colors/screenshot.png create mode 100644 themes/pete/pete.theme.sh create mode 100644 themes/powerline-multiline/README.md create mode 100644 themes/powerline-multiline/powerline-multiline.base.sh create mode 100644 themes/powerline-multiline/powerline-multiline.theme.sh create mode 100644 themes/powerline-naked/README.md create mode 100644 themes/powerline-naked/powerline-naked.base.sh create mode 100644 themes/powerline-naked/powerline-naked.theme.sh create mode 100644 themes/powerline-plain/README.md create mode 100644 themes/powerline-plain/powerline-plain.base.sh create mode 100644 themes/powerline-plain/powerline-plain.theme.sh delete mode 100644 themes/powerline.theme.sh create mode 100644 themes/powerline/README.md create mode 100644 themes/powerline/powerline.base.sh create mode 100644 themes/powerline/powerline.theme.sh create mode 100644 themes/primer/primer.theme.sh create mode 100644 themes/pro/pro.theme.sh create mode 100644 themes/pure/pure.theme.sh create mode 100644 themes/purity/purity.theme.sh create mode 100644 themes/rainbowbrite/rainbowbrite.theme.sh create mode 100644 themes/rana/rana.theme.sh create mode 100644 themes/rjorgenson/rjorgenson.theme.sh create mode 100644 themes/roderik/roderik.theme.sh create mode 100644 themes/sexy/sexy.theme.sh create mode 100644 themes/simple/simple.theme.sh create mode 100644 themes/sirup/sirup.theme.sh create mode 100644 themes/slick/slick.theme.sh create mode 100644 themes/standard/standard.theme.sh create mode 100644 themes/tonka/tonka.theme.sh create mode 100644 themes/tonotdo/tonotdo.theme.sh create mode 100644 themes/tylenol/tylenol.theme.sh create mode 100644 themes/wanelo/wanelo.theme.sh create mode 100644 themes/zitron/zitron.theme.sh create mode 100644 themes/zork/zork.theme.sh create mode 100644 tools/git-prompt.sh diff --git a/.gitignore b/.gitignore index 3d92762..79285e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ # custom files -/custom/ +!/custom/aliases/example.aliases.sh +!/custom/completion/example.completion.sh !/custom/plugins/example/ +!/custom/themes/example/ !/custom/example.sh +/custom/ # temp files directories /cache/ diff --git a/aliases/general.aliases.sh b/aliases/general.aliases.sh new file mode 100644 index 0000000..f17cfb7 --- /dev/null +++ b/aliases/general.aliases.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +# --------------------------------------------------------------------------- +# +# Description: This file holds all general BASH aliases +# +# Sections: +# 1. Make Terminal Better (remapping defaults and adding functionality) +# 2. File and Folder Management +# 3. Searching +# 4. Process Management +# 5. Networking +# 6. System Operations & Information +# 7. Date & Time Management +# 8. Web Development +# 9. +# +# X. Reminders & Notes +# +# --------------------------------------------------------------------------- + +# ----------------------------- +# 1. MAKE TERMINAL BETTER +# ----------------------------- + +alias cp='cp -iv' # Preferred 'cp' implementation +alias mv='mv -iv' # Preferred 'mv' implementation +alias mkdir='mkdir -pv' # Preferred 'mkdir' implementation +alias ll='ls -lAFh' # Preferred 'ls' implementation +alias less='less -FSRXc' # Preferred 'less' implementation +alias nano='nano -W -$' # Preferred 'nano' implementation +alias wget='wget -c' # Preferred 'wget' implementation (resume download) +alias cd..='cd ../' # Go back 1 directory level (for fast typers) +alias ..='cd ../' # Go back 1 directory level +alias ...='cd ../../' # Go back 2 directory levels +alias .3='cd ../../../' # Go back 3 directory levels +alias .4='cd ../../../../' # Go back 4 directory levels +alias .5='cd ../../../../../' # Go back 5 directory levels +alias .6='cd ../../../../../../' # Go back 6 directory levels +alias dud='du -d 1 -h' # Short and human-readable file listing +alias duf='du -sh *' # Short and human-readable directory listing +alias ~="cd ~" # ~: Go Home +alias c='clear' # c: Clear terminal display +alias path='echo -e ${PATH//:/\\n}' # path: Echo all executable Paths +alias show_options='shopt' # Show_options: display bash options settings +alias fix_stty='stty sane' # fix_stty: Restore terminal settings when screwed up +alias cic='set completion-ignore-case On' # cic: Make tab-completion case-insensitive +alias h='fc -l 1 | grep $1' # h: Find an executed command in .bash_history +alias src='source ~/.bashrc' # src: Reload .bashrc file + +# lr: Full Recursive Directory Listing +# ------------------------------------------ + alias lr='ls -R | grep ":$" | sed -e '\''s/:$//'\'' -e '\''s/[^-][^\/]*\//--/g'\'' -e '\''s/^/ /'\'' -e '\''s/-/|/'\'' | less' + + +# ------------------------------- +# 2. FILE AND FOLDER MANAGEMENT +# ------------------------------- + +alias numFiles='echo $(ls -1 | wc -l)' # numFiles: Count of non-hidden files in current dir +alias make1mb='truncate -s 1m ./1MB.dat' # make1mb: Creates a file of 1mb size (all zeros) +alias make5mb='truncate -s 5m ./5MB.dat' # make5mb: Creates a file of 5mb size (all zeros) +alias make10mb='truncate -s 10m ./10MB.dat' # make10mb: Creates a file of 10mb size (all zeros) + + +# --------------------------- +# 3. SEARCHING +# --------------------------- + +alias qfind="find . -name " # qfind: Quickly search for file + + +# --------------------------- +# 4. PROCESS MANAGEMENT +# --------------------------- + +# memHogsTop, memHogsPs: Find memory hogs +# ----------------------------------------------------- + alias memHogsTop='top -l 1 -o rsize | head -20' + alias memHogsPs='ps wwaxm -o pid,stat,vsize,rss,time,command | head -10' + +# cpuHogs: Find CPU hogs +# ----------------------------------------------------- + alias cpu_hogs='ps wwaxr -o pid,stat,%cpu,time,command | head -10' + +# topForever: Continual 'top' listing (every 10 seconds) +# ----------------------------------------------------- + alias topForever='top -l 9999999 -s 10 -o cpu' + +# ttop: Recommended 'top' invocation to minimize resources +# ------------------------------------------------------------ +# Taken from this macosxhints article +# http://www.macosxhints.com/article.php?story=20060816123853639 +# ------------------------------------------------------------ + alias ttop="top -R -F -s 10 -o rsize" + + +# --------------------------- +# 5. NETWORKING +# --------------------------- + +alias netCons='lsof -i' # netCons: Show all open TCP/IP sockets +alias lsock='sudo /usr/sbin/lsof -i -P' # lsock: Display open sockets +alias lsockU='sudo /usr/sbin/lsof -nP | grep UDP' # lsockU: Display only open UDP sockets +alias lsockT='sudo /usr/sbin/lsof -nP | grep TCP' # lsockT: Display only open TCP sockets +alias ipInfo0='ifconfig getpacket en0' # ipInfo0: Get info on connections for en0 +alias ipInfo1='ifconfig getpacket en1' # ipInfo1: Get info on connections for en1 +alias openPorts='sudo lsof -i | grep LISTEN' # openPorts: All listening connections +alias showBlocked='sudo ipfw list' # showBlocked: All ipfw rules inc/ blocked IPs + + +# --------------------------------------- +# 6. SYSTEMS OPERATIONS & INFORMATION +# --------------------------------------- + +alias mountReadWrite='/sbin/mount -uw /' # mountReadWrite: For use when booted into single-user +alias perm='stat --printf "%a %n \n "' # perm: Show permission of target in number +alias 000='chmod 000' # ---------- (no fucking permissions) +alias 640='chmod 640' # -rw-r----- (user: rw, group: r, other: -) +alias 644='chmod 644' # -rw-r--r-- (user: rw, group: r, other: -) +alias 755='chmod 755' # -rwxr-xr-x (user: rwx, group: rx, other: x) +alias 775='chmod 775' # -rwxrwxr-x (user: rwx, group: rwx, other: rx) +alias mx='chmod a+x' # ---x--x--x (user: --x, group: --x, other: --x) +alias ux='chmod u+x' # ---x------ (user: --x, group: -, other: -) + + +# --------------------------------------- +# 7. DATE & TIME MANAGEMENT +# --------------------------------------- + +alias bdate="date '+%a, %b %d %Y %T %Z'" +alias cal='cal -3' +alias da='date "+%Y-%m-%d %A %T %Z"' +alias daysleft='echo "There are $(($(date +%j -d"Dec 31, $(date +%Y)")-$(date +%j))) left in year $(date +%Y)."' +alias epochtime='date +%s' +alias mytime='date +%H:%M:%S' +alias secconvert='date -d@1234567890' +alias stamp='date "+%Y%m%d%a%H%M"' +alias timestamp='date "+%Y%m%dT%H%M%S"' +alias today='date +"%A, %B %-d, %Y"' +alias weeknum='date +%V' + + +# --------------------------------------- +# 8. WEB DEVELOPMENT +# --------------------------------------- + +alias apacheEdit='sudo edit /etc/httpd/httpd.conf' # apacheEdit: Edit httpd.conf +alias apacheRestart='sudo apachectl graceful' # apacheRestart: Restart Apache +alias editHosts='sudo edit /etc/hosts' # editHosts: Edit /etc/hosts file +alias herr='tail /var/log/httpd/error_log' # herr: Tails HTTP error logs +alias apacheLogs="less +F /var/log/apache2/error_log" # Apachelogs: Shows apache error logs + +# --------------------------------------- +# 9. REMINDERS & NOTES +# --------------------------------------- diff --git a/completion/apm.completion.sh b/completion/apm.completion.sh new file mode 100644 index 0000000..a0a4e13 --- /dev/null +++ b/completion/apm.completion.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# apm-bash-completion is written by Ugur Ozyilmazel +# repo: https://github.com/vigo/apm-bash-completion + +__apm(){ + local cur prev options apm_command + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + __apm_get_command + if [[ $cur = -* ]]; then + options="--color" + if [[ -z $apm_command ]]; then + options="$options --version --help" + fi + if [[ $apm_command && $apm_command = publish ]]; then + options="--tag --rename" + fi + else + if [[ -z $apm_command || $apm_command = help ]]; then + options="help clean config dedupe deinstall delete dev develop docs erase featured home init install link linked links list ln lns login ls open outdated publish rebuild rebuild-module-cache remove rm search show star starred stars test uninstall unlink unpublish unstar update upgrade view" + fi + if [[ $apm_command && $apm_command = publish ]]; then + options="major minor patch build" + fi + if [[ $apm_command && $apm_command = config ]]; then + options="set get delete list edit" + fi + fi + COMPREPLY=($(compgen -W "$options" -- "$cur")) +} +__apm_get_command() { + local i + for ((i=1; i < $COMP_CWORD; ++i)); do + local arg=${COMP_WORDS[$i]} + case $arg in + [^-]*) + apm_command=$arg + return;; + --version) + apm_command=- + return;; + --help) + apm_command=help + return;; + publish) + apm_command=publish + return;; + config) + apm_command=config + return;; + esac + done +} +complete -F __apm -o bashdefault -o default apm diff --git a/completion/awscli.completion.sh b/completion/awscli.completion.sh new file mode 100644 index 0000000..530bdd2 --- /dev/null +++ b/completion/awscli.completion.sh @@ -0,0 +1 @@ +[[ -x "$(which aws_completer)" ]] && complete -C "$(which aws_completer)" aws diff --git a/completion/brew.completion.sh b/completion/brew.completion.sh new file mode 100644 index 0000000..50f6c08 --- /dev/null +++ b/completion/brew.completion.sh @@ -0,0 +1,9 @@ +if which brew >/dev/null 2>&1; then + if [ -f `brew --prefix`/etc/bash_completion ]; then + . `brew --prefix`/etc/bash_completion + fi + + if [ -f `brew --prefix`/Library/Contributions/brew_bash_completion.sh ]; then + . `brew --prefix`/Library/Contributions/brew_bash_completion.sh + fi +fi diff --git a/completion/bundler.completion.sh b/completion/bundler.completion.sh new file mode 100644 index 0000000..274a4a3 --- /dev/null +++ b/completion/bundler.completion.sh @@ -0,0 +1,55 @@ +#! bash +# bash completion for the `bundle` command. +# +# Copyright (c) 2011-2013 Daniel Luz . +# Distributed under the MIT license. +# http://mernen.com/projects/completion-ruby +# +# To use, source this file on bash: +# . completion-bundle + +__bundle() { + local cur=$2 + local prev=$3 + local bundle_command + __bundle_get_command + COMPREPLY=() + + local options + if [[ $cur = -* ]]; then + options="--no-color --verbose" + if [[ -z $bundle_command ]]; then + options="$options --version --help" + fi + else + if [[ -z $bundle_command || $bundle_command = help ]]; then + options="help install update package exec config check list show + console open viz init gem" + fi + fi + COMPREPLY=($(compgen -W "$options" -- "$cur")) +} + +__bundle_get_command() { + local i + for ((i=1; i < $COMP_CWORD; ++i)); do + local arg=${COMP_WORDS[$i]} + + case $arg in + [^-]*) + bundle_command=$arg + return;; + --version) + # command-killer + bundle_command=- + return;; + --help) + bundle_command=help + return;; + esac + done +} + + +complete -F __bundle -o bashdefault -o default bundle +# vim: ai ft=sh sw=4 sts=2 et diff --git a/completion/capistrano.completion.sh b/completion/capistrano.completion.sh new file mode 100755 index 0000000..d5fda06 --- /dev/null +++ b/completion/capistrano.completion.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Bash completion support for Capistrano. + +export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} + +_capcomplete() { + if [ -f Capfile ]; then + recent=`ls -t .cap_tasks~ Capfile **/*.cap 2> /dev/null | head -n 1` + if [[ $recent != '.cap_tasks~' ]]; then + cap --version | grep 'Capistrano v2.' > /dev/null + if [ $? -eq 0 ]; then + # Capistrano 2.x + cap --tool --verbose --tasks | cut -d " " -f 2 > .cap_tasks~ + else + # Capistrano 3.x + cap --all --tasks | cut -d " " -f 2 > .cap_tasks~ + fi + fi + COMPREPLY=($(compgen -W "`cat .cap_tasks~`" -- ${COMP_WORDS[COMP_CWORD]})) + return 0 + fi +} + +complete -o default -o nospace -F _capcomplete cap diff --git a/completion/composer.completion.sh b/completion/composer.completion.sh new file mode 100644 index 0000000..be19fd2 --- /dev/null +++ b/completion/composer.completion.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash + +_composer() +{ + local cur script coms opts com + COMPREPLY=() + _get_comp_words_by_ref -n : cur words + + # for an alias, get the real script behind it + if [[ $(type -t ${words[0]}) == "alias" ]]; then + script=$(alias ${words[0]} | sed -E "s/alias ${words[0]}='(.*)'/\1/") + else + script=${words[0]} + fi + + # lookup for command + for word in ${words[@]:1}; do + if [[ $word != -* ]]; then + com=$word + break + fi + done + + # completing for an option + if [[ ${cur} == --* ]] ; then + opts="--help --quiet --verbose --version --ansi --no-ansi --no-interaction --profile --no-plugins --working-dir" + + case "$com" in + about) + opts="${opts} " + ;; + archive) + opts="${opts} --format --dir --file" + ;; + browse) + opts="${opts} --homepage --show" + ;; + clear-cache) + opts="${opts} " + ;; + config) + opts="${opts} --global --editor --auth --unset --list --file --absolute" + ;; + create-project) + opts="${opts} --stability --prefer-source --prefer-dist --repository --repository-url --dev --no-dev --no-custom-installers --no-scripts --no-progress --no-secure-http --keep-vcs --no-install --ignore-platform-reqs" + ;; + depends) + opts="${opts} --recursive --tree" + ;; + diagnose) + opts="${opts} " + ;; + dump-autoload) + opts="${opts} --no-scripts --optimize --classmap-authoritative --apcu --no-dev" + ;; + exec) + opts="${opts} --list" + ;; + global) + opts="${opts} " + ;; + help) + opts="${opts} --xml --format --raw" + ;; + init) + opts="${opts} --name --description --author --type --homepage --require --require-dev --stability --license --repository" + ;; + install) + opts="${opts} --prefer-source --prefer-dist --dry-run --dev --no-dev --no-custom-installers --no-autoloader --no-scripts --no-progress --no-suggest --optimize-autoloader --classmap-authoritative --apcu-autoloader --ignore-platform-reqs" + ;; + licenses) + opts="${opts} --format --no-dev" + ;; + list) + opts="${opts} --xml --raw --format" + ;; + outdated) + opts="${opts} --outdated --all --direct --strict" + ;; + prohibits) + opts="${opts} --recursive --tree" + ;; + remove) + opts="${opts} --dev --no-progress --no-update --no-scripts --update-no-dev --update-with-dependencies --no-update-with-dependencies --ignore-platform-reqs --optimize-autoloader --classmap-authoritative --apcu-autoloader" + ;; + require) + opts="${opts} --dev --prefer-source --prefer-dist --no-progress --no-suggest --no-update --no-scripts --update-no-dev --update-with-dependencies --ignore-platform-reqs --prefer-stable --prefer-lowest --sort-packages --optimize-autoloader --classmap-authoritative --apcu-autoloader" + ;; + run-script) + opts="${opts} --timeout --dev --no-dev --list" + ;; + search) + opts="${opts} --only-name --type" + ;; + self-update) + opts="${opts} --rollback --clean-backups --no-progress --update-keys --stable --preview --snapshot" + ;; + show) + opts="${opts} --all --installed --platform --available --self --name-only --path --tree --latest --outdated --minor-only --direct --strict" + ;; + status) + opts="${opts} " + ;; + suggests) + opts="${opts} --by-package --by-suggestion --no-dev" + ;; + update) + opts="${opts} --prefer-source --prefer-dist --dry-run --dev --no-dev --lock --no-custom-installers --no-autoloader --no-scripts --no-progress --no-suggest --with-dependencies --optimize-autoloader --classmap-authoritative --apcu-autoloader --ignore-platform-reqs --prefer-stable --prefer-lowest --interactive --root-reqs" + ;; + validate) + opts="${opts} --no-check-all --no-check-lock --no-check-publish --with-dependencies --strict" + ;; + + esac + + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + __ltrim_colon_completions "$cur" + + return 0; + fi + + # completing for a command + if [[ $cur == $com ]]; then + coms="about archive browse clear-cache config create-project depends diagnose dump-autoload exec global help init install licenses list outdated prohibits remove require run-script search self-update show status suggests update validate" + + COMPREPLY=($(compgen -W "${coms}" -- ${cur})) + __ltrim_colon_completions "$cur" + + return 0 + fi +} + +complete -o default -F _composer composer diff --git a/completion/conda.completion.sh b/completion/conda.completion.sh new file mode 100644 index 0000000..f43889f --- /dev/null +++ b/completion/conda.completion.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +which register-python-argcomplete > /dev/null \ + && eval "$(register-python-argcomplete conda)" \ + || echo "Please install argcomplete to use conda completion" > /dev/null diff --git a/completion/defaults.completion.sh b/completion/defaults.completion.sh new file mode 100644 index 0000000..5a8d034 --- /dev/null +++ b/completion/defaults.completion.sh @@ -0,0 +1,175 @@ +# defaults +# Bash command line completion for defaults +# +# Created by Jonathon Mah on 2006-11-08. +# Copyright 2006 Playhaus. All rights reserved. +# +# Version 1.0 (2006-11-08) + + +_defaults_domains() +{ + local cur + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + local domains=$( defaults domains | sed -e 's/, /:/g' | tr : '\n' | sed -e 's/ /\\ /g' | grep -i "^$cur" ) + local IFS=$'\n' + COMPREPLY=( $domains ) + if [[ $( echo '-app' | grep "^$cur" ) ]]; then + COMPREPLY[${#COMPREPLY[@]}]="-app" + fi + + return 0 +} + + +_defaults() +{ + local cur prev host_opts cmds cmd domain keys key_index + cur=${COMP_WORDS[COMP_CWORD]} + prev=${COMP_WORDS[COMP_CWORD-1]} + + host_opts='-currentHost -host' + cmds='read read-type write rename delete domains find help' + + if [[ $COMP_CWORD -eq 1 ]]; then + COMPREPLY=( $( compgen -W "$host_opts $cmds" -- $cur ) ) + return 0 + elif [[ $COMP_CWORD -eq 2 ]]; then + if [[ "$prev" == "-currentHost" ]]; then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + elif [[ "$prev" == "-host" ]]; then + return 0 + _known_hosts -a + else + _defaults_domains + return 0 + fi + elif [[ $COMP_CWORD -eq 3 ]]; then + if [[ ${COMP_WORDS[1]} == "-host" ]]; then + _defaults_domains + return 0 + fi + fi + + # Both a domain and command have been specified + + if [[ ${COMP_WORDS[1]} == [${cmds// /|}] ]]; then + cmd=${COMP_WORDS[1]} + domain=${COMP_WORDS[2]} + key_index=3 + if [[ "$domain" == "-app" ]]; then + if [[ $COMP_CWORD -eq 3 ]]; then + # Completing application name. Can't help here, sorry + return 0 + fi + domain="-app ${COMP_WORDS[3]}" + key_index=4 + fi + elif [[ ${COMP_WORDS[2]} == "-currentHost" ]] && [[ ${COMP_WORDS[2]} == [${cmds// /|}] ]]; then + cmd=${COMP_WORDS[2]} + domain=${COMP_WORDS[3]} + key_index=4 + if [[ "$domain" == "-app" ]]; then + if [[ $COMP_CWORD -eq 4 ]]; then + # Completing application name. Can't help here, sorry + return 0 + fi + domain="-app ${COMP_WORDS[4]}" + key_index=5 + fi + elif [[ ${COMP_WORDS[3]} == "-host" ]] && [[ ${COMP_WORDS[3]} == [${cmds// /|}] ]]; then + cmd=${COMP_WORDS[3]} + domain=${COMP_WORDS[4]} + key_index=5 + if [[ "$domain" == "-app" ]]; then + if [[ $COMP_CWORD -eq 5 ]]; then + # Completing application name. Can't help here, sorry + return 0 + fi + domain="-app ${COMP_WORDS[5]}" + key_index=6 + fi + fi + + keys=$( defaults read $domain 2>/dev/null | sed -n -e '/^ [^}) ]/p' | sed -e 's/^ \([^" ]\{1,\}\) = .*$/\1/g' -e 's/^ "\([^"]\{1,\}\)" = .*$/\1/g' | sed -e 's/ /\\ /g' ) + + case $cmd in + read|read-type) + # Complete key + local IFS=$'\n' + COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) ) + ;; + write) + if [[ $key_index -eq $COMP_CWORD ]]; then + # Complete key + local IFS=$'\n' + COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) ) + elif [[ $((key_index+1)) -eq $COMP_CWORD ]]; then + # Complete value type + # Unfortunately ${COMP_WORDS[key_index]} fails on keys with spaces + local value_types='-string -data -integer -float -boolean -date -array -array-add -dict -dict-add' + local cur_type=$( defaults read-type $domain ${COMP_WORDS[key_index]} 2>/dev/null | sed -e 's/^Type is \(.*\)/-\1/' -e's/dictionary/dict/' | grep "^$cur" ) + if [[ $cur_type ]]; then + COMPREPLY=( $cur_type ) + else + COMPREPLY=( $( compgen -W "$value_types" -- $cur ) ) + fi + elif [[ $((key_index+2)) -eq $COMP_CWORD ]]; then + # Complete value + # Unfortunately ${COMP_WORDS[key_index]} fails on keys with spaces + COMPREPLY=( $( defaults read $domain ${COMP_WORDS[key_index]} 2>/dev/null | grep -i "^${cur//\\/\\\\}" ) ) + fi + ;; + rename) + if [[ $key_index -eq $COMP_CWORD ]] || + [[ $((key_index+1)) -eq $COMP_CWORD ]]; then + # Complete source and destination keys + local IFS=$'\n' + COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) ) + fi + ;; + delete) + if [[ $key_index -eq $COMP_CWORD ]]; then + # Complete key + local IFS=$'\n' + COMPREPLY=( $( echo "$keys" | grep -i "^${cur//\\/\\\\}" ) ) + fi + ;; + esac + + return 0 +} + +complete -F _defaults -o default defaults + + +# This file is licensed under the BSD license, as follows: +# +# Copyright (c) 2006, Playhaus +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the Playhaus nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# This software is provided by the copyright holders and contributors "as is" +# and any express or implied warranties, including, but not limited to, the +# implied warranties of merchantability and fitness for a particular purpose are +# disclaimed. In no event shall the copyright owner or contributors be liable +# for any direct, indirect, incidental, special, exemplary, or consequential +# damages (including, but not limited to, procurement of substitute goods or +# services; loss of use, data, or profits; or business interruption) however +# caused and on any theory of liability, whether in contract, strict liability, +# or tort (including negligence or otherwise) arising in any way out of the use +# of this software, even if advised of the possibility of such damage. diff --git a/completion/dirs.completion.sh b/completion/dirs.completion.sh new file mode 100644 index 0000000..ba18db3 --- /dev/null +++ b/completion/dirs.completion.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Bash completion support for the 'dirs' plugin (commands G, R). + +_dirs-complete() { + local CURRENT_PROMPT="${COMP_WORDS[COMP_CWORD]}" + + # parse all defined shortcuts from ~/.dirs + if [ -r "$HOME/.dirs" ]; then + COMPREPLY=($(compgen -W "$(grep -v '^#' ~/.dirs | sed -e 's/\(.*\)=.*/\1/')" -- ${CURRENT_PROMPT}) ) + fi + + return 0 +} + +complete -o default -o nospace -F _dirs-complete G R diff --git a/completion/django.completion.sh b/completion/django.completion.sh new file mode 100644 index 0000000..1c3887e --- /dev/null +++ b/completion/django.completion.sh @@ -0,0 +1,72 @@ +# ######################################################################### +# This bash script adds tab-completion feature to django-admin.py and +# manage.py. +# +# Testing it out without installing +# ================================= +# +# To test out the completion without "installing" this, just run this file +# directly, like so: +# +# . ~/path/to/django_bash_completion +# +# Note: There's a dot ('.') at the beginning of that command. +# +# After you do that, tab completion will immediately be made available in your +# current Bash shell. But it won't be available next time you log in. +# +# Installing +# ========== +# +# To install this, point to this file from your .bash_profile, like so: +# +# . ~/path/to/django_bash_completion +# +# Do the same in your .bashrc if .bashrc doesn't invoke .bash_profile. +# +# Settings will take effect the next time you log in. +# +# Uninstalling +# ============ +# +# To uninstall, just remove the line from your .bash_profile and .bashrc. + +_django_completion() +{ + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + DJANGO_AUTO_COMPLETE=1 $1 ) ) +} +complete -F _django_completion -o default django-admin.py manage.py django-admin + +_python_django_completion() +{ + if [[ ${COMP_CWORD} -ge 2 ]]; then + PYTHON_EXE=$( basename -- ${COMP_WORDS[0]} ) + echo $PYTHON_EXE | egrep "python([2-9]\.[0-9])?" >/dev/null 2>&1 + if [[ $? == 0 ]]; then + PYTHON_SCRIPT=$( basename -- ${COMP_WORDS[1]} ) + echo $PYTHON_SCRIPT | egrep "manage\.py|django-admin(\.py)?" >/dev/null 2>&1 + if [[ $? == 0 ]]; then + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]:1}" \ + COMP_CWORD=$(( COMP_CWORD-1 )) \ + DJANGO_AUTO_COMPLETE=1 ${COMP_WORDS[*]} ) ) + fi + fi + fi +} + +# Support for multiple interpreters. +unset pythons +if command -v whereis &>/dev/null; then + python_interpreters=$(whereis python | cut -d " " -f 2-) + for python in $python_interpreters; do + pythons="${pythons} $(basename -- $python)" + done + pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ") +else + pythons=python +fi + +complete -F _python_django_completion -o default $pythons + diff --git a/completion/docker-compose.completion.sh b/completion/docker-compose.completion.sh new file mode 100644 index 0000000..0201bcb --- /dev/null +++ b/completion/docker-compose.completion.sh @@ -0,0 +1,561 @@ +#!bash +# +# bash completion for docker-compose +# +# This work is based on the completion for the docker command. +# +# This script provides completion of: +# - commands and their options +# - service names +# - filepaths +# +# To enable the completions either: +# - place this file in /etc/bash_completion.d +# or +# - copy this file to e.g. ~/.docker-compose-completion.sh and add the line +# below to your .bashrc after bash completion features are loaded +# . ~/.docker-compose-completion.sh + + +__docker_compose_q() { + docker-compose 2>/dev/null $daemon_options "$@" +} + +# Transforms a multiline list of strings into a single line string +# with the words separated by "|". +__docker_compose_to_alternatives() { + local parts=( $1 ) + local IFS='|' + echo "${parts[*]}" +} + +# Transforms a multiline list of options into an extglob pattern +# suitable for use in case statements. +__docker_compose_to_extglob() { + local extglob=$( __docker_compose_to_alternatives "$1" ) + echo "@($extglob)" +} + +# suppress trailing whitespace +__docker_compose_nospace() { + # compopt is not available in ancient bash versions + type compopt &>/dev/null && compopt -o nospace +} + +# Extracts all service names from the compose file. +___docker_compose_all_services_in_compose_file() { + __docker_compose_q config --services +} + +# All services, even those without an existing container +__docker_compose_services_all() { + COMPREPLY=( $(compgen -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) +} + +# All services that have an entry with the given key in their compose_file section +___docker_compose_services_with_key() { + # flatten sections under "services" to one line, then filter lines containing the key and return section name + __docker_compose_q config \ + | sed -n -e '/^services:/,/^[^ ]/p' \ + | sed -n 's/^ //p' \ + | awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' \ + | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' +} + +# All services that are defined by a Dockerfile reference +__docker_compose_services_from_build() { + COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key build)" -- "$cur") ) +} + +# All services that are defined by an image +__docker_compose_services_from_image() { + COMPREPLY=( $(compgen -W "$(___docker_compose_services_with_key image)" -- "$cur") ) +} + +# The services for which containers have been created, optionally filtered +# by a boolean expression passed in as argument. +__docker_compose_services_with() { + local containers names + containers="$(__docker_compose_q ps -q)" + names=$(docker 2>/dev/null inspect -f "{{if ${1:-true}}}{{range \$k, \$v := .Config.Labels}}{{if eq \$k \"com.docker.compose.service\"}}{{\$v}}{{end}}{{end}}{{end}}" $containers) + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) +} + +# The services for which at least one paused container exists +__docker_compose_services_paused() { + __docker_compose_services_with '.State.Paused' +} + +# The services for which at least one running container exists +__docker_compose_services_running() { + __docker_compose_services_with '.State.Running' +} + +# The services for which at least one stopped container exists +__docker_compose_services_stopped() { + __docker_compose_services_with 'not .State.Running' +} + + +_docker_compose_build() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force-rm --help --no-cache --pull" -- "$cur" ) ) + ;; + *) + __docker_compose_services_from_build + ;; + esac +} + + +_docker_compose_bundle() { + case "$prev" in + --output|-o) + _filedir + return + ;; + esac + + COMPREPLY=( $( compgen -W "--fetch-digests --help --output -o" -- "$cur" ) ) +} + + +_docker_compose_config() { + COMPREPLY=( $( compgen -W "--help --quiet -q --services" -- "$cur" ) ) +} + + +_docker_compose_create() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force-recreate --help --no-build --no-recreate" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_docker_compose() { + case "$prev" in + --tlscacert|--tlscert|--tlskey) + _filedir + return + ;; + --file|-f) + _filedir "y?(a)ml" + return + ;; + $(__docker_compose_to_extglob "$daemon_options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args --help -h --verbose --version -v" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) + ;; + esac +} + + +_docker_compose_down() { + case "$prev" in + --rmi) + COMPREPLY=( $( compgen -W "all local" -- "$cur" ) ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --rmi --volumes -v --remove-orphans" -- "$cur" ) ) + ;; + esac +} + + +_docker_compose_events() { + case "$prev" in + --json) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_exec() { + case "$prev" in + --index|--user) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "-d --help --index --privileged -T --user" -- "$cur" ) ) + ;; + *) + __docker_compose_services_running + ;; + esac +} + + +_docker_compose_help() { + COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) +} + + +_docker_compose_kill() { + case "$prev" in + -s) + COMPREPLY=( $( compgen -W "SIGHUP SIGINT SIGKILL SIGUSR1 SIGUSR2" -- "$(echo $cur | tr '[:lower:]' '[:upper:]')" ) ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) ) + ;; + *) + __docker_compose_services_running + ;; + esac +} + + +_docker_compose_logs() { + case "$prev" in + --tail) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_pause() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_compose_services_running + ;; + esac +} + + +_docker_compose_port() { + case "$prev" in + --protocol) + COMPREPLY=( $( compgen -W "tcp udp" -- "$cur" ) ) + return; + ;; + --index) + return; + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_ps() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help -q" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_pull() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --ignore-pull-failures" -- "$cur" ) ) + ;; + *) + __docker_compose_services_from_image + ;; + esac +} + + +_docker_compose_push() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_restart() { + case "$prev" in + --timeout|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) + ;; + *) + __docker_compose_services_running + ;; + esac +} + + +_docker_compose_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force -f --help -v" -- "$cur" ) ) + ;; + *) + __docker_compose_services_stopped + ;; + esac +} + + +_docker_compose_run() { + case "$prev" in + -e) + COMPREPLY=( $( compgen -e -- "$cur" ) ) + __docker_compose_nospace + return + ;; + --entrypoint|--name|--user|-u|--workdir|-w) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --name --no-deps --publish -p --rm --service-ports -T --user -u --workdir -w" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_scale() { + case "$prev" in + =) + COMPREPLY=("$cur") + return + ;; + --timeout|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) + __docker_compose_nospace + ;; + esac +} + + +_docker_compose_start() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_compose_services_stopped + ;; + esac +} + + +_docker_compose_stop() { + case "$prev" in + --timeout|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) + ;; + *) + __docker_compose_services_running + ;; + esac +} + + +_docker_compose_unpause() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_compose_services_paused + ;; + esac +} + + +_docker_compose_up() { + case "$prev" in + --timeout|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) ) + ;; + *) + __docker_compose_services_all + ;; + esac +} + + +_docker_compose_version() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--short" -- "$cur" ) ) + ;; + esac +} + + +_docker_compose() { + local previous_extglob_setting=$(shopt -p extglob) + shopt -s extglob + + local commands=( + build + bundle + config + create + down + events + exec + help + kill + logs + pause + port + ps + pull + push + restart + rm + run + scale + start + stop + unpause + up + version + ) + + # options for the docker daemon that have to be passed to secondary calls to + # docker-compose executed by this script + local daemon_boolean_options=" + --skip-hostname-check + --tls + --tlsverify + " + local daemon_options_with_args=" + --file -f + --host -H + --project-name -p + --tlscacert + --tlscert + --tlskey + " + + COMPREPLY=() + local cur prev words cword + _get_comp_words_by_ref -n : cur prev words cword + + # search subcommand and invoke its handler. + # special treatment of some top-level options + local command='docker_compose' + local daemon_options=() + local counter=1 + + while [ $counter -lt $cword ]; do + case "${words[$counter]}" in + $(__docker_compose_to_extglob "$daemon_boolean_options") ) + local opt=${words[counter]} + daemon_options+=($opt) + ;; + $(__docker_compose_to_extglob "$daemon_options_with_args") ) + local opt=${words[counter]} + local arg=${words[++counter]} + daemon_options+=($opt $arg) + ;; + -*) + ;; + *) + command="${words[$counter]}" + break + ;; + esac + (( counter++ )) + done + + local completions_func=_docker_compose_${command//-/_} + declare -F $completions_func >/dev/null && $completions_func + + eval "$previous_extglob_setting" + return 0 +} + +complete -F _docker_compose docker-compose diff --git a/completion/docker-machine.completion.sh b/completion/docker-machine.completion.sh new file mode 100644 index 0000000..a1ed9f8 --- /dev/null +++ b/completion/docker-machine.completion.sh @@ -0,0 +1,252 @@ +# +# bash completion file for docker-machine commands +# +# This script provides completion of: +# - commands and their options +# - machine names +# - filepaths +# +# To enable the completions either: +# - place this file in /etc/bash_completion.d +# or +# - copy this file to e.g. ~/.docker-machine-completion.sh and add the line +# below to your .bashrc after bash completion features are loaded +# . ~/.docker-machine-completion.sh +# + +_docker_machine_active() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=() + fi +} + +_docker_machine_config() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--swarm --help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_create() { + # cheating, b/c there are approximately one zillion options to create + COMPREPLY=($(compgen -W "$(docker-machine create --help | grep '^ -' | sed 's/^ //; s/[^a-z0-9-].*$//')" -- "${cur}")) +} + +_docker_machine_env() { + case "${prev}" in + --shell) + # What are the options for --shell? + COMPREPLY=() + ;; + *) + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--swarm --shell --unset --no-proxy --help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi + esac +} + +# See docker-machine-wrapper.bash for the use command +_docker_machine_use() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--swarm --unset --help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_inspect() { + case "${prev}" in + -f|--format) + COMPREPLY=() + ;; + *) + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--format --help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi + ;; + esac +} + +_docker_machine_ip() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_kill() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_ls() { + case "${prev}" in + --filter) + COMPREPLY=() + ;; + *) + COMPREPLY=($(compgen -W "--quiet --filter --format --timeout --help" -- "${cur}")) + ;; + esac +} + +_docker_machine_regenerate_certs() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help --force" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_restart() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_rm() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help --force -y" -- "${cur}")) + else + # For rm, it's best to be explicit + COMPREPLY=() + fi +} + +_docker_machine_ssh() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_scp() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help --recursive" -- "${cur}")) + else + _filedir + # It would be really nice to ssh to the machine and ls to complete + # remote files. + COMPREPLY=($(compgen -W "$(docker-machine ls -q | sed 's/$/:/')" -- "${cur}") "${COMPREPLY[@]}") + fi +} + +_docker_machine_start() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_status() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_stop() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_upgrade() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_url() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_version() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "$(docker-machine ls -q)" -- "${cur}")) + fi +} + +_docker_machine_help() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help" -- "${cur}")) + else + COMPREPLY=($(compgen -W "${commands[*]}" -- "${cur}")) + fi +} + +_docker_machine_docker_machine() { + if [[ " ${wants_file[*]} " =~ " ${prev} " ]]; then + _filedir + elif [[ " ${wants_dir[*]} " =~ " ${prev} " ]]; then + _filedir -d + elif [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "${flags[*]} ${wants_dir[*]} ${wants_file[*]}" -- "${cur}")) + else + COMPREPLY=($(compgen -W "${commands[*]}" -- "${cur}")) + fi +} + +_docker_machine() { + COMPREPLY=() + local commands=(active config create env inspect ip kill ls regenerate-certs restart rm ssh scp start status stop upgrade url version help) + + local flags=(--debug --native-ssh --github-api-token --bugsnag-api-token --help --version) + local wants_dir=(--storage-path) + local wants_file=(--tls-ca-cert --tls-ca-key --tls-client-cert --tls-client-key) + + # Add the use subcommand, if we have an alias loaded + if [[ ${DOCKER_MACHINE_WRAPPED} = true ]]; then + commands=("${commands[@]}" use) + fi + + local cur prev words cword + _get_comp_words_by_ref -n : cur prev words cword + local i + local command=docker-machine + + for (( i=1; i < ${cword}; ++i)); do + local word=${words[i]} + if [[ " ${wants_file[*]} ${wants_dir[*]} " =~ " ${word} " ]]; then + # skip the next option + (( ++i )) + elif [[ " ${commands[*]} " =~ " ${word} " ]]; then + command=${word} + fi + done + + local completion_func=_docker_machine_"${command//-/_}" + if declare -F "${completion_func}" > /dev/null; then + ${completion_func} + fi + + return 0 +} + +complete -F _docker_machine docker-machine diff --git a/completion/docker.completion.sh b/completion/docker.completion.sh new file mode 100644 index 0000000..1495b85 --- /dev/null +++ b/completion/docker.completion.sh @@ -0,0 +1,2965 @@ +#!/bin/bash +# +# bash completion file for core docker commands +# +# This script provides completion of: +# - commands and their options +# - container ids and names +# - image repos and tags +# - filepaths +# +# To enable the completions either: +# - place this file in /etc/bash_completion.d +# or +# - copy this file to e.g. ~/.docker-completion.sh and add the line +# below to your .bashrc after bash completion features are loaded +# . ~/.docker-completion.sh +# +# Configuration: +# +# For several commands, the amount of completions can be configured by +# setting environment variables. +# +# DOCKER_COMPLETION_SHOW_NETWORK_IDS +# DOCKER_COMPLETION_SHOW_NODE_IDS +# DOCKER_COMPLETION_SHOW_SERVICE_IDS +# "no" - Show names only (default) +# "yes" - Show names and ids +# +# You can tailor completion for the "events", "history", "inspect", "run", +# "rmi" and "save" commands by settings the following environment +# variables: +# +# DOCKER_COMPLETION_SHOW_IMAGE_IDS +# "none" - Show names only (default) +# "non-intermediate" - Show names and ids, but omit intermediate image IDs +# "all" - Show names and ids, including intermediate image IDs +# +# DOCKER_COMPLETION_SHOW_TAGS +# "yes" - include tags in completion options (default) +# "no" - don't include tags in completion options + +# +# Note: +# Currently, the completions will not work if the docker daemon is not +# bound to the default communication port/socket +# If the docker daemon is using a unix socket for communication your user +# must have access to the socket for the completions to function correctly +# +# Note for developers: +# Please arrange options sorted alphabetically by long name with the short +# options immediately following their corresponding long form. +# This order should be applied to lists, alternatives and code blocks. + +__docker_previous_extglob_setting=$(shopt -p extglob) +shopt -s extglob + +__docker_q() { + docker ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@" +} + +__docker_complete_containers_all() { + local IFS=$'\n' + local containers=( $(__docker_q ps -aq --no-trunc) ) + if [ "$1" ]; then + containers=( $(__docker_q inspect --format "{{if $1}}{{.Id}}{{end}}" "${containers[@]}") ) + fi + local names=( $(__docker_q inspect --format '{{.Name}}' "${containers[@]}") ) + names=( "${names[@]#/}" ) # trim off the leading "/" from the container names + unset IFS + COMPREPLY=( $(compgen -W "${names[*]} ${containers[*]}" -- "$cur") ) +} + +__docker_complete_containers_running() { + __docker_complete_containers_all '.State.Running' +} + +__docker_complete_containers_stopped() { + __docker_complete_containers_all 'not .State.Running' +} + +__docker_complete_containers_pauseable() { + __docker_complete_containers_all 'and .State.Running (not .State.Paused)' +} + +__docker_complete_containers_unpauseable() { + __docker_complete_containers_all '.State.Paused' +} + +__docker_complete_container_names() { + local containers=( $(__docker_q ps -aq --no-trunc) ) + local names=( $(__docker_q inspect --format '{{.Name}}' "${containers[@]}") ) + names=( "${names[@]#/}" ) # trim off the leading "/" from the container names + COMPREPLY=( $(compgen -W "${names[*]}" -- "$cur") ) +} + +__docker_complete_container_ids() { + local containers=( $(__docker_q ps -aq) ) + COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) +} + +__docker_complete_images() { + local images_args="" + + case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in + all) + images_args="--no-trunc -a" + ;; + non-intermediate) + images_args="--no-trunc" + ;; + esac + + local repo_print_command + if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then + repo_print_command='print $1; print $1":"$2' + else + repo_print_command='print $1' + fi + + local awk_script + case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in + all|non-intermediate) + awk_script='NR>1 { print $3; if ($1 != "") { '"$repo_print_command"' } }' + ;; + none|*) + awk_script='NR>1 && $1 != "" { '"$repo_print_command"' }' + ;; + esac + + local images=$(__docker_q images $images_args | awk "$awk_script") + COMPREPLY=( $(compgen -W "$images" -- "$cur") ) + __ltrim_colon_completions "$cur" +} + +__docker_complete_image_repos() { + local repos="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1 }')" + COMPREPLY=( $(compgen -W "$repos" -- "$cur") ) +} + +__docker_complete_image_repos_and_tags() { + local reposAndTags="$(__docker_q images | awk 'NR>1 && $1 != "" { print $1; print $1":"$2 }')" + COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") ) + __ltrim_colon_completions "$cur" +} + +__docker_complete_containers_and_images() { + __docker_complete_containers_all + local containers=( "${COMPREPLY[@]}" ) + __docker_complete_images + COMPREPLY+=( "${containers[@]}" ) +} + +# Returns the names and optionally IDs of networks. +# The selection can be narrowed by an optional filter parameter, e.g. 'type=custom' +__docker_networks() { + local filter="$1" + # By default, only network names are completed. + # Set DOCKER_COMPLETION_SHOW_NETWORK_IDS=yes to also complete network IDs. + local fields='$2' + [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS}" = yes ] && fields='$1,$2' + __docker_q network ls --no-trunc ${filter:+-f "$filter"} | awk "NR>1 {print $fields}" + #__docker_q network ls --no-trunc | awk "NR>1 {print $fields}" +} + +__docker_complete_networks() { + COMPREPLY=( $(compgen -W "$(__docker_networks $@)" -- "$cur") ) +} + +__docker_complete_network_ids() { + COMPREPLY=( $(compgen -W "$(__docker_q network ls -q --no-trunc)" -- "$cur") ) +} + +__docker_complete_network_names() { + COMPREPLY=( $(compgen -W "$(__docker_q network ls | awk 'NR>1 {print $2}')" -- "$cur") ) +} + +__docker_complete_containers_in_network() { + local containers=$(__docker_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1") + COMPREPLY=( $(compgen -W "$containers" -- "$cur") ) +} + +__docker_complete_volumes() { + COMPREPLY=( $(compgen -W "$(__docker_q volume ls -q)" -- "$cur") ) +} + +__docker_plugins() { + __docker_q info | sed -n "/^Plugins/,/^[^ ]/s/ $1: //p" +} + +__docker_complete_plugins() { + COMPREPLY=( $(compgen -W "$(__docker_plugins $1)" -- "$cur") ) +} + +__docker_runtimes() { + __docker_q info | sed -n 's/^Runtimes: \(.*\)/\1/p' +} + +__docker_complete_runtimes() { + COMPREPLY=( $(compgen -W "$(__docker_runtimes)" -- "$cur") ) +} + +# Returns a list of all nodes. Additional arguments to `docker node` +# may be specified in order to filter the node list, e.g. +# `__docker_nodes --filter role=manager` +# By default, only node names are completed. +# Set DOCKER_COMPLETION_SHOW_NODE_IDS=yes to also complete node IDs. +# An optional first argument `--id|--name` may be used to limit +# the output to the IDs or names of matching nodes. This setting takes +# precedence over the environment setting. +__docker_nodes() { + local fields='$2' # default: node name only + [ "${DOCKER_COMPLETION_SHOW_NODE_IDS}" = yes ] && fields='$1,$2' # ID and name + + if [ "$1" = "--id" ] ; then + fields='$1' # IDs only + shift + elif [ "$1" = "--name" ] ; then + fields='$2' # names only + shift + fi + __docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}" +} + +# Applies completion of nodes based on the current value of `$cur` or +# the value of the optional first argument `--cur`, if given. +# Additional filters may be appended, see `__docker_nodes`. +__docker_complete_nodes() { + local current=$cur + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_nodes "$@")" -- "$current") ) +} + +__docker_complete_nodes_plus_self() { + __docker_complete_nodes "$@" + COMPREPLY+=( self ) +} + +# Returns a list of all services. Additional arguments to `docker service ls` +# may be specified in order to filter the service list, e.g. +# `__docker_services --filter name=xxx` +# By default, only node names are completed. +# Set DOCKER_COMPLETION_SHOW_SERVICE_IDS=yes to also complete service IDs. +# An optional first argument `--id|--name` may be used to limit +# the output to the IDs or names of matching services. This setting takes +# precedence over the environment setting. +__docker_services() { + local fields='$2' # default: service name only + [ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name + + if [ "$1" = "--id" ] ; then + fields='$1' # IDs only + shift + elif [ "$1" = "--name" ] ; then + fields='$2' # names only + shift + fi + __docker_q service ls "$@" | awk "NR>1 {print $fields}" +} + +# Applies completion of services based on the current value of `$cur` or +# the value of the optional first argument `--cur`, if given. +# Additional filters may be appended, see `__docker_services`. +__docker_complete_services() { + local current=$cur + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_services "$@")" -- "$current") ) +} + +# Appends the word passed as an argument to every word in `$COMPREPLY`. +# Normally you do this with `compgen -S`. This function exists so that you can use +# the __docker_complete_XXX functions in cases where you need a suffix. +__docker_append_to_completions() { + COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) +} + +# Finds the position of the first word that is neither option nor an option's argument. +# If there are options that require arguments, you should pass a glob describing those +# options, e.g. "--option1|-o|--option2" +# Use this function to restrict completions to exact positions after the argument list. +__docker_pos_first_nonflag() { + local argument_flags=$1 + + local counter=$((${subcommand_pos:-${command_pos}} + 1)) + while [ $counter -le $cword ]; do + if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then + (( counter++ )) + # eat "=" in case of --option=arg syntax + [ "${words[$counter]}" = "=" ] && (( counter++ )) + else + case "${words[$counter]}" in + -*) + ;; + *) + break + ;; + esac + fi + + # Bash splits words at "=", retaining "=" as a word, examples: + # "--debug=false" => 3 words, "--log-opt syslog-facility=daemon" => 4 words + while [ "${words[$counter + 1]}" = "=" ] ; do + counter=$(( counter + 2)) + done + + (( counter++ )) + done + + echo $counter +} + +# If we are currently completing the value of a map option (key=value) +# which matches the extglob given as an argument, returns key. +# This function is needed for key-specific completions. +__docker_map_key_of_current_option() { + local glob="$1" + + local key glob_pos + if [ "$cur" = "=" ] ; then # key= case + key="$prev" + glob_pos=$((cword - 2)) + elif [[ $cur == *=* ]] ; then # key=value case (OSX) + key=${cur%=*} + glob_pos=$((cword - 1)) + elif [ "$prev" = "=" ] ; then + key=${words[$cword - 2]} # key=value case + glob_pos=$((cword - 3)) + else + return + fi + + [ "${words[$glob_pos]}" = "=" ] && ((glob_pos--)) # --option=key=value syntax + + [[ ${words[$glob_pos]} == @($glob) ]] && echo "$key" +} + +# Returns the value of the first option matching option_glob. +# Valid values for option_glob are option names like '--log-level' and +# globs like '--log-level|-l' +# Only positions between the command and the current word are considered. +__docker_value_of_option() { + local option_extglob=$(__docker_to_extglob "$1") + + local counter=$((command_pos + 1)) + while [ $counter -lt $cword ]; do + case ${words[$counter]} in + $option_extglob ) + echo ${words[$counter + 1]} + break + ;; + esac + (( counter++ )) + done +} + +# Transforms a multiline list of strings into a single line string +# with the words separated by "|". +# This is used to prepare arguments to __docker_pos_first_nonflag(). +__docker_to_alternatives() { + local parts=( $1 ) + local IFS='|' + echo "${parts[*]}" +} + +# Transforms a multiline list of options into an extglob pattern +# suitable for use in case statements. +__docker_to_extglob() { + local extglob=$( __docker_to_alternatives "$1" ) + echo "@($extglob)" +} + +# Subcommand processing. +# Locates the first occurrence of any of the subcommands contained in the +# first argument. In case of a match, calls the corresponding completion +# function and returns 0. +# If no match is found, 1 is returned. The calling function can then +# continue processing its completion. +# +# TODO if the preceding command has options that accept arguments and an +# argument is equal ot one of the subcommands, this is falsely detected as +# a match. +__docker_subcommands() { + local subcommands="$1" + + local counter=$(($command_pos + 1)) + while [ $counter -lt $cword ]; do + case "${words[$counter]}" in + $(__docker_to_extglob "$subcommands") ) + subcommand_pos=$counter + local subcommand=${words[$counter]} + local completions_func=_docker_${command}_${subcommand} + declare -F $completions_func >/dev/null && $completions_func + return 0 + ;; + esac + (( counter++ )) + done + return 1 +} + +# suppress trailing whitespace +__docker_nospace() { + # compopt is not available in ancient bash versions + type compopt &>/dev/null && compopt -o nospace +} + +__docker_complete_resolved_hostname() { + command -v host >/dev/null 2>&1 || return + COMPREPLY=( $(host 2>/dev/null "${cur%:}" | awk '/has address/ {print $4}') ) +} + +__docker_complete_capabilities() { + # The list of capabilities is defined in types.go, ALL was added manually. + COMPREPLY=( $( compgen -W " + ALL + AUDIT_CONTROL + AUDIT_WRITE + AUDIT_READ + BLOCK_SUSPEND + CHOWN + DAC_OVERRIDE + DAC_READ_SEARCH + FOWNER + FSETID + IPC_LOCK + IPC_OWNER + KILL + LEASE + LINUX_IMMUTABLE + MAC_ADMIN + MAC_OVERRIDE + MKNOD + NET_ADMIN + NET_BIND_SERVICE + NET_BROADCAST + NET_RAW + SETFCAP + SETGID + SETPCAP + SETUID + SYS_ADMIN + SYS_BOOT + SYS_CHROOT + SYSLOG + SYS_MODULE + SYS_NICE + SYS_PACCT + SYS_PTRACE + SYS_RAWIO + SYS_RESOURCE + SYS_TIME + SYS_TTY_CONFIG + WAKE_ALARM + " -- "$cur" ) ) +} + +__docker_complete_detach-keys() { + case "$prev" in + --detach-keys) + case "$cur" in + *,) + COMPREPLY=( $( compgen -W "${cur}ctrl-" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "ctrl-" -- "$cur" ) ) + ;; + esac + + __docker_nospace + return + ;; + esac + return 1 +} + +__docker_complete_isolation() { + COMPREPLY=( $( compgen -W "default hyperv process" -- "$cur" ) ) +} + +__docker_complete_log_drivers() { + COMPREPLY=( $( compgen -W " + awslogs + etwlogs + fluentd + gcplogs + gelf + journald + json-file + none + splunk + syslog + " -- "$cur" ) ) +} + +__docker_complete_log_options() { + # see docs/reference/logging/index.md + local awslogs_options="awslogs-region awslogs-group awslogs-stream" + local fluentd_options="env fluentd-address fluentd-async-connect fluentd-buffer-limit fluentd-retry-wait fluentd-max-retries labels tag" + local gcplogs_options="env gcp-log-cmd gcp-project labels" + local gelf_options="env gelf-address gelf-compression-level gelf-compression-type labels tag" + local journald_options="env labels tag" + local json_file_options="env labels max-file max-size" + local syslog_options="syslog-address syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify syslog-facility tag" + local splunk_options="env labels splunk-caname splunk-capath splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url tag" + + local all_options="$fluentd_options $gcplogs_options $gelf_options $journald_options $json_file_options $syslog_options $splunk_options" + + case $(__docker_value_of_option --log-driver) in + '') + COMPREPLY=( $( compgen -W "$all_options" -S = -- "$cur" ) ) + ;; + awslogs) + COMPREPLY=( $( compgen -W "$awslogs_options" -S = -- "$cur" ) ) + ;; + fluentd) + COMPREPLY=( $( compgen -W "$fluentd_options" -S = -- "$cur" ) ) + ;; + gcplogs) + COMPREPLY=( $( compgen -W "$gcplogs_options" -S = -- "$cur" ) ) + ;; + gelf) + COMPREPLY=( $( compgen -W "$gelf_options" -S = -- "$cur" ) ) + ;; + journald) + COMPREPLY=( $( compgen -W "$journald_options" -S = -- "$cur" ) ) + ;; + json-file) + COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) ) + ;; + syslog) + COMPREPLY=( $( compgen -W "$syslog_options" -S = -- "$cur" ) ) + ;; + splunk) + COMPREPLY=( $( compgen -W "$splunk_options" -S = -- "$cur" ) ) + ;; + *) + return + ;; + esac + + __docker_nospace +} + +__docker_complete_log_driver_options() { + local key=$(__docker_map_key_of_current_option '--log-opt') + case "$key" in + fluentd-async-connect) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + gelf-address) + COMPREPLY=( $( compgen -W "udp" -S "://" -- "${cur##*=}" ) ) + __docker_nospace + return + ;; + gelf-compression-level) + COMPREPLY=( $( compgen -W "1 2 3 4 5 6 7 8 9" -- "${cur##*=}" ) ) + return + ;; + gelf-compression-type) + COMPREPLY=( $( compgen -W "gzip none zlib" -- "${cur##*=}" ) ) + return + ;; + syslog-address) + COMPREPLY=( $( compgen -W "tcp:// tcp+tls:// udp:// unix://" -- "${cur##*=}" ) ) + __docker_nospace + __ltrim_colon_completions "${cur}" + return + ;; + syslog-facility) + COMPREPLY=( $( compgen -W " + auth + authpriv + cron + daemon + ftp + kern + local0 + local1 + local2 + local3 + local4 + local5 + local6 + local7 + lpr + mail + news + syslog + user + uucp + " -- "${cur##*=}" ) ) + return + ;; + syslog-format) + COMPREPLY=( $( compgen -W "rfc3164 rfc5424 rfc5424micro" -- "${cur##*=}" ) ) + return + ;; + syslog-tls-ca-cert|syslog-tls-cert|syslog-tls-key) + _filedir + return + ;; + syslog-tls-skip-verify) + COMPREPLY=( $( compgen -W "true" -- "${cur##*=}" ) ) + return + ;; + splunk-url) + COMPREPLY=( $( compgen -W "http:// https://" -- "${cur##*=}" ) ) + __docker_nospace + __ltrim_colon_completions "${cur}" + return + ;; + splunk-insecureskipverify) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + esac + return 1 +} + +__docker_complete_log_levels() { + COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) ) +} + +__docker_complete_restart() { + case "$prev" in + --restart) + case "$cur" in + on-failure:*) + ;; + *) + COMPREPLY=( $( compgen -W "always no on-failure on-failure: unless-stopped" -- "$cur") ) + ;; + esac + return + ;; + esac + return 1 +} + +# a selection of the available signals that is most likely of interest in the +# context of docker containers. +__docker_complete_signals() { + local signals=( + SIGCONT + SIGHUP + SIGINT + SIGKILL + SIGQUIT + SIGSTOP + SIGTERM + SIGUSR1 + SIGUSR2 + ) + COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) ) +} + +__docker_complete_user_group() { + if [[ $cur == *:* ]] ; then + COMPREPLY=( $(compgen -g -- "${cur#*:}") ) + else + COMPREPLY=( $(compgen -u -S : -- "$cur") ) + __docker_nospace + fi +} + +# global options that may appear after the docker command +_docker_docker() { + local boolean_options=" + $global_boolean_options + --help + --version -v + " + + case "$prev" in + --config) + _filedir -d + return + ;; + --log-level|-l) + __docker_complete_log_levels + return + ;; + $(__docker_to_extglob "$global_options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$boolean_options $global_options_with_args" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) + if [ $cword -eq $counter ]; then + COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) + fi + ;; + esac +} + +_docker_attach() { + __docker_complete_detach-keys && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--detach-keys --help --no-stdin --sig-proxy=false" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--detach-keys') + if [ $cword -eq $counter ]; then + __docker_complete_containers_running + fi + ;; + esac +} + +_docker_build() { + local options_with_args=" + --build-arg + --cgroup-parent + --cpuset-cpus + --cpuset-mems + --cpu-shares -c + --cpu-period + --cpu-quota + --file -f + --isolation + --label + --memory -m + --memory-swap + --shm-size + --tag -t + --ulimit + " + + local boolean_options=" + --disable-content-trust=false + --force-rm + --help + --no-cache + --pull + --quiet -q + --rm + " + + local all_options="$options_with_args $boolean_options" + + case "$prev" in + --build-arg) + COMPREPLY=( $( compgen -e -- "$cur" ) ) + __docker_nospace + return + ;; + --file|-f) + _filedir + return + ;; + --isolation) + __docker_complete_isolation + return + ;; + --tag|-t) + __docker_complete_image_repos_and_tags + return + ;; + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) + if [ $cword -eq $counter ]; then + _filedir -d + fi + ;; + esac +} + +_docker_commit() { + case "$prev" in + --author|-a|--change|-c|--message|-m) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--author -a --change -c --help --message -m --pause=false -p=false" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--author|-a|--change|-c|--message|-m') + + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + return + fi + (( counter++ )) + + if [ $cword -eq $counter ]; then + __docker_complete_image_repos_and_tags + return + fi + ;; + esac +} + +_docker_cp() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--follow-link -L --help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + case "$cur" in + *:) + return + ;; + *) + # combined container and filename completion + _filedir + local files=( ${COMPREPLY[@]} ) + + __docker_complete_containers_all + COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) + local containers=( ${COMPREPLY[@]} ) + + COMPREPLY=( $( compgen -W "${files[*]} ${containers[*]}" -- "$cur" ) ) + if [[ "$COMPREPLY" == *: ]]; then + __docker_nospace + fi + return + ;; + esac + fi + (( counter++ )) + + if [ $cword -eq $counter ]; then + if [ -e "$prev" ]; then + __docker_complete_containers_all + COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) + __docker_nospace + else + _filedir + fi + return + fi + ;; + esac +} + +_docker_create() { + _docker_run +} + +_docker_daemon() { + local boolean_options=" + $global_boolean_options + --disable-legacy-registry + --help + --icc=false + --ip-forward=false + --ip-masq=false + --iptables=false + --ipv6 + --live-restore + --raw-logs + --selinux-enabled + --userland-proxy=false + " + local options_with_args=" + $global_options_with_args + --add-runtime + --api-cors-header + --authorization-plugin + --bip + --bridge -b + --cgroup-parent + --cluster-advertise + --cluster-store + --cluster-store-opt + --config-file + --containerd + --default-gateway + --default-gateway-v6 + --default-ulimit + --dns + --dns-search + --dns-opt + --exec-opt + --exec-root + --fixed-cidr + --fixed-cidr-v6 + --graph -g + --group -G + --insecure-registry + --ip + --label + --log-driver + --log-opt + --max-concurrent-downloads + --max-concurrent-uploads + --mtu + --pidfile -p + --registry-mirror + --storage-driver -s + --storage-opt + --userns-remap + " + + __docker_complete_log_driver_options && return + + key=$(__docker_map_key_of_current_option '--cluster-store-opt') + case "$key" in + kv.*file) + cur=${cur##*=} + _filedir + return + ;; + esac + + local key=$(__docker_map_key_of_current_option '--storage-opt') + case "$key" in + dm.blkdiscard|dm.override_udev_sync_check|dm.use_deferred_removal|dm.use_deferred_deletion) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + dm.fs) + COMPREPLY=( $( compgen -W "ext4 xfs" -- "${cur##*=}" ) ) + return + ;; + dm.thinpooldev) + cur=${cur##*=} + _filedir + return + ;; + esac + + case "$prev" in + --authorization-plugin) + __docker_complete_plugins Authorization + return + ;; + --cluster-store) + COMPREPLY=( $( compgen -W "consul etcd zk" -S "://" -- "$cur" ) ) + __docker_nospace + return + ;; + --cluster-store-opt) + COMPREPLY=( $( compgen -W "discovery.heartbeat discovery.ttl kv.cacertfile kv.certfile kv.keyfile kv.path" -S = -- "$cur" ) ) + __docker_nospace + return + ;; + --exec-root|--graph|-g) + _filedir -d + return + ;; + --log-driver) + __docker_complete_log_drivers + return + ;; + --config-file|--containerd|--pidfile|-p|--tlscacert|--tlscert|--tlskey) + _filedir + return + ;; + --storage-driver|-s) + COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) ) + return + ;; + --storage-opt) + local btrfs_options="btrfs.min_space" + local devicemapper_options=" + dm.basesize + dm.blkdiscard + dm.blocksize + dm.fs + dm.loopdatasize + dm.loopmetadatasize + dm.min_free_space + dm.mkfsarg + dm.mountopt + dm.override_udev_sync_check + dm.thinpooldev + dm.use_deferred_deletion + dm.use_deferred_removal + " + local zfs_options="zfs.fsname" + + case $(__docker_value_of_option '--storage-driver|-s') in + '') + COMPREPLY=( $( compgen -W "$btrfs_options $devicemapper_options $zfs_options" -S = -- "$cur" ) ) + ;; + btrfs) + COMPREPLY=( $( compgen -W "$btrfs_options" -S = -- "$cur" ) ) + ;; + devicemapper) + COMPREPLY=( $( compgen -W "$devicemapper_options" -S = -- "$cur" ) ) + ;; + zfs) + COMPREPLY=( $( compgen -W "$zfs_options" -S = -- "$cur" ) ) + ;; + *) + return + ;; + esac + __docker_nospace + return + ;; + --log-level|-l) + __docker_complete_log_levels + return + ;; + --log-opt) + __docker_complete_log_options + return + ;; + --userns-remap) + __docker_complete_user_group + return + ;; + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) + ;; + esac +} + +_docker_diff() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_events() { + local key=$(__docker_map_key_of_current_option '-f|--filter') + case "$key" in + container) + cur="${cur##*=}" + __docker_complete_containers_all + return + ;; + daemon) + local name=$(__docker_q info | sed -n 's/^\(ID\|Name\): //p') + COMPREPLY=( $( compgen -W "$name" -- "${cur##*=}" ) ) + return + ;; + event) + COMPREPLY=( $( compgen -W " + attach + commit + connect + copy + create + delete + destroy + detach + die + disconnect + exec_create + exec_detach + exec_start + export + import + kill + load + mount + oom + pause + pull + push + reload + rename + resize + restart + save + start + stop + tag + top + unmount + unpause + untag + update + " -- "${cur##*=}" ) ) + return + ;; + image) + cur="${cur##*=}" + __docker_complete_images + return + ;; + network) + cur="${cur##*=}" + __docker_complete_networks + return + ;; + type) + COMPREPLY=( $( compgen -W "container daemon image network volume" -- "${cur##*=}" ) ) + return + ;; + volume) + cur="${cur##*=}" + __docker_complete_volumes + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "container daemon event image label network type volume" -- "$cur" ) ) + __docker_nospace + return + ;; + --since|--until) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --since --until" -- "$cur" ) ) + ;; + esac +} + +_docker_exec() { + __docker_complete_detach-keys && return + + case "$prev" in + --user|-u) + __docker_complete_user_group + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--detach -d --detach-keys --help --interactive -i --privileged -t --tty -u --user" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_running + ;; + esac +} + +_docker_export() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_help() { + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) + fi +} + +_docker_history() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_images + fi + ;; + esac +} + +_docker_images() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + before) + cur="${cur##*=}" + __docker_complete_images + return + ;; + dangling) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + label) + return + ;; + since) + cur="${cur##*=}" + __docker_complete_images + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "before dangling label since" -- "$cur" ) ) + __docker_nospace + return + ;; + --format) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --digests --filter -f --format --help --no-trunc --quiet -q" -- "$cur" ) ) + ;; + =) + return + ;; + *) + __docker_complete_image_repos + ;; + esac +} + +_docker_import() { + case "$prev" in + --change|-c|--message|-m) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m') + if [ $cword -eq $counter ]; then + return + fi + (( counter++ )) + + if [ $cword -eq $counter ]; then + __docker_complete_image_repos_and_tags + return + fi + ;; + esac +} + +_docker_info() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + esac +} + +_docker_inspect() { + case "$prev" in + --format|-f) + return + ;; + --type) + COMPREPLY=( $( compgen -W "image container" -- "$cur" ) ) + return + ;; + + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help --size -s --type" -- "$cur" ) ) + ;; + *) + case $(__docker_value_of_option --type) in + '') + __docker_complete_containers_and_images + ;; + container) + __docker_complete_containers_all + ;; + image) + __docker_complete_images + ;; + esac + esac +} + +_docker_kill() { + case "$prev" in + --signal|-s) + __docker_complete_signals + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --signal -s" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_running + ;; + esac +} + +_docker_load() { + case "$prev" in + --input|-i) + _filedir + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --input -i --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_login() { + case "$prev" in + --password|-p|--username|-u) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --password -p --username -u" -- "$cur" ) ) + ;; + esac +} + +_docker_logout() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + esac +} + +_docker_logs() { + case "$prev" in + --since|--tail) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--details --follow -f --help --since --tail --timestamps -t" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--tail') + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_network_connect() { + local options_with_args=" + --alias + --ip + --ip6 + --link + --link-local-ip + " + + local boolean_options=" + --help + " + + case "$prev" in + --link) + case "$cur" in + *:*) + ;; + *) + __docker_complete_containers_running + COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) + __docker_nospace + ;; + esac + return + ;; + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) + if [ $cword -eq $counter ]; then + __docker_complete_networks + elif [ $cword -eq $(($counter + 1)) ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_network_create() { + case "$prev" in + --aux-address|--gateway|--internal|--ip-range|--ipam-opt|--ipv6|--opt|-o|--subnet) + return + ;; + --ipam-driver) + COMPREPLY=( $( compgen -W "default" -- "$cur" ) ) + return + ;; + --driver|-d) + local plugins=" $(__docker_plugins Network) " + # remove drivers that allow one instance only + plugins=${plugins/ host / } + plugins=${plugins/ null / } + COMPREPLY=( $(compgen -W "$plugins" -- "$cur") ) + return + ;; + --label) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--aux-address --driver -d --gateway --help --internal --ip-range --ipam-driver --ipam-opt --ipv6 --label --opt -o --subnet" -- "$cur" ) ) + ;; + esac +} + +_docker_network_disconnect() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_networks + elif [ $cword -eq $(($counter + 1)) ]; then + __docker_complete_containers_in_network "$prev" + fi + ;; + esac +} + +_docker_network_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_networks + esac +} + +_docker_network_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + driver) + local plugins=" $(__docker_plugins Network) " + COMPREPLY=( $(compgen -W "$plugins" -- "${cur##*=}") ) + return + ;; + id) + cur="${cur##*=}" + __docker_complete_network_ids + return + ;; + name) + cur="${cur##*=}" + __docker_complete_network_names + return + ;; + type) + COMPREPLY=( $( compgen -W "builtin custom" -- "${cur##*=}" ) ) + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "driver id label name type" -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --no-trunc --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_network_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_networks type=custom + esac +} + +_docker_network() { + local subcommands=" + connect + create + disconnect + inspect + ls + rm + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_service() { + local subcommands=" + create + inspect + ls list + rm remove + scale + tasks + update + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_service_create() { + _docker_service_update +} + +_docker_service_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help --pretty -p" -- "$cur" ) ) + ;; + *) + __docker_complete_services + esac +} + +_docker_service_list() { + _docker_service_ls +} + +_docker_service_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + id) + __docker_complete_services --cur "${cur##*=}" --id + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_service_remove() { + _docker_service_rm +} + +_docker_service_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_services + esac +} + +_docker_service_scale() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_services + __docker_append_to_completions "=" + __docker_nospace + ;; + esac +} + +_docker_service_tasks() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + desired-state) + COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -W "desired-state id name" -S = -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve -n" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_services + fi + ;; + esac +} + +_docker_service_update() { + local $subcommand="${words[$subcommand_pos]}" + + local options_with_args=" + --constraint + --endpoint-mode + --env -e + --label -l + --limit-cpu + --limit-memory + --mode + --mount -m + --name + --network + --publish -p + --replicas + --reserve-cpu + --reserve-memory + --restart-condition + --restart-delay + --restart-max-attempts + --restart-window + --stop-grace-period + --update-delay + --update-parallelism + --user -u + --workdir -w + " + + local boolean_options=" + --help + " + + if [ "$subcommand" = "update" ] ; then + options_with_args="$options_with_args + --arg + --command + --image + " + + case "$prev" in + --image) + __docker_complete_image_repos_and_tags + return + ;; + esac + fi + + case "$prev" in + --endpoint-mode) + COMPREPLY=( $( compgen -W "DNSRR VIP" -- "$cur" ) ) + return + ;; + --env|-e) + COMPREPLY=( $( compgen -e -S = -- "$cur" ) ) + __docker_nospace + return + ;; + --mode) + COMPREPLY=( $( compgen -W "global replicated" -- "$cur" ) ) + return + ;; + --network) + __docker_complete_networks + return + ;; + --restart-condition) + COMPREPLY=( $( compgen -W "any none on-failure" -- "$cur" ) ) + return + ;; + --user|-u) + __docker_complete_user_group + return + ;; + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) + ;; + *) + if [ "$subcommand" = "update" ] ; then + __docker_complete_services + fi + esac +} + +_docker_swarm() { + local subcommands=" + init + inspect + join + leave + update + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_swarm_init() { + case "$prev" in + --auto-accept) + COMPREPLY=( $( compgen -W "manager none worker" -- "$cur" ) ) + return + ;; + --listen-addr) + if [[ $cur == *: ]] ; then + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + fi + return + ;; + --secret) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--auto-accept --force-new-cluster --help --listen-addr --secret" -- "$cur" ) ) + ;; + esac +} + +_docker_swarm_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + ;; + esac +} + +_docker_swarm_join() { + case "$prev" in + --ca-hash|--secret) + return + ;; + --listen-addr) + if [[ $cur == *: ]] ; then + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + fi + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--ca-hash --help --listen-addr --manager --secret" -- "$cur" ) ) + ;; + *:) + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + ;; + esac +} + +_docker_swarm_leave() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force --help" -- "$cur" ) ) + ;; + esac +} + +_docker_swarm_update() { + case "$prev" in + --auto-accept) + COMPREPLY=( $( compgen -W "manager none worker" -- "$cur" ) ) + return + ;; + --cert-expiry|--dispatcher-heartbeat|--secret|--task-history-limit) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--auto-accept --cert-expiry --dispatcher-heartbeat --help --secret --task-history-limit" -- "$cur" ) ) + ;; + esac +} + +_docker_node() { + local subcommands=" + accept + demote + inspect + ls list + promote + rm remove + tasks + update + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_node_accept() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes --id --filter membership=pending + esac +} + +_docker_node_demote() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes --filter role=manager + esac +} + +_docker_node_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help --pretty -p" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes + esac +} + +_docker_node_list() { + _docker_node_ls +} + +_docker_node_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + id) + __docker_complete_nodes --cur "${cur##*=}" --id + return + ;; + name) + __docker_complete_nodes --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_node_promote() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes --filter role=worker + esac +} + +_docker_node_remove() { + _docker_node_rm +} + +_docker_node_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes + esac +} + +_docker_node_tasks() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + desired-state) + COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -W "desired-state id label name" -S = -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve -n" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_nodes_plus_self + fi + ;; + esac +} + +_docker_node_update() { + case "$prev" in + --availability) + COMPREPLY=( $( compgen -W "active drain pause" -- "$cur" ) ) + return + ;; + --membership) + COMPREPLY=( $( compgen -W "accepted rejected" -- "$cur" ) ) + return + ;; + --role) + COMPREPLY=( $( compgen -W "manager worker" -- "$cur" ) ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--availability --help --membership --role" -- "$cur" ) ) + ;; + *) + __docker_complete_nodes + esac +} + +_docker_pause() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_pauseable + fi + ;; + esac +} + +_docker_port() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_ps() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + ancestor) + cur="${cur##*=}" + __docker_complete_images + return + ;; + before) + cur="${cur##*=}" + __docker_complete_containers_all + return + ;; + id) + cur="${cur##*=}" + __docker_complete_container_ids + return + ;; + name) + cur="${cur##*=}" + __docker_complete_container_names + return + ;; + network) + cur="${cur##*=}" + __docker_complete_networks + return + ;; + since) + cur="${cur##*=}" + __docker_complete_containers_all + return + ;; + status) + COMPREPLY=( $( compgen -W "created dead exited paused restarting running" -- "${cur##*=}" ) ) + return + ;; + volume) + cur="${cur##*=}" + __docker_complete_volumes + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "ancestor before exited id label name network since status volume" -- "$cur" ) ) + __docker_nospace + return + ;; + --format|--last|-n) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter -f --format --help --last -n --latest -l --no-trunc --quiet -q --size -s" -- "$cur" ) ) + ;; + esac +} + +_docker_pull() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all-tags -a --disable-content-trust=false --help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + for arg in "${COMP_WORDS[@]}"; do + case "$arg" in + --all-tags|-a) + __docker_complete_image_repos + return + ;; + esac + done + __docker_complete_image_repos_and_tags + fi + ;; + esac +} + +_docker_push() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--disable-content-trust=false --help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_image_repos_and_tags + fi + ;; + esac +} + +_docker_rename() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_all + fi + ;; + esac +} + +_docker_restart() { + case "$prev" in + --time|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_all + ;; + esac +} + +_docker_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force -f --help --link -l --volumes -v" -- "$cur" ) ) + ;; + *) + for arg in "${COMP_WORDS[@]}"; do + case "$arg" in + --force|-f) + __docker_complete_containers_all + return + ;; + esac + done + __docker_complete_containers_stopped + ;; + esac +} + +_docker_rmi() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) ) + ;; + *) + __docker_complete_images + ;; + esac +} + +_docker_run() { + local options_with_args=" + --add-host + --attach -a + --blkio-weight + --blkio-weight-device + --cap-add + --cap-drop + --cgroup-parent + --cidfile + --cpu-period + --cpu-quota + --cpuset-cpus + --cpuset-mems + --cpu-shares -c + --device + --device-read-bps + --device-read-iops + --device-write-bps + --device-write-iops + --dns + --dns-opt + --dns-search + --entrypoint + --env -e + --env-file + --expose + --group-add + --hostname -h + --ip + --ip6 + --ipc + --isolation + --kernel-memory + --label-file + --label -l + --link + --link-local-ip + --log-driver + --log-opt + --mac-address + --memory -m + --memory-swap + --memory-swappiness + --memory-reservation + --name + --net + --net-alias + --oom-score-adj + --pid + --pids-limit + --publish -p + --restart + --runtime + --security-opt + --shm-size + --stop-signal + --storage-opt + --tmpfs + --sysctl + --ulimit + --user -u + --userns + --uts + --volume-driver + --volumes-from + --volume -v + --workdir -w + " + + local boolean_options=" + --disable-content-trust=false + --help + --interactive -i + --oom-kill-disable + --privileged + --publish-all -P + --read-only + --tty -t + " + + if [ "$command" = "run" ] ; then + options_with_args="$options_with_args + --detach-keys + --health-cmd + --health-interval + --health-retries + --health-timeout + " + boolean_options="$boolean_options + --detach -d + --no-healthcheck + --rm + --sig-proxy=false + " + __docker_complete_detach-keys && return + fi + + local all_options="$options_with_args $boolean_options" + + + __docker_complete_log_driver_options && return + __docker_complete_restart && return + + local key=$(__docker_map_key_of_current_option '--security-opt') + case "$key" in + label) + [[ $cur == *: ]] && return + COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "${cur##*=}") ) + if [ "${COMPREPLY[*]}" != "disable" ] ; then + __docker_nospace + fi + return + ;; + seccomp) + local cur=${cur##*=} + _filedir + COMPREPLY+=( $( compgen -W "unconfined" -- "$cur" ) ) + return + ;; + esac + + case "$prev" in + --add-host) + case "$cur" in + *:) + __docker_complete_resolved_hostname + return + ;; + esac + ;; + --attach|-a) + COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) ) + return + ;; + --cap-add|--cap-drop) + __docker_complete_capabilities + return + ;; + --cidfile|--env-file|--label-file) + _filedir + return + ;; + --device|--tmpfs|--volume|-v) + case "$cur" in + *:*) + # TODO somehow do _filedir for stuff inside the image, if it's already specified (which is also somewhat difficult to determine) + ;; + '') + COMPREPLY=( $( compgen -W '/' -- "$cur" ) ) + __docker_nospace + ;; + /*) + _filedir + __docker_nospace + ;; + esac + return + ;; + --env|-e) + COMPREPLY=( $( compgen -e -- "$cur" ) ) + __docker_nospace + return + ;; + --ipc) + case "$cur" in + *:*) + cur="${cur#*:}" + __docker_complete_containers_running + ;; + *) + COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) + if [ "$COMPREPLY" = "container:" ]; then + __docker_nospace + fi + ;; + esac + return + ;; + --isolation) + __docker_complete_isolation + return + ;; + --link) + case "$cur" in + *:*) + ;; + *) + __docker_complete_containers_running + COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) + __docker_nospace + ;; + esac + return + ;; + --log-driver) + __docker_complete_log_drivers + return + ;; + --log-opt) + __docker_complete_log_options + return + ;; + --net) + case "$cur" in + container:*) + local cur=${cur#*:} + __docker_complete_containers_all + ;; + *) + COMPREPLY=( $( compgen -W "$(__docker_plugins Network) $(__docker_networks) container:" -- "$cur") ) + if [ "${COMPREPLY[*]}" = "container:" ] ; then + __docker_nospace + fi + ;; + esac + return + ;; + --pid) + case "$cur" in + *:*) + cur="${cur#*:}" + __docker_complete_containers_running + ;; + *) + COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) + if [ "$COMPREPLY" = "container:" ]; then + __docker_nospace + fi + ;; + esac + return + ;; + --runtime) + __docker_complete_runtimes + return + ;; + --security-opt) + COMPREPLY=( $( compgen -W "apparmor= label= no-new-privileges seccomp=" -- "$cur") ) + if [ "${COMPREPLY[*]}" != "no-new-privileges" ] ; then + __docker_nospace + fi + return + ;; + --storage-opt) + COMPREPLY=( $( compgen -W "size" -S = -- "$cur") ) + __docker_nospace + return + ;; + --user|-u) + __docker_complete_user_group + return + ;; + --userns) + COMPREPLY=( $( compgen -W "host" -- "$cur" ) ) + return + ;; + --volume-driver) + __docker_complete_plugins Volume + return + ;; + --volumes-from) + __docker_complete_containers_all + return + ;; + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) + if [ $cword -eq $counter ]; then + __docker_complete_images + fi + ;; + esac +} + +_docker_save() { + case "$prev" in + --output|-o) + _filedir + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) ) + ;; + *) + __docker_complete_images + ;; + esac +} + +_docker_search() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + is-automated) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + is-official) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "is-automated is-official stars" -- "$cur" ) ) + __docker_nospace + return + ;; + --limit) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter --help --limit --no-trunc" -- "$cur" ) ) + ;; + esac +} + +_docker_start() { + __docker_complete_detach-keys && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--attach -a --detach-keys --help --interactive -i" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_stopped + ;; + esac +} + +_docker_stats() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --help --no-stream" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_running + ;; + esac +} + +_docker_stop() { + case "$prev" in + --time|-t) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_running + ;; + esac +} + +_docker_tag() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + + if [ $cword -eq $counter ]; then + __docker_complete_image_repos_and_tags + return + fi + (( counter++ )) + + if [ $cword -eq $counter ]; then + __docker_complete_image_repos_and_tags + return + fi + ;; + esac +} + +_docker_unpause() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_unpauseable + fi + ;; + esac +} + +_docker_update() { + local options_with_args=" + --blkio-weight + --cpu-period + --cpu-quota + --cpuset-cpus + --cpuset-mems + --cpu-shares -c + --kernel-memory + --memory -m + --memory-reservation + --memory-swap + --restart + " + + local boolean_options=" + --help + " + + local all_options="$options_with_args $boolean_options" + + __docker_complete_restart && return + + case "$prev" in + $(__docker_to_extglob "$options_with_args") ) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_all + ;; + esac +} + +_docker_top() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_containers_running + fi + ;; + esac +} + +_docker_version() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + esac +} + +_docker_volume_create() { + case "$prev" in + --driver|-d) + __docker_complete_plugins Volume + return + ;; + --label|--name|--opt|-o) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--driver -d --help --label --name --opt -o" -- "$cur" ) ) + ;; + esac +} + +_docker_volume_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_volumes + ;; + esac +} + +_docker_volume_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + dangling) + COMPREPLY=( $( compgen -W "true false" -- "${cur##*=}" ) ) + return + ;; + driver) + cur=${cur##*=} + __docker_complete_plugins Volume + return + ;; + name) + cur=${cur##*=} + __docker_complete_volumes + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "dangling driver name" -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_volume_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_volumes + ;; + esac +} + +_docker_volume() { + local subcommands=" + create + inspect + ls + rm + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_wait() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + __docker_complete_containers_all + ;; + esac +} + +_docker() { + local previous_extglob_setting=$(shopt -p extglob) + shopt -s extglob + + local commands=( + attach + build + commit + cp + create + daemon + diff + events + exec + export + history + images + import + info + inspect + kill + load + login + logout + logs + network + node + pause + port + ps + pull + push + rename + restart + rm + rmi + run + save + search + service + start + stats + stop + swarm + tag + top + unpause + update + version + volume + wait + ) + + # These options are valid as global options for all client commands + # and valid as command options for `docker daemon` + local global_boolean_options=" + --debug -D + --tls + --tlsverify + " + local global_options_with_args=" + --config + --host -H + --log-level -l + --tlscacert + --tlscert + --tlskey + " + + local host config + + COMPREPLY=() + local cur prev words cword + _get_comp_words_by_ref -n : cur prev words cword + + local command='docker' command_pos=0 subcommand_pos + local counter=1 + while [ $counter -lt $cword ]; do + case "${words[$counter]}" in + # save host so that completion can use custom daemon + --host|-H) + (( counter++ )) + host="${words[$counter]}" + ;; + # save config so that completion can use custom configuration directories + --config) + (( counter++ )) + config="${words[$counter]}" + ;; + $(__docker_to_extglob "$global_options_with_args") ) + (( counter++ )) + ;; + -*) + ;; + =) + (( counter++ )) + ;; + *) + command="${words[$counter]}" + command_pos=$counter + break + ;; + esac + (( counter++ )) + done + + local binary="${words[0]}" + if [[ $binary == ?(*/)dockerd ]] ; then + # for the dockerd binary, we reuse completion of `docker daemon`. + # dockerd does not have subcommands and global options. + command=daemon + command_pos=0 + fi + + local completions_func=_docker_${command} + declare -F $completions_func >/dev/null && $completions_func + + eval "$previous_extglob_setting" + return 0 +} + +eval "$__docker_previous_extglob_setting" +unset __docker_previous_extglob_setting + +complete -F _docker docker dockerd diff --git a/completion/drush.completion.sh b/completion/drush.completion.sh new file mode 100644 index 0000000..4f3f784 --- /dev/null +++ b/completion/drush.completion.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# +# bash completion support for Drush: +# https://github.com/drush-ops/drush +# +# Originally from: +# http://github.com/drush-ops/drush/blob/master/drush.complete.sh + +# Ensure drush is available. +which drush &> /dev/null || alias drush &> /dev/null || return + +__drush_ps1() { + f="${TMPDIR:-/tmp/}/drush-env/drush-drupal-site-$$" + if [ -f $f ] + then + __DRUPAL_SITE=$(cat "$f") + else + __DRUPAL_SITE="$DRUPAL_SITE" + fi + + [[ -n "$__DRUPAL_SITE" ]] && printf "${1:- (%s)}" "$__DRUPAL_SITE" +} + +# Completion function, uses the "drush complete" command to retrieve +# completions for a specific command line COMP_WORDS. +_drush_completion() { + # Set IFS to newline (locally), since we only use newline separators, and + # need to retain spaces (or not) after completions. + local IFS=$'\n' + # The '< /dev/null' is a work around for a bug in php libedit stdin handling. + # Note that libedit in place of libreadline in some distributions. See: + # https://bugs.launchpad.net/ubuntu/+source/php5/+bug/322214 + COMPREPLY=( $(drush --early=includes/complete.inc "${COMP_WORDS[@]}" < /dev/null 2> /dev/null) ) +} + +# Register our completion function. We include common short aliases for Drush. +complete -o bashdefault -o default -o nospace -F _drush_completion d dr drush drush5 drush6 drush6 drush.php diff --git a/completion/fabric-completion.sh b/completion/fabric-completion.sh new file mode 100644 index 0000000..7809b38 --- /dev/null +++ b/completion/fabric-completion.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash +# +# Bash completion support for Fabric (http://fabfile.org/) +# +# +# Copyright (C) 2011 by Konstantin Bakulin +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# Thanks to: +# - Adam Vandenberg, +# https://github.com/adamv/dotfiles/blob/master/completion_scripts/fab_completion.bash +# +# - Enrico Batista da Luz, +# https://github.com/ricobl/dotfiles/blob/master/bin/fab_bash_completion +# + + +# Use cache files for fab tasks or not. +# If set to "false" command "fab --shortlist" will be executed every time. +export FAB_COMPLETION_CACHE_TASKS=true + +# File name where tasks cache will be stored (in current dir). +export FAB_COMPLETION_CACHED_TASKS_FILENAME=".fab_tasks~" + + +# Set command to get time of last file modification as seconds since Epoch +case `uname` in + Darwin|FreeBSD) + __FAB_COMPLETION_MTIME_COMMAND="stat -f '%m'" + ;; + *) + __FAB_COMPLETION_MTIME_COMMAND="stat -c '%Y'" + ;; +esac + + +# +# Get time of last fab cache file modification as seconds since Epoch +# +function __fab_chache_mtime() { + ${__FAB_COMPLETION_MTIME_COMMAND} \ + $FAB_COMPLETION_CACHED_TASKS_FILENAME | xargs -n 1 expr +} + + +# +# Get time of last fabfile file/module modification as seconds since Epoch +# +function __fab_fabfile_mtime() { + local f="fabfile" + if [[ -e "$f.py" ]]; then + ${__FAB_COMPLETION_MTIME_COMMAND} "$f.py" | xargs -n 1 expr + else + # Suppose that it's a fabfile dir + find $f/*.py -exec ${__FAB_COMPLETION_MTIME_COMMAND} {} + \ + | xargs -n 1 expr | sort -n -r | head -1 + fi +} + + +# +# Completion for "fab" command +# +function __fab_completion() { + # Return if "fab" command doesn't exists + [[ -e `which fab 2> /dev/null` ]] || return 0 + + # Variables to hold the current word and possible matches + local cur="${COMP_WORDS[COMP_CWORD]}" + local opts=() + + # Generate possible matches and store them in variable "opts" + case "${cur}" in + -*) + if [[ -z "${__FAB_COMPLETION_LONG_OPT}" ]]; then + export __FAB_COMPLETION_LONG_OPT=$( + fab --help | egrep -o "\-\-[A-Za-z_\-]+\=?" | sort -u) + fi + opts="${__FAB_COMPLETION_LONG_OPT}" + ;; + + # Completion for short options is not nessary. + # It's left here just for history. + # -*) + # if [[ -z "${__FAB_COMPLETION_SHORT_OPT}" ]]; then + # export __FAB_COMPLETION_SHORT_OPT=$( + # fab --help | egrep -o "^ +\-[A-Za-z_\]" | sort -u) + # fi + # opts="${__FAB_COMPLETION_SHORT_OPT}" + # ;; + + *) + # If "fabfile.py" or "fabfile" dir with "__init__.py" file exists + local f="fabfile" + if [[ -e "$f.py" || (-d "$f" && -e "$f/__init__.py") ]]; then + # Build a list of the available tasks + if $FAB_COMPLETION_CACHE_TASKS; then + # If use cache + if [[ ! -s ${FAB_COMPLETION_CACHED_TASKS_FILENAME} || + $(__fab_fabfile_mtime) -gt $(__fab_chache_mtime) ]]; then + fab --shortlist > ${FAB_COMPLETION_CACHED_TASKS_FILENAME} \ + 2> /dev/null + fi + opts=$(cat ${FAB_COMPLETION_CACHED_TASKS_FILENAME}) + else + # Without cache + opts=$(fab --shortlist 2> /dev/null) + fi + fi + ;; + esac + + # Set possible completions + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) +} +complete -o default -o nospace -F __fab_completion fab diff --git a/completion/gem.completion.sh b/completion/gem.completion.sh new file mode 100644 index 0000000..de986e0 --- /dev/null +++ b/completion/gem.completion.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Completion for gem + +_installcomp() { + if [ -z "$REMOTE_GEMS" ] + then + REMOTE_GEMS=( $(gem list --remote --no-versions | tr '\n' ' ') ) + fi + + local cur=${COMP_WORDS[COMP_CWORD]} + COMPREPLY=( $(compgen -W "${REMOTE_GEMS[*]}" -- $cur) ) +} + +_uninstallcomp() { + if [ -z "$LOCAL_GEMS" ] + then + LOCAL_GEMS=( $(gem list --no-versions | sed 's/\*\*\* LOCAL GEMS \*\*\*//' | tr '\n' ' ') ) + fi + + local cur=${COMP_WORDS[COMP_CWORD]} + COMPREPLY=( $(compgen -W "${LOCAL_GEMS[*]}" -- $cur) ) +} + +_gem() { + local cur=${COMP_WORDS[COMP_CWORD]} + local prev=${COMP_WORDS[COMP_CWORD-1]} + case $prev in + install) + _installcomp + return 0 + ;; + uninstall) + _uninstallcomp + return 0 + ;; + esac + local commands=(build cert check cleanup contents dependency environment fetch generate_index help install list lock outdated owner pristine push query rdoc search server sources specification stale uninstall unpack update which) + COMPREPLY=( $(compgen -W "${commands[*]}" -- $cur) ) +} + +complete -F _gem gem diff --git a/completion/gh.completion.sh b/completion/gh.completion.sh new file mode 100644 index 0000000..c294938 --- /dev/null +++ b/completion/gh.completion.sh @@ -0,0 +1,366 @@ +# hub tab-completion script for bash. +# This script complements the completion script that ships with git. + +# Check that git tab completion is available +if declare -F _git > /dev/null; then + # Duplicate and rename the 'list_all_commands' function + eval "$(declare -f __git_list_all_commands | \ + sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')" + + # Wrap the 'list_all_commands' function with extra hub commands + __git_list_all_commands() { + cat <<-EOF +alias +pull-request +fork +create +browse +compare +ci-status +release +issue +update +EOF + __git_list_all_commands_without_hub + } + + # Ensure cached commands are cleared + __git_all_commands="" + + ########################## + # hub command completions + ########################## + + # hub alias [-s] [SHELL] + _git_alias() { + local i c=2 s=-s sh shells="bash zsh sh ksh csh fish" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -s) + unset s + ;; + *) + for sh in $shells; do + if [ "$sh" = "$i" ]; then + unset shells + break + fi + done + ;; + esac + ((c++)) + done + __gitcomp "$s $shells" + } + + # hub browse [-u] [--|[USER/]REPOSITORY] [SUBPAGE] + _git_browse() { + local i c=2 u=-u repo subpage + local subpages_="commits issues tree wiki pulls branches stargazers + contributors network network/ graphs graphs/" + local subpages_network="members" + local subpages_graphs="commit-activity code-frequency punch-card" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -u) + unset u + ;; + *) + if [ -z "$repo" ]; then + repo=$i + else + subpage=$i + fi + ;; + esac + ((c++)) + done + if [ -z "$repo" ]; then + __gitcomp "$u -- $(__hub_github_repos '\p')" + elif [ -z "$subpage" ]; then + case "$cur" in + */*) + local pfx="${cur%/*}" cur_="${cur#*/}" + local subpages_var="subpages_$pfx" + __gitcomp "${!subpages_var}" "$pfx/" "$cur_" + ;; + *) + __gitcomp "$u ${subpages_}" + ;; + esac + else + __gitcomp "$u" + fi + } + + # hub compare [-u] [USER[/REPOSITORY]] [[START...]END] + _git_compare() { + local i c=$((cword - 1)) u=-u user remote owner repo arg_repo rev + while [ $c -gt 1 ]; do + i="${words[c]}" + case "$i" in + -u) + unset u + ;; + *) + if [ -z "$rev" ]; then + # Even though the logic below is able to complete both user/repo + # and revision in the right place, when there is only one argument + # (other than -u) in the command, that argument will be taken as + # revision. For example: + # $ hub compare -u upstream + # > https://github.com/USER/REPO/compare/upstream + if __hub_github_repos '\p' | grep -Eqx "^$i(/[^/]+)?"; then + arg_repo=$i + else + rev=$i + fi + elif [ -z "$arg_repo" ]; then + arg_repo=$i + fi + ;; + esac + ((c--)) + done + + # Here we want to find out the git remote name of user/repo, in order to + # generate an appropriate revision list + if [ -z "$arg_repo" ]; then + user=$(__hub_github_user) + if [ -z "$user" ]; then + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + if [ "$remote" = origin ]; then + break + fi + done + else + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + owner=${repo%%/*} + if [ "$user" = "$owner" ]; then + break + fi + done + fi + else + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + owner=${repo%%/*} + case "$arg_repo" in + "$repo"|"$owner") + break + ;; + esac + done + fi + + local pfx cur_="$cur" + case "$cur_" in + *..*) + pfx="${cur_%%..*}..." + cur_="${cur_##*..}" + __gitcomp_nl "$(__hub_revlist $remote)" "$pfx" "$cur_" + ;; + *) + if [ -z "${arg_repo}${rev}" ]; then + __gitcomp "$u $(__hub_github_repos '\o\n\p') $(__hub_revlist $remote)" + elif [ -z "$rev" ]; then + __gitcomp "$u $(__hub_revlist $remote)" + else + __gitcomp "$u" + fi + ;; + esac + } + + # hub create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE] + _git_create() { + local i c=2 name repo flags="-p -d -h" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-h) + ((c++)) + flags=${flags/$i/} + ;; + -p) + flags=${flags/$i/} + ;; + *) + name=$i + ;; + esac + ((c++)) + done + if [ -z "$name" ]; then + repo=$(basename "$(pwd)") + fi + case "$prev" in + -d|-h) + COMPREPLY=() + ;; + -p|*) + __gitcomp "$repo $flags" + ;; + esac + } + + # hub fork [--no-remote] + _git_fork() { + local i c=2 remote=yes + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --no-remote) + unset remote + ;; + esac + ((c++)) + done + if [ -n "$remote" ]; then + __gitcomp "--no-remote" + fi + } + + # hub pull-request [-f] [-m |-F |-i |] [-b ] [-h ] + _git_pull_request() { + local i c=2 flags="-f -m -F -i -b -h" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -m|-F|-i|-b|-h) + ((c++)) + flags=${flags/$i/} + ;; + -f) + flags=${flags/$i/} + ;; + esac + ((c++)) + done + case "$prev" in + -i) + COMPREPLY=() + ;; + -b|-h) + # (Doesn't seem to need this...) + # Uncomment the following line when 'owner/repo:[TAB]' misbehaved + #_get_comp_words_by_ref -n : cur + __gitcomp_nl "$(__hub_heads)" + # __ltrim_colon_completions "$cur" + ;; + -F) + COMPREPLY=( "$cur"* ) + ;; + -f|*) + __gitcomp "$flags" + ;; + esac + } + + ################### + # Helper functions + ################### + + # __hub_github_user [HOST] + # Return $GITHUB_USER or the default github user defined in hub config + # HOST - Host to be looked-up in hub config. Default is "github.com" + __hub_github_user() { + if [ -n "$GITHUB_USER" ]; then + echo $GITHUB_USER + return + fi + local line h k v host=${1:-github.com} config=${HUB_CONFIG:-~/.config/gh} + if [ -f "$config" ]; then + while read line; do + if [ "$line" = "---" ]; then + continue + fi + k=${line%%:*} + v=${line#*:} + if [ -z "$v" ]; then + if [ "$h" = "$host" ]; then + break + fi + h=$k + continue + fi + k=${k#* } + v=${v#* } + if [ "$h" = "$host" ] && [ "$k" = "user" ]; then + echo "$v" + break + fi + done < "$config" + fi + } + + # __hub_github_repos [FORMAT] + # List all github hosted repository + # FORMAT - Format string contains multiple of these: + # \m remote + # \p owner/repo + # \o owner + # escaped characters (\n, \t ...etc) work + # If omitted, prints all github repos in the format of "remote:owner/repo" + __hub_github_repos() { + local f format=$1 + if [ -z "$(__gitdir)" ]; then + return + fi + if [ -z "$format" ]; then + format='\1:\2' + else + format=${format//\m/\1} + format=${format//\p/\2} + format=${format//\o/\3} + fi + command git config --get-regexp 'remote\.[^.]*\.url' | + grep -E ' ((https?|git)://|git@)github\.com[:/][^:/]+/[^/]+$' | + sed -E 's#^remote\.([^.]+)\.url +.+[:/](([^/]+)/[^.]+)(\.git)?$#'"$format"'#' + } + + # __hub_heads + # List all local "branch", and remote "owner/repo:branch" + __hub_heads() { + local i remote repo branch dir=$(__gitdir) + if [ -d "$dir" ]; then + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/heads/" + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/remotes/${remote}/" | while read branch; do + echo "${repo}:${branch#${remote}/}" + done + done + fi + } + + # __hub_revlist [REMOTE] + # List all tags, and branches under REMOTE, without the "remote/" prefix + # REMOTE - Remote name to search branches from. Default is "origin" + __hub_revlist() { + local i remote=${1:-origin} dir=$(__gitdir) + if [ -d "$dir" ]; then + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/remotes/${remote}/" | while read i; do + echo "${i#${remote}/}" + done + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/tags/" + fi + } + + # Enable completion for hub even when not using the alias + complete -o bashdefault -o default -o nospace -F _git gh 2>/dev/null \ + || complete -o default -o nospace -F _git gh +fi + diff --git a/completion/git.completion.sh b/completion/git.completion.sh new file mode 100644 index 0000000..e3918c8 --- /dev/null +++ b/completion/git.completion.sh @@ -0,0 +1,2776 @@ +# bash/zsh completion support for core Git. +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). +# Distributed under the GNU General Public License, version 2.0. +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) .git/remotes file names +# *) git 'subcommands' +# *) git email aliases for git-send-email +# *) tree paths within 'ref:path/to/file' expressions +# *) file paths within current working directory and index +# *) common --long-options +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.git-completion.bash). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-completion.bash +# 3) Consider changing your PS1 to also show the current branch, +# see git-prompt.sh for details. +# +# If you use complex aliases of form '!f() { ... }; f', you can use the null +# command ':' as the first command in the function body to declare the desired +# completion style. For example '!f() { : git commit ; ... }; f' will +# tell the completion to use commit completion. This also works with aliases +# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". + +case "$COMP_WORDBREAKS" in +*:*) : great ;; +*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" +esac + +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + if [ -n "${__git_dir-}" ]; then + echo "$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" || return 1 + echo "$GIT_DIR" + elif [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# The following function is based on code from: +# +# bash_completion - programmable completion functions for bash 3.2+ +# +# Copyright © 2006-2008, Ian Macdonald +# © 2009-2010, Bash Completion Maintainers +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The latest version of this software can be obtained here: +# +# http://bash-completion.alioth.debian.org/ +# +# RELEASE: 2.x + +# This function can be used to access a tokenized list of words +# on the command line: +# +# __git_reassemble_comp_words_by_ref '=:' +# if test "${words_[cword_-1]}" = -w +# then +# ... +# fi +# +# The argument should be a collection of characters from the list of +# word completion separators (COMP_WORDBREAKS) to treat as ordinary +# characters. +# +# This is roughly equivalent to going back in time and setting +# COMP_WORDBREAKS to exclude those characters. The intent is to +# make option types like --date= and : easy to +# recognize by treating each shell word as a single token. +# +# It is best not to set COMP_WORDBREAKS directly because the value is +# shared with other completion scripts. By the time the completion +# function gets called, COMP_WORDS has already been populated so local +# changes to COMP_WORDBREAKS have no effect. +# +# Output: words_, cword_, cur_. + +__git_reassemble_comp_words_by_ref() +{ + local exclude i j first + # Which word separators to exclude? + exclude="${1//[^$COMP_WORDBREAKS]}" + cword_=$COMP_CWORD + if [ -z "$exclude" ]; then + words_=("${COMP_WORDS[@]}") + return + fi + # List of word completion separators has shrunk; + # re-assemble words to complete. + for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do + # Append each nonempty word consisting of just + # word separator characters to the current word. + first=t + while + [ $i -gt 0 ] && + [ -n "${COMP_WORDS[$i]}" ] && + # word consists of excluded word separators + [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] + do + # Attach to the previous token, + # unless the previous token is the command name. + if [ $j -ge 2 ] && [ -n "$first" ]; then + ((j--)) + fi + first= + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + if (($i < ${#COMP_WORDS[@]} - 1)); then + ((i++)) + else + # Done. + return + fi + done + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + done +} + +if ! type _get_comp_words_by_ref >/dev/null 2>&1; then +_get_comp_words_by_ref () +{ + local exclude cur_ words_ cword_ + if [ "$1" = "-n" ]; then + exclude=$2 + shift 2 + fi + __git_reassemble_comp_words_by_ref "$exclude" + cur_=${words_[cword_]} + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=$cur_ + ;; + prev) + prev=${words_[$cword_-1]} + ;; + words) + words=("${words_[@]}") + ;; + cword) + cword=$cword_ + ;; + esac + shift + done +} +fi + +__gitcompappend () +{ + local x i=${#COMPREPLY[@]} + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +__gitcompadd () +{ + COMPREPLY=() + __gitcompappend "$@" +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp () +{ + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c i=0 IFS=$' \t\n' + for c in $1; do + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; + esac +} + +# Variation of __gitcomp_nl () that appends to the existing list of +# completion candidates, COMPREPLY. +__gitcomp_nl_append () +{ + local IFS=$'\n' + __gitcompappend "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words, separated by a single newline. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word instead of +# the default space (optional). If specified but empty, nothing is +# appended. +__gitcomp_nl () +{ + COMPREPLY=() + __gitcomp_nl_append "$@" +} + +# Generates completion reply with compgen from newline-separated possible +# completion filenames. +# It accepts 1 to 3 arguments: +# 1: List of possible completion filenames, separated by a single newline. +# 2: A directory prefix to be added to each possible completion filename +# (optional). +# 3: Generate possible completion matches for this word (optional). +__gitcomp_file () +{ + local IFS=$'\n' + + # XXX does not work when the directory prefix contains a tilde, + # since tilde expansion is not applied. + # This means that COMPREPLY will be empty and Bash default + # completion will be used. + __gitcompadd "$1" "${2-}" "${3-$cur}" "" + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ > /dev/null +} + +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. +__git_ls_files_helper () +{ + if [ "$2" == "--committable" ]; then + git -C "$1" diff-index --name-only --relative HEAD + else + # NOTE: $2 is not quoted in order to support multiple options + git -C "$1" ls-files --exclude-standard $2 + fi 2>/dev/null +} + + +# __git_index_files accepts 1 or 2 arguments: +# 1: Options to pass to ls-files (required). +# 2: A directory path (optional). +# If provided, only files within the specified directory are listed. +# Sub directories are never recursed. Path must have a trailing +# slash. +__git_index_files () +{ + local dir="$(__gitdir)" root="${2-.}" file + + if [ -d "$dir" ]; then + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + done | sort | uniq + fi +} + +__git_heads () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/heads + return + fi +} + +__git_tags () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/tags + return + fi +} + +# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments +# presence of 2nd argument means use the guess heuristic employed +# by checkout for tracking branches +__git_refs () +{ + local i hash dir="$(__gitdir "${1-}")" track="${2-}" + local format refs + if [ -d "$dir" ]; then + case "$cur" in + refs|refs/*) + format="refname" + refs="${cur%/*}" + track="" + ;; + *) + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do + if [ -e "$dir/$i" ]; then echo $i; fi + done + format="refname:short" + refs="refs/tags refs/heads refs/remotes" + ;; + esac + git --git-dir="$dir" for-each-ref --format="%($format)" \ + $refs + if [ -n "$track" ]; then + # employ the heuristic used by git checkout + # Try to find a remote branch that matches the completion word + # but only output if the branch name is unique + local ref entry + git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \ + "refs/remotes/" | \ + while read -r entry; do + eval "$entry" + ref="${ref#*/}" + if [[ "$ref" == "$cur"* ]]; then + echo "$ref" + fi + done | sort | uniq -u + fi + return + fi + case "$cur" in + refs|refs/*) + git ls-remote "$dir" "$cur*" 2>/dev/null | \ + while read -r hash i; do + case "$i" in + *^{}) ;; + *) echo "$i" ;; + esac + done + ;; + *) + echo "HEAD" + git for-each-ref --format="%(refname:short)" -- \ + "refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##" + ;; + esac +} + +# __git_refs2 requires 1 argument (to pass to __git_refs) +__git_refs2 () +{ + local i + for i in $(__git_refs "$1"); do + echo "$i:$i" + done +} + +# __git_refs_remotes requires 1 argument (to pass to ls-remote) +__git_refs_remotes () +{ + local i hash + git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ + while read -r hash i; do + echo "$i:refs/remotes/$1/${i#refs/heads/}" + done +} + +__git_remotes () +{ + local d="$(__gitdir)" + test -d "$d/remotes" && ls -1 "$d/remotes" + git --git-dir="$d" remote +} + +__git_list_merge_strategies () +{ + git merge -s help 2>&1 | + sed -n -e '/[Aa]vailable strategies are: /,/^$/{ + s/\.$// + s/.*:// + s/^[ ]*// + s/[ ]*$// + p + }' +} + +__git_merge_strategies= +# 'git merge -s help' (and thus detection of the merge strategy +# list) fails, unfortunately, if run outside of any git working +# tree. __git_merge_strategies is set to the empty string in +# that case, and the detection will be repeated the next time it +# is needed. +__git_compute_merge_strategies () +{ + test -n "$__git_merge_strategies" || + __git_merge_strategies=$(__git_list_merge_strategies) +} + +__git_complete_revlist_file () +{ + local pfx ls ref cur_="$cur" + case "$cur_" in + *..?*:*) + return + ;; + ?*:*) + ref="${cur_%%:*}" + cur_="${cur_#*:}" + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + ls="$ref:$pfx" + pfx="$pfx/" + ;; + *) + ls="$ref" + ;; + esac + + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="$ref:$pfx" ;; + esac + + __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ + | sed '/^100... blob /{ + s,^.* ,, + s,$, , + } + /^120000 blob /{ + s,^.* ,, + s,$, , + } + /^040000 tree /{ + s,^.* ,, + s,$,/, + } + s/^.* //')" \ + "$pfx" "$cur_" "" + ;; + *...*) + pfx="${cur_%...*}..." + cur_="${cur_#*...}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *..*) + pfx="${cur_%..*}.." + cur_="${cur_#*..}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + + +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ + local pfx="" cur_="$cur" + + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + pfx="${pfx}/" + ;; + esac + + __gitcomp_file "$(__git_index_files "$1" ${pfx:+"$pfx"})" "$pfx" "$cur_" +} + +__git_complete_file () +{ + __git_complete_revlist_file +} + +__git_complete_revlist () +{ + __git_complete_revlist_file +} + +__git_complete_remote_or_refspec () +{ + local cur_="$cur" cmd="${words[1]}" + local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 + if [ "$cmd" = "remote" ]; then + ((c++)) + fi + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; + --all) + case "$cmd" in + push) no_complete_refspec=1 ;; + fetch) + return + ;; + *) ;; + esac + ;; + -*) ;; + *) remote="$i"; break ;; + esac + ((c++)) + done + if [ -z "$remote" ]; then + __gitcomp_nl "$(__git_remotes)" + return + fi + if [ $no_complete_refspec = 1 ]; then + return + fi + [ "$remote" = "." ] && remote= + case "$cur_" in + *:*) + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="${cur_%%:*}:" ;; + esac + cur_="${cur_#*:}" + lhs=0 + ;; + +*) + pfx="+" + cur_="${cur_#+}" + ;; + esac + case "$cmd" in + fetch) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + pull|remote) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + push) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + fi + ;; + esac +} + +__git_complete_strategy () +{ + __git_compute_merge_strategies + case "$prev" in + -s|--strategy) + __gitcomp "$__git_merge_strategies" + return 0 + esac + case "$cur" in + --strategy=*) + __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}" + return 0 + ;; + esac + return 1 +} + +__git_commands () { + if test -n "${GIT_TESTING_COMMAND_COMPLETION:-}" + then + printf "%s" "${GIT_TESTING_COMMAND_COMPLETION}" + else + git help -a|egrep '^ [a-zA-Z0-9]' + fi +} + +__git_list_all_commands () +{ + local i IFS=" "$'\n' + for i in $(__git_commands) + do + case $i in + *--*) : helper pattern;; + *) echo $i;; + esac + done +} + +__git_all_commands= +__git_compute_all_commands () +{ + test -n "$__git_all_commands" || + __git_all_commands=$(__git_list_all_commands) +} + +__git_list_porcelain_commands () +{ + local i IFS=" "$'\n' + __git_compute_all_commands + for i in $__git_all_commands + do + case $i in + *--*) : helper pattern;; + applymbox) : ask gittus;; + applypatch) : ask gittus;; + archimport) : import;; + cat-file) : plumbing;; + check-attr) : plumbing;; + check-ignore) : plumbing;; + check-mailmap) : plumbing;; + check-ref-format) : plumbing;; + checkout-index) : plumbing;; + column) : internal helper;; + commit-tree) : plumbing;; + count-objects) : infrequent;; + credential) : credentials;; + credential-*) : credentials helper;; + cvsexportcommit) : export;; + cvsimport) : import;; + cvsserver) : daemon;; + daemon) : daemon;; + diff-files) : plumbing;; + diff-index) : plumbing;; + diff-tree) : plumbing;; + fast-import) : import;; + fast-export) : export;; + fsck-objects) : plumbing;; + fetch-pack) : plumbing;; + fmt-merge-msg) : plumbing;; + for-each-ref) : plumbing;; + hash-object) : plumbing;; + http-*) : transport;; + index-pack) : plumbing;; + init-db) : deprecated;; + local-fetch) : plumbing;; + ls-files) : plumbing;; + ls-remote) : plumbing;; + ls-tree) : plumbing;; + mailinfo) : plumbing;; + mailsplit) : plumbing;; + merge-*) : plumbing;; + mktree) : plumbing;; + mktag) : plumbing;; + pack-objects) : plumbing;; + pack-redundant) : plumbing;; + pack-refs) : plumbing;; + parse-remote) : plumbing;; + patch-id) : plumbing;; + prune) : plumbing;; + prune-packed) : plumbing;; + quiltimport) : import;; + read-tree) : plumbing;; + receive-pack) : plumbing;; + remote-*) : transport;; + rerere) : plumbing;; + rev-list) : plumbing;; + rev-parse) : plumbing;; + runstatus) : plumbing;; + sh-setup) : internal;; + shell) : daemon;; + show-ref) : plumbing;; + send-pack) : plumbing;; + show-index) : plumbing;; + ssh-*) : transport;; + stripspace) : plumbing;; + symbolic-ref) : plumbing;; + unpack-file) : plumbing;; + unpack-objects) : plumbing;; + update-index) : plumbing;; + update-ref) : plumbing;; + update-server-info) : daemon;; + upload-archive) : plumbing;; + upload-pack) : plumbing;; + write-tree) : plumbing;; + var) : infrequent;; + verify-pack) : infrequent;; + verify-tag) : plumbing;; + *) echo $i;; + esac + done +} + +__git_porcelain_commands= +__git_compute_porcelain_commands () +{ + test -n "$__git_porcelain_commands" || + __git_porcelain_commands=$(__git_list_porcelain_commands) +} + +# Lists all set config variables starting with the given section prefix, +# with the prefix removed. +__git_get_config_variables () +{ + local section="$1" i IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do + echo "${i#$section.}" + done +} + +__git_pretty_aliases () +{ + __git_get_config_variables "pretty" +} + +__git_aliases () +{ + __git_get_config_variables "alias" +} + +# __git_aliased_command requires 1 argument +__git_aliased_command () +{ + local word cmdline=$(git --git-dir="$(__gitdir)" \ + config --get "alias.$1") + for word in $cmdline; do + case "$word" in + \!gitk|gitk) + echo "gitk" + return + ;; + \!*) : shell command alias ;; + -*) : option ;; + *=*) : setting env ;; + git) : git itself ;; + \(\)) : skip parens of shell function definition ;; + {) : skip start of shell helper function ;; + :) : skip null command ;; + \'*) : skip opening quote after sh -c ;; + *) + echo "$word" + return + esac + done +} + +# __git_find_on_cmdline requires 1 argument +__git_find_on_cmdline () +{ + local word subcommand c=1 + while [ $c -lt $cword ]; do + word="${words[c]}" + for subcommand in $1; do + if [ "$subcommand" = "$word" ]; then + echo "$subcommand" + return + fi + done + ((c++)) + done +} + +__git_has_doubledash () +{ + local c=1 + while [ $c -lt $cword ]; do + if [ "--" = "${words[c]}" ]; then + return 0 + fi + ((c++)) + done + return 1 +} + +# Try to count non option arguments passed on the command line for the +# specified git command. +# When options are used, it is necessary to use the special -- option to +# tell the implementation were non option arguments begin. +# XXX this can not be improved, since options can appear everywhere, as +# an example: +# git mv x -n y +# +# __git_count_arguments requires 1 argument: the git command executed. +__git_count_arguments () +{ + local word i c=0 + + # Skip "git" (first argument) + for ((i=1; i < ${#words[@]}; i++)); do + word="${words[i]}" + + case "$word" in + --) + # Good; we can assume that the following are only non + # option arguments. + ((c = 0)) + ;; + "$1") + # Skip the specified git command and discard git + # main options + ((c = 0)) + ;; + ?*) + ((c++)) + ;; + esac + done + + printf "%d" $c +} + +__git_whitespacelist="nowarn warn error error-all fix" + +_git_am () +{ + local dir="$(__gitdir)" + if [ -d "$dir"/rebase-apply ]; then + __gitcomp "--skip --continue --resolved --abort" + return + fi + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --3way --committer-date-is-author-date --ignore-date + --ignore-whitespace --ignore-space-change + --interactive --keep --no-utf8 --signoff --utf8 + --whitespace= --scissors + " + return + esac +} + +_git_apply () +{ + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --stat --numstat --summary --check --index + --cached --index-info --reverse --reject --unidiff-zero + --apply --no-add --exclude= + --ignore-whitespace --ignore-space-change + --whitespace= --inaccurate-eof --verbose + " + return + esac +} + +_git_add () +{ + case "$cur" in + --*) + __gitcomp " + --interactive --refresh --patch --update --dry-run + --ignore-errors --intent-to-add + " + return + esac + + # XXX should we check for --update and --all options ? + __git_complete_index_file "--others --modified --directory --no-empty-directory" +} + +_git_archive () +{ + case "$cur" in + --format=*) + __gitcomp "$(git archive --list)" "" "${cur##--format=}" + return + ;; + --remote=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--remote=}" + return + ;; + --*) + __gitcomp " + --format= --list --verbose + --prefix= --remote= --exec= + " + return + ;; + esac + __git_complete_file +} + +_git_bisect () +{ + __git_has_doubledash && return + + local subcommands="start bad good skip reset visualize replay log run" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + if [ -f "$(__gitdir)"/BISECT_START ]; then + __gitcomp "$subcommands" + else + __gitcomp "replay start" + fi + return + fi + + case "$subcommand" in + bad|good|reset|skip|start) + __gitcomp_nl "$(__git_refs)" + ;; + *) + ;; + esac +} + +_git_branch () +{ + local i c=1 only_local_ref="n" has_r="n" + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-m) only_local_ref="y" ;; + -r) has_r="y" ;; + esac + ((c++)) + done + + case "$cur" in + --set-upstream-to=*) + __gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}" + ;; + --*) + __gitcomp " + --color --no-color --verbose --abbrev= --no-abbrev + --track --no-track --contains --merged --no-merged + --set-upstream-to= --edit-description --list + --unset-upstream + " + ;; + *) + if [ $only_local_ref = "y" -a $has_r = "n" ]; then + __gitcomp_nl "$(__git_heads)" + else + __gitcomp_nl "$(__git_refs)" + fi + ;; + esac +} + +_git_bundle () +{ + local cmd="${words[2]}" + case "$cword" in + 2) + __gitcomp "create list-heads verify unbundle" + ;; + 3) + # looking for a file + ;; + *) + case "$cmd" in + create) + __git_complete_revlist + ;; + esac + ;; + esac +} + +_git_checkout () +{ + __git_has_doubledash && return + + case "$cur" in + --conflict=*) + __gitcomp "diff3 merge" "" "${cur##--conflict=}" + ;; + --*) + __gitcomp " + --quiet --ours --theirs --track --no-track --merge + --conflict= --orphan --patch + " + ;; + *) + # check if --track, --no-track, or --no-guess was specified + # if so, disable DWIM mode + local flags="--track --no-track --no-guess" track=1 + if [ -n "$(__git_find_on_cmdline "$flags")" ]; then + track='' + fi + __gitcomp_nl "$(__git_refs '' $track)" + ;; + esac +} + +_git_cherry () +{ + __gitcomp_nl "$(__git_refs)" +} + +_git_cherry_pick () +{ + local dir="$(__gitdir)" + if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __gitcomp "--continue --quit --abort" + return + fi + case "$cur" in + --*) + __gitcomp "--edit --no-commit --signoff --strategy= --mainline" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + +_git_clean () +{ + case "$cur" in + --*) + __gitcomp "--dry-run --quiet" + return + ;; + esac + + # XXX should we check for -x option ? + __git_complete_index_file "--others --directory" +} + +_git_clone () +{ + case "$cur" in + --*) + __gitcomp " + --local + --no-hardlinks + --shared + --reference + --quiet + --no-checkout + --bare + --mirror + --origin + --upload-pack + --template= + --depth + --single-branch + --branch + " + return + ;; + esac +} + +_git_commit () +{ + case "$prev" in + -c|-C) + __gitcomp_nl "$(__git_refs)" "" "${cur}" + return + ;; + esac + + case "$cur" in + --cleanup=*) + __gitcomp "default scissors strip verbatim whitespace + " "" "${cur##--cleanup=}" + return + ;; + --reuse-message=*|--reedit-message=*|\ + --fixup=*|--squash=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + return + ;; + --untracked-files=*) + __gitcomp "all no normal" "" "${cur##--untracked-files=}" + return + ;; + --*) + __gitcomp " + --all --author= --signoff --verify --no-verify + --edit --no-edit + --amend --include --only --interactive + --dry-run --reuse-message= --reedit-message= + --reset-author --file= --message= --template= + --cleanup= --untracked-files --untracked-files= + --verbose --quiet --fixup= --squash= + " + return + esac + + if git rev-parse --verify --quiet HEAD >/dev/null; then + __git_complete_index_file "--committable" + else + # This is the first commit + __git_complete_index_file "--cached" + fi +} + +_git_describe () +{ + case "$cur" in + --*) + __gitcomp " + --all --tags --contains --abbrev= --candidates= + --exact-match --debug --long --match --always + " + return + esac + __gitcomp_nl "$(__git_refs)" +} + +__git_diff_algorithms="myers minimal patience histogram" + +__git_diff_common_options="--stat --numstat --shortstat --summary + --patch-with-stat --name-only --name-status --color + --no-color --color-words --no-renames --check + --full-index --binary --abbrev --diff-filter= + --find-copies-harder + --text --ignore-space-at-eol --ignore-space-change + --ignore-all-space --ignore-blank-lines --exit-code + --quiet --ext-diff --no-ext-diff + --no-prefix --src-prefix= --dst-prefix= + --inter-hunk-context= + --patience --histogram --minimal + --raw --word-diff --word-diff-regex= + --dirstat --dirstat= --dirstat-by-file + --dirstat-by-file= --cumulative + --diff-algorithm= +" + +_git_diff () +{ + __git_has_doubledash && return + + case "$cur" in + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs --no-index + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +__git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff + tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc codecompare +" + +_git_difftool () +{ + __git_has_doubledash && return + + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs + --no-renames --diff-filter= --find-copies-harder + --relative --ignore-submodules + --tool=" + return + ;; + esac + __git_complete_revlist_file +} + +__git_fetch_recurse_submodules="yes on-demand no" + +__git_fetch_options=" + --quiet --verbose --append --upload-pack --force --keep --depth= + --tags --no-tags --all --prune --dry-run --recurse-submodules= +" + +_git_fetch () +{ + case "$cur" in + --recurse-submodules=*) + __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --*) + __gitcomp "$__git_fetch_options" + return + ;; + esac + __git_complete_remote_or_refspec +} + +__git_format_patch_options=" + --stdout --attach --no-attach --thread --thread= --no-thread + --numbered --start-number --numbered-files --keep-subject --signoff + --signature --no-signature --in-reply-to= --cc= --full-index --binary + --not --all --cover-letter --no-prefix --src-prefix= --dst-prefix= + --inline --suffix= --ignore-if-in-upstream --subject-prefix= + --output-directory --reroll-count --to= --quiet --notes +" + +_git_format_patch () +{ + case "$cur" in + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --*) + __gitcomp "$__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_fsck () +{ + case "$cur" in + --*) + __gitcomp " + --tags --root --unreachable --cache --no-reflogs --full + --strict --verbose --lost-found + " + return + ;; + esac +} + +_git_gc () +{ + case "$cur" in + --*) + __gitcomp "--prune --aggressive" + return + ;; + esac +} + +_git_gitk () +{ + _gitk +} + +__git_match_ctag() { + awk "/^${1//\//\\/}/ { print \$1 }" "$2" +} + +_git_grep () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + --cached + --text --ignore-case --word-regexp --invert-match + --full-name --line-number + --extended-regexp --basic-regexp --fixed-strings + --perl-regexp + --threads + --files-with-matches --name-only + --files-without-match + --max-depth + --count + --and --or --not --all-match + " + return + ;; + esac + + case "$cword,$prev" in + 2,*|*,-*) + if test -r tags; then + __gitcomp_nl "$(__git_match_ctag "$cur" tags)" + return + fi + ;; + esac + + __gitcomp_nl "$(__git_refs)" +} + +_git_help () +{ + case "$cur" in + --*) + __gitcomp "--all --info --man --web" + return + ;; + esac + __git_compute_all_commands + __gitcomp "$__git_all_commands $(__git_aliases) + attributes cli core-tutorial cvs-migration + diffcore gitk glossary hooks ignore modules + namespaces repository-layout tutorial tutorial-2 + workflows + " +} + +_git_init () +{ + case "$cur" in + --shared=*) + __gitcomp " + false true umask group all world everybody + " "" "${cur##--shared=}" + return + ;; + --*) + __gitcomp "--quiet --bare --template= --shared --shared=" + return + ;; + esac +} + +_git_ls_files () +{ + case "$cur" in + --*) + __gitcomp "--cached --deleted --modified --others --ignored + --stage --directory --no-empty-directory --unmerged + --killed --exclude= --exclude-from= + --exclude-per-directory= --exclude-standard + --error-unmatch --with-tree= --full-name + --abbrev --ignored --exclude-per-directory + " + return + ;; + esac + + # XXX ignore options like --modified and always suggest all cached + # files. + __git_complete_index_file "--cached" +} + +_git_ls_remote () +{ + __gitcomp_nl "$(__git_remotes)" +} + +_git_ls_tree () +{ + __git_complete_file +} + +# Options that go well for log, shortlog and gitk +__git_log_common_options=" + --not --all + --branches --tags --remotes + --first-parent --merges --no-merges + --max-count= + --max-age= --since= --after= + --min-age= --until= --before= + --min-parents= --max-parents= + --no-min-parents --no-max-parents +" +# Options that go well for log and gitk (not shortlog) +__git_log_gitk_options=" + --dense --sparse --full-history + --simplify-merges --simplify-by-decoration + --left-right --notes --no-notes +" +# Options that go well for log and shortlog (not gitk) +__git_log_shortlog_options=" + --author= --committer= --grep= + --all-match --invert-grep +" + +__git_log_pretty_formats="oneline short medium full fuller email raw format:" +__git_log_date_formats="relative iso8601 rfc2822 short local default raw" + +_git_log () +{ + __git_has_doubledash && return + + local g="$(git rev-parse --git-dir 2>/dev/null)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --date=*) + __gitcomp "$__git_log_date_formats" "" "${cur##--date=}" + return + ;; + --decorate=*) + __gitcomp "full short no" "" "${cur##--decorate=}" + return + ;; + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + $__git_log_gitk_options + --root --topo-order --date-order --reverse + --follow --full-diff + --abbrev-commit --abbrev= + --relative-date --date= + --pretty= --format= --oneline + --show-signature + --cherry-pick + --graph + --decorate --decorate= + --walk-reflogs + --parents --children + $merge + $__git_diff_common_options + --pickaxe-all --pickaxe-regex + " + return + ;; + esac + __git_complete_revlist +} + +# Common merge options shared by git-merge(1) and git-pull(1). +__git_merge_options=" + --no-commit --no-stat --log --no-log --squash --strategy + --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit + --verify-signatures --no-verify-signatures --gpg-sign + --quiet --verbose --progress --no-progress +" + +_git_merge () +{ + __git_complete_strategy && return + + case "$cur" in + --*) + __gitcomp "$__git_merge_options + --rerere-autoupdate --no-rerere-autoupdate --abort" + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_mergetool () +{ + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--tool=" + return + ;; + esac +} + +_git_merge_base () +{ + case "$cur" in + --*) + __gitcomp "--octopus --independent --is-ancestor --fork-point" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_mv () +{ + case "$cur" in + --*) + __gitcomp "--dry-run" + return + ;; + esac + + if [ $(__git_count_arguments "mv") -gt 0 ]; then + # We need to show both cached and untracked files (including + # empty directories) since this may not be the last argument. + __git_complete_index_file "--cached --others --directory" + else + __git_complete_index_file "--cached" + fi +} + +_git_name_rev () +{ + __gitcomp "--tags --all --stdin" +} + +_git_notes () +{ + local subcommands='add append copy edit list prune remove show' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + case "$subcommand,$cur" in + ,--*) + __gitcomp '--ref' + ;; + ,*) + case "$prev" in + --ref) + __gitcomp_nl "$(__git_refs)" + ;; + *) + __gitcomp "$subcommands --ref" + ;; + esac + ;; + add,--reuse-message=*|append,--reuse-message=*|\ + add,--reedit-message=*|append,--reedit-message=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + ;; + add,--*|append,--*) + __gitcomp '--file= --message= --reedit-message= + --reuse-message=' + ;; + copy,--*) + __gitcomp '--stdin' + ;; + prune,--*) + __gitcomp '--dry-run --verbose' + ;; + prune,*) + ;; + *) + case "$prev" in + -m|-F) + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac + ;; + esac +} + +_git_pull () +{ + __git_complete_strategy && return + + case "$cur" in + --recurse-submodules=*) + __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --*) + __gitcomp " + --rebase --no-rebase + $__git_merge_options + $__git_fetch_options + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +__git_push_recurse_submodules="check on-demand" + +__git_complete_force_with_lease () +{ + local cur_=$1 + + case "$cur_" in + --*=) + ;; + *:*) + __gitcomp_nl "$(__git_refs)" "" "${cur_#*:}" + ;; + *) + __gitcomp_nl "$(__git_refs)" "" "$cur_" + ;; + esac +} + +_git_push () +{ + case "$prev" in + --repo) + __gitcomp_nl "$(__git_remotes)" + return + ;; + --recurse-submodules) + __gitcomp "$__git_push_recurse_submodules" + return + ;; + esac + case "$cur" in + --repo=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}" + return + ;; + --recurse-submodules=*) + __gitcomp "$__git_push_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --force-with-lease=*) + __git_complete_force_with_lease "${cur##--force-with-lease=}" + return + ;; + --*) + __gitcomp " + --all --mirror --tags --dry-run --force --verbose + --quiet --prune --delete --follow-tags + --receive-pack= --repo= --set-upstream + --force-with-lease --force-with-lease= --recurse-submodules= + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +_git_rebase () +{ + local dir="$(__gitdir)" + if [ -f "$dir"/rebase-merge/interactive ]; then + __gitcomp "--continue --skip --abort --edit-todo" + return + elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then + __gitcomp "--continue --skip --abort" + return + fi + __git_complete_strategy && return + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --onto --merge --strategy --interactive + --preserve-merges --stat --no-stat + --committer-date-is-author-date --ignore-date + --ignore-whitespace --whitespace= + --autosquash --no-autosquash + --fork-point --no-fork-point + --autostash --no-autostash + --verify --no-verify + --keep-empty --root --force-rebase --no-ff + --exec + " + + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_reflog () +{ + local subcommands="show delete expire" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + __gitcomp_nl "$(__git_refs)" + fi +} + +__git_send_email_confirm_options="always never auto cc compose" +__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all" + +_git_send_email () +{ + case "$prev" in + --to|--cc|--bcc|--from) + __gitcomp " + $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) + " + return + ;; + esac + + case "$cur" in + --confirm=*) + __gitcomp " + $__git_send_email_confirm_options + " "" "${cur##--confirm=}" + return + ;; + --suppress-cc=*) + __gitcomp " + $__git_send_email_suppresscc_options + " "" "${cur##--suppress-cc=}" + + return + ;; + --smtp-encryption=*) + __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}" + return + ;; + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --to=*|--cc=*|--bcc=*|--from=*) + __gitcomp " + $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) + " "" "${cur#--*=}" + return + ;; + --*) + __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to + --compose --confirm= --dry-run --envelope-sender + --from --identity + --in-reply-to --no-chain-reply-to --no-signed-off-by-cc + --no-suppress-from --no-thread --quiet + --signed-off-by-cc --smtp-pass --smtp-server + --smtp-server-port --smtp-encryption= --smtp-user + --subject --suppress-cc= --suppress-from --thread --to + --validate --no-validate + $__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_stage () +{ + _git_add +} + +__git_config_get_set_variables () +{ + local prevword word config_file= c=$cword + while [ $c -gt 1 ]; do + word="${words[c]}" + case "$word" in + --system|--global|--local|--file=*) + config_file="$word" + break + ;; + -f|--file) + config_file="$word $prevword" + break + ;; + esac + prevword=$word + c=$((--c)) + done + + git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null +} + +_git_config () +{ + case "$prev" in + branch.*.remote|branch.*.pushremote) + __gitcomp_nl "$(__git_remotes)" + return + ;; + branch.*.merge) + __gitcomp_nl "$(__git_refs)" + return + ;; + branch.*.rebase) + __gitcomp "false true preserve interactive" + return + ;; + remote.pushdefault) + __gitcomp_nl "$(__git_remotes)" + return + ;; + remote.*.fetch) + local remote="${prev#remote.}" + remote="${remote%.fetch}" + if [ -z "$cur" ]; then + __gitcomp_nl "refs/heads/" "" "" "" + return + fi + __gitcomp_nl "$(__git_refs_remotes "$remote")" + return + ;; + remote.*.push) + local remote="${prev#remote.}" + remote="${remote%.push}" + __gitcomp_nl "$(git --git-dir="$(__gitdir)" \ + for-each-ref --format='%(refname):%(refname)' \ + refs/heads)" + return + ;; + pull.twohead|pull.octopus) + __git_compute_merge_strategies + __gitcomp "$__git_merge_strategies" + return + ;; + color.branch|color.diff|color.interactive|\ + color.showbranch|color.status|color.ui) + __gitcomp "always never auto" + return + ;; + color.pager) + __gitcomp "false true" + return + ;; + color.*.*) + __gitcomp " + normal black red green yellow blue magenta cyan white + bold dim ul blink reverse + " + return + ;; + diff.submodule) + __gitcomp "log short" + return + ;; + help.format) + __gitcomp "man info web html" + return + ;; + log.date) + __gitcomp "$__git_log_date_formats" + return + ;; + sendemail.aliasesfiletype) + __gitcomp "mutt mailrc pine elm gnus" + return + ;; + sendemail.confirm) + __gitcomp "$__git_send_email_confirm_options" + return + ;; + sendemail.suppresscc) + __gitcomp "$__git_send_email_suppresscc_options" + return + ;; + sendemail.transferencoding) + __gitcomp "7bit 8bit quoted-printable base64" + return + ;; + --get|--get-all|--unset|--unset-all) + __gitcomp_nl "$(__git_config_get_set_variables)" + return + ;; + *.*) + return + ;; + esac + case "$cur" in + --*) + __gitcomp " + --system --global --local --file= + --list --replace-all + --get --get-all --get-regexp + --add --unset --unset-all + --remove-section --rename-section + --name-only + " + return + ;; + branch.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_" + return + ;; + branch.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." + __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_" + return + ;; + guitool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + argprompt cmd confirm needsfile noconsole norescan + prompt revprompt revunmerged title + " "$pfx" "$cur_" + return + ;; + difftool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + man.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + mergetool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path trustExitCode" "$pfx" "$cur_" + return + ;; + pager.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __git_compute_all_commands + __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" + return + ;; + remote.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + url proxy fetch push mirror skipDefaultUpdate + receivepack uploadpack tagopt pushurl + " "$pfx" "$cur_" + return + ;; + remote.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." + __gitcomp_nl_append "pushdefault" "$pfx" "$cur_" + return + ;; + url.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_" + return + ;; + esac + __gitcomp " + add.ignoreErrors + advice.commitBeforeMerge + advice.detachedHead + advice.implicitIdentity + advice.pushNonFastForward + advice.resolveConflict + advice.statusHints + alias. + am.keepcr + apply.ignorewhitespace + apply.whitespace + branch.autosetupmerge + branch.autosetuprebase + browser. + clean.requireForce + color.branch + color.branch.current + color.branch.local + color.branch.plain + color.branch.remote + color.decorate.HEAD + color.decorate.branch + color.decorate.remoteBranch + color.decorate.stash + color.decorate.tag + color.diff + color.diff.commit + color.diff.frag + color.diff.func + color.diff.meta + color.diff.new + color.diff.old + color.diff.plain + color.diff.whitespace + color.grep + color.grep.context + color.grep.filename + color.grep.function + color.grep.linenumber + color.grep.match + color.grep.selected + color.grep.separator + color.interactive + color.interactive.error + color.interactive.header + color.interactive.help + color.interactive.prompt + color.pager + color.showbranch + color.status + color.status.added + color.status.changed + color.status.header + color.status.nobranch + color.status.unmerged + color.status.untracked + color.status.updated + color.ui + commit.status + commit.template + core.abbrev + core.askpass + core.attributesfile + core.autocrlf + core.bare + core.bigFileThreshold + core.compression + core.createObject + core.deltaBaseCacheLimit + core.editor + core.eol + core.excludesfile + core.fileMode + core.fsyncobjectfiles + core.gitProxy + core.ignoreStat + core.ignorecase + core.logAllRefUpdates + core.loosecompression + core.notesRef + core.packedGitLimit + core.packedGitWindowSize + core.pager + core.preferSymlinkRefs + core.preloadindex + core.quotepath + core.repositoryFormatVersion + core.safecrlf + core.sharedRepository + core.sparseCheckout + core.symlinks + core.trustctime + core.untrackedCache + core.warnAmbiguousRefs + core.whitespace + core.worktree + diff.autorefreshindex + diff.external + diff.ignoreSubmodules + diff.mnemonicprefix + diff.noprefix + diff.renameLimit + diff.renames + diff.statGraphWidth + diff.submodule + diff.suppressBlankEmpty + diff.tool + diff.wordRegex + diff.algorithm + difftool. + difftool.prompt + fetch.recurseSubmodules + fetch.unpackLimit + format.attach + format.cc + format.coverLetter + format.headers + format.numbered + format.pretty + format.signature + format.signoff + format.subjectprefix + format.suffix + format.thread + format.to + gc. + gc.aggressiveWindow + gc.auto + gc.autopacklimit + gc.packrefs + gc.pruneexpire + gc.reflogexpire + gc.reflogexpireunreachable + gc.rerereresolved + gc.rerereunresolved + gitcvs.allbinary + gitcvs.commitmsgannotation + gitcvs.dbTableNamePrefix + gitcvs.dbdriver + gitcvs.dbname + gitcvs.dbpass + gitcvs.dbuser + gitcvs.enabled + gitcvs.logfile + gitcvs.usecrlfattr + guitool. + gui.blamehistoryctx + gui.commitmsgwidth + gui.copyblamethreshold + gui.diffcontext + gui.encoding + gui.fastcopyblame + gui.matchtrackingbranch + gui.newbranchtemplate + gui.pruneduringfetch + gui.spellingdictionary + gui.trustmtime + help.autocorrect + help.browser + help.format + http.lowSpeedLimit + http.lowSpeedTime + http.maxRequests + http.minSessions + http.noEPSV + http.postBuffer + http.proxy + http.sslCipherList + http.sslVersion + http.sslCAInfo + http.sslCAPath + http.sslCert + http.sslCertPasswordProtected + http.sslKey + http.sslVerify + http.useragent + i18n.commitEncoding + i18n.logOutputEncoding + imap.authMethod + imap.folder + imap.host + imap.pass + imap.port + imap.preformattedHTML + imap.sslverify + imap.tunnel + imap.user + init.templatedir + instaweb.browser + instaweb.httpd + instaweb.local + instaweb.modulepath + instaweb.port + interactive.singlekey + log.date + log.decorate + log.showroot + mailmap.file + man. + man.viewer + merge. + merge.conflictstyle + merge.log + merge.renameLimit + merge.renormalize + merge.stat + merge.tool + merge.verbosity + mergetool. + mergetool.keepBackup + mergetool.keepTemporaries + mergetool.prompt + notes.displayRef + notes.rewrite. + notes.rewrite.amend + notes.rewrite.rebase + notes.rewriteMode + notes.rewriteRef + pack.compression + pack.deltaCacheLimit + pack.deltaCacheSize + pack.depth + pack.indexVersion + pack.packSizeLimit + pack.threads + pack.window + pack.windowMemory + pager. + pretty. + pull.octopus + pull.twohead + push.default + push.followTags + rebase.autosquash + rebase.stat + receive.autogc + receive.denyCurrentBranch + receive.denyDeleteCurrent + receive.denyDeletes + receive.denyNonFastForwards + receive.fsckObjects + receive.unpackLimit + receive.updateserverinfo + remote.pushdefault + remotes. + repack.usedeltabaseoffset + rerere.autoupdate + rerere.enabled + sendemail. + sendemail.aliasesfile + sendemail.aliasfiletype + sendemail.bcc + sendemail.cc + sendemail.cccmd + sendemail.chainreplyto + sendemail.confirm + sendemail.envelopesender + sendemail.from + sendemail.identity + sendemail.multiedit + sendemail.signedoffbycc + sendemail.smtpdomain + sendemail.smtpencryption + sendemail.smtppass + sendemail.smtpserver + sendemail.smtpserveroption + sendemail.smtpserverport + sendemail.smtpuser + sendemail.suppresscc + sendemail.suppressfrom + sendemail.thread + sendemail.to + sendemail.validate + showbranch.default + status.relativePaths + status.showUntrackedFiles + status.submodulesummary + submodule. + tar.umask + transfer.unpackLimit + url. + user.email + user.name + user.signingkey + web.browser + branch. remote. + " +} + +_git_remote () +{ + local subcommands="add rename remove set-head set-branches set-url show prune update" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + rename|remove|set-url|show|prune) + __gitcomp_nl "$(__git_remotes)" + ;; + set-head|set-branches) + __git_complete_remote_or_refspec + ;; + update) + __gitcomp "$(__git_get_config_variables "remotes")" + ;; + *) + ;; + esac +} + +_git_replace () +{ + __gitcomp_nl "$(__git_refs)" +} + +_git_reset () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp "--merge --mixed --hard --soft --patch" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_revert () +{ + local dir="$(__gitdir)" + if [ -f "$dir"/REVERT_HEAD ]; then + __gitcomp "--continue --quit --abort" + return + fi + case "$cur" in + --*) + __gitcomp "--edit --mainline --no-edit --no-commit --signoff" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_rm () +{ + case "$cur" in + --*) + __gitcomp "--cached --dry-run --ignore-unmatch --quiet" + return + ;; + esac + + __git_complete_index_file "--cached" +} + +_git_shortlog () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + --numbered --summary + " + return + ;; + esac + __git_complete_revlist +} + +_git_show () +{ + __git_has_doubledash && return + + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--pretty= --format= --abbrev-commit --oneline + --show-signature + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +_git_show_branch () +{ + case "$cur" in + --*) + __gitcomp " + --all --remotes --topo-order --date-order --current --more= + --list --independent --merge-base --no-name + --color --no-color + --sha1-name --sparse --topics --reflog + " + return + ;; + esac + __git_complete_revlist +} + +_git_stash () +{ + local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked' + local subcommands='save list show apply clear drop pop create branch' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + case "$cur" in + --*) + __gitcomp "$save_opts" + ;; + *) + if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then + __gitcomp "$subcommands" + fi + ;; + esac + else + case "$subcommand,$cur" in + save,--*) + __gitcomp "$save_opts" + ;; + apply,--*|pop,--*) + __gitcomp "--index --quiet" + ;; + drop,--*) + __gitcomp "--quiet" + ;; + show,--*|branch,--*) + ;; + branch,*) + if [ $cword -eq 3 ]; then + __gitcomp_nl "$(__git_refs)"; + else + __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + | sed -n -e 's/:.*//p')" + fi + ;; + show,*|apply,*|drop,*|pop,*) + __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + | sed -n -e 's/:.*//p')" + ;; + *) + ;; + esac + fi +} + +_git_submodule () +{ + __git_has_doubledash && return + + local subcommands="add status init deinit update summary foreach sync" + if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then + case "$cur" in + --*) + __gitcomp "--quiet --cached" + ;; + *) + __gitcomp "$subcommands" + ;; + esac + return + fi +} + +_git_svn () +{ + local subcommands=" + init fetch clone rebase dcommit log find-rev + set-tree commit-diff info create-ignore propget + proplist show-ignore show-externals branch tag blame + migrate mkdirs reset gc + " + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + local remote_opts="--username= --config-dir= --no-auth-cache" + local fc_opts=" + --follow-parent --authors-file= --repack= + --no-metadata --use-svm-props --use-svnsync-props + --log-window-size= --no-checkout --quiet + --repack-flags --use-log-author --localtime + --ignore-paths= --include-paths= $remote_opts + " + local init_opts=" + --template= --shared= --trunk= --tags= + --branches= --stdlayout --minimize-url + --no-metadata --use-svm-props --use-svnsync-props + --rewrite-root= --prefix= --use-log-author + --add-author-from $remote_opts + " + local cmt_opts=" + --edit --rmdir --find-copies-harder --copy-similarity= + " + + case "$subcommand,$cur" in + fetch,--*) + __gitcomp "--revision= --fetch-all $fc_opts" + ;; + clone,--*) + __gitcomp "--revision= $fc_opts $init_opts" + ;; + init,--*) + __gitcomp "$init_opts" + ;; + dcommit,--*) + __gitcomp " + --merge --strategy= --verbose --dry-run + --fetch-all --no-rebase --commit-url + --revision --interactive $cmt_opts $fc_opts + " + ;; + set-tree,--*) + __gitcomp "--stdin $cmt_opts $fc_opts" + ;; + create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\ + show-externals,--*|mkdirs,--*) + __gitcomp "--revision=" + ;; + log,--*) + __gitcomp " + --limit= --revision= --verbose --incremental + --oneline --show-commit --non-recursive + --authors-file= --color + " + ;; + rebase,--*) + __gitcomp " + --merge --verbose --strategy= --local + --fetch-all --dry-run $fc_opts + " + ;; + commit-diff,--*) + __gitcomp "--message= --file= --revision= $cmt_opts" + ;; + info,--*) + __gitcomp "--url" + ;; + branch,--*) + __gitcomp "--dry-run --message --tag" + ;; + tag,--*) + __gitcomp "--dry-run --message" + ;; + blame,--*) + __gitcomp "--git-format" + ;; + migrate,--*) + __gitcomp " + --config-dir= --ignore-paths= --minimize + --no-auth-cache --username= + " + ;; + reset,--*) + __gitcomp "--revision= --parent" + ;; + *) + ;; + esac + fi +} + +_git_tag () +{ + local i c=1 f=0 + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-v) + __gitcomp_nl "$(__git_tags)" + return + ;; + -f) + f=1 + ;; + esac + ((c++)) + done + + case "$prev" in + -m|-F) + ;; + -*|tag) + if [ $f = 1 ]; then + __gitcomp_nl "$(__git_tags)" + fi + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac + + case "$cur" in + --*) + __gitcomp " + --list --delete --verify --annotate --message --file + --sign --cleanup --local-user --force --column --sort + --contains --points-at + " + ;; + esac +} + +_git_whatchanged () +{ + _git_log +} + +__git_main () +{ + local i c=1 command __git_dir + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --git-dir=*) __git_dir="${i#--git-dir=}" ;; + --git-dir) ((c++)) ; __git_dir="${words[c]}" ;; + --bare) __git_dir="." ;; + --help) command="help"; break ;; + -c|--work-tree|--namespace) ((c++)) ;; + -*) ;; + *) command="$i"; break ;; + esac + ((c++)) + done + + if [ -z "$command" ]; then + case "$cur" in + --*) __gitcomp " + --paginate + --no-pager + --git-dir= + --bare + --version + --exec-path + --exec-path= + --html-path + --man-path + --info-path + --work-tree= + --namespace= + --no-replace-objects + --help + " + ;; + *) __git_compute_porcelain_commands + __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;; + esac + return + fi + + local completion_func="_git_${command//-/_}" + declare -f $completion_func >/dev/null && $completion_func && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + words[1]=$expansion + completion_func="_git_${expansion//-/_}" + declare -f $completion_func >/dev/null && $completion_func + fi +} + +__gitk_main () +{ + __git_has_doubledash && return + + local g="$(__gitdir)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_gitk_options + $merge + " + return + ;; + esac + __git_complete_revlist +} + +if [[ -n ${ZSH_VERSION-} ]]; then + echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2 + + autoload -U +X compinit && compinit + + __gitcomp () + { + emulate -L zsh + + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c IFS=$' \t\n' + local -a array + for c in ${=1}; do + c="$c${4-}" + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + array[${#array[@]}+1]="$c" + done + compset -P '*[=:]' + compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 + ;; + esac + } + + __gitcomp_nl () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 + } + + __gitcomp_file () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 + } + + _git () + { + local _ret=1 cur cword prev + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + emulate ksh -c __${service}_main + let _ret && _default && _ret=0 + return _ret + } + + compdef _git git gitk + return +fi + +__git_func_wrap () +{ + local cur words cword prev + _get_comp_words_by_ref -n =: cur words cword prev + $1 +} + +# Setup completion for certain functions defined above by setting common +# variables and workarounds. +# This is NOT a public function; use at your own risk. +__git_complete () +{ + local wrapper="__git_wrap${2}" + eval "$wrapper () { __git_func_wrap $2 ; }" + complete -o bashdefault -o default -o nospace -F $wrapper $1 2>/dev/null \ + || complete -o default -o nospace -F $wrapper $1 +} + +# wrapper for backwards compatibility +_git () +{ + __git_wrap__git_main +} + +# wrapper for backwards compatibility +_gitk () +{ + __git_wrap__gitk_main +} + +__git_complete git __git_main +__git_complete gitk __gitk_main + +# The following are necessary only for Cygwin, and only are needed +# when the user has tab-completed the executable name and consequently +# included the '.exe' suffix. +# +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then +__git_complete git.exe __git_main +fi diff --git a/completion/git_flow.completion.sh b/completion/git_flow.completion.sh new file mode 100644 index 0000000..c76d323 --- /dev/null +++ b/completion/git_flow.completion.sh @@ -0,0 +1,177 @@ +#!bash +# +# git-flow-completion +# =================== +# +# Bash completion support for [git-flow](http://github.com/nvie/gitflow) +# +# The contained completion routines provide support for completing: +# +# * git-flow init and version +# * feature, hotfix and release branches +# * remote feature branch names (for `git-flow feature track`) +# +# +# Installation +# ------------ +# +# To achieve git-flow completion nirvana: +# +# 0. Install git-completion. +# +# 1. Install this file. Either: +# +# a. Place it in a `bash-completion.d` folder: +# +# * /etc/bash-completion.d +# * /usr/local/etc/bash-completion.d +# * ~/bash-completion.d +# +# b. Or, copy it somewhere (e.g. ~/.git-flow-completion.sh) and put the following line in +# your .bashrc: +# +# source ~/.git-flow-completion.sh +# +# 2. If you are using Git < 1.7.1: Edit git-completion.sh and add the following line to the giant +# $command case in _git: +# +# flow) _git_flow ;; +# +# +# The Fine Print +# -------------- +# +# Copyright (c) 2010 [Justin Hileman](http://justinhileman.com) +# +# Distributed under the [MIT License](http://creativecommons.org/licenses/MIT/) + +_git_flow () +{ + local subcommands="init feature release hotfix" + local subcommand="$(__git_find_subcommand "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + feature) + __git_flow_feature + return + ;; + release) + __git_flow_release + return + ;; + hotfix) + __git_flow_hotfix + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_feature () +{ + local subcommands="list start finish publish track diff rebase checkout pull" + local subcommand="$(__git_find_subcommand "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + pull) + __gitcomp "$(__git_remotes)" + return + ;; + checkout|finish|diff|rebase) + __gitcomp "$(__git_flow_list_features)" + return + ;; + publish) + __gitcomp "$(comm -23 <(__git_flow_list_features) <(__git_flow_list_remote_features))" + return + ;; + track) + __gitcomp "$(__git_flow_list_remote_features)" + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_list_features () +{ + git flow feature list 2> /dev/null | tr -d ' |*' +} + +__git_flow_list_remote_features () +{ + git branch -r 2> /dev/null | grep "origin/$(__git_flow_feature_prefix)" | awk '{ sub(/^origin\/$(__git_flow_feature_prefix)/, "", $1); print }' +} + +__git_flow_feature_prefix () +{ + git config gitflow.prefix.feature 2> /dev/null || echo "feature/" +} + +__git_flow_release () +{ + local subcommands="list start finish" + local subcommand="$(__git_find_subcommand "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + finish) + __gitcomp "$(__git_flow_list_releases)" + return + ;; + *) + COMPREPLY=() + ;; + esac + +} + +__git_flow_list_releases () +{ + git flow release list 2> /dev/null +} + +__git_flow_hotfix () +{ + local subcommands="list start finish" + local subcommand="$(__git_find_subcommand "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + finish) + __gitcomp "$(__git_flow_list_hotfixes)" + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_list_hotfixes () +{ + git flow hotfix list 2> /dev/null +} + +# temporarily wrap __git_find_on_cmdline() for backwards compatibility +if [ -z "`type -t __git_find_subcommand`" ]; then + alias __git_find_subcommand=__git_find_on_cmdline +fi \ No newline at end of file diff --git a/completion/git_flow_avh.completion.sh b/completion/git_flow_avh.completion.sh new file mode 100644 index 0000000..0b73a0b --- /dev/null +++ b/completion/git_flow_avh.completion.sh @@ -0,0 +1,510 @@ +#!bash +# +# git-flow-completion +# =================== +# +# Bash completion support for [git-flow (AVH Edition)](http://github.com/petervanderdoes/gitflow) +# +# The contained completion routines provide support for completing: +# +# * git-flow init and version +# * feature, hotfix and release branches +# * remote feature, hotfix and release branch names +# +# +# Installation +# ------------ +# +# To achieve git-flow completion nirvana: +# +# 0. Install git-completion. +# +# 1. Install this file. Either: +# +# a. Place it in a `bash-completion.d` folder: +# +# * /etc/bash-completion.d +# * /usr/local/etc/bash-completion.d +# * ~/bash-completion.d +# +# b. Or, copy it somewhere (e.g. ~/.git-flow-completion.sh) and put the following line in +# your .bashrc: +# +# source ~/.git-flow-completion.sh +# +# 2. If you are using Git < 1.7.1: Edit git-completion.sh and add the following line to the giant +# $command case in _git: +# +# flow) _git_flow ;; +# +# +# The Fine Print +# -------------- +# +# Author: +# Copyright 2012-2013 Peter van der Does. +# +# Original Author: +# Copyright (c) 2011 [Justin Hileman](http://justinhileman.com) +# +# Distributed under the [MIT License](http://creativecommons.org/licenses/MIT/) + +__git_flow_config_file_options=" + --local --global --system --file= + " + +_git_flow () +{ + local subcommands="init feature release hotfix support help version config finish delete publish rebase" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + init) + __git_flow_init + return + ;; + feature) + __git_flow_feature + return + ;; + release) + __git_flow_release + return + ;; + hotfix) + __git_flow_hotfix + return + ;; + support) + __git_flow_support + return + ;; + config) + __git_flow_config + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_init () +{ + local subcommands="help" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + fi + + case "$cur" in + --*) + __gitcomp " + --nodefaults --defaults + --noforce --force + $__git_flow_config_file_options + " + return + ;; + esac +} + +__git_flow_feature () +{ + local subcommands="list start finish publish track diff rebase checkout pull help delete" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + pull) + __gitcomp_nl "$(__git_remotes)" + return + ;; + checkout) + __gitcomp_nl "$(__git_flow_list_local_branches 'feature')" + return + ;; + delete) + case "$cur" in + --*) + __gitcomp " + --noforce --force + --noremote --remote + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'feature')" + return + ;; + finish) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + --norebase --rebase + --nopreserve-merges --preserve-merges + --nokeep --keep + --keepremote + --keeplocal + --noforce_delete --force_delete + --nosquash --squash + --no-ff + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'feature')" + return + ;; + diff) + __gitcomp_nl "$(__git_flow_list_local_branches 'feature')" + return + ;; + rebase) + case "$cur" in + --*) + __gitcomp " + --nointeractive --interactive + --nopreserve-merges --preserve-merges + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'feature')" + return + ;; + publish) + __gitcomp_nl "$(__git_flow_list_branches 'feature')" + return + ;; + track) + __gitcomp_nl "$(__git_flow_list_branches 'feature')" + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_release () +{ + local subcommands="list start finish track publish help delete" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + finish) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + --sign + --signingkey + --message + --nomessagefile --messagefile= + --nopush --push + --nokeep --keep + --keepremote + --keeplocal + --noforce_delete --force_delete + --notag --tag + --nonobackmerge --nobackmerge + --nosquash --squash + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'release')" + return + ;; + rebase) + case "$cur" in + --*) + __gitcomp " + --nointeractive --interactive + --nopreserve-merges --preserve-merges + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'release')" + return + ;; + delete) + case "$cur" in + --*) + __gitcomp " + --noforce --force + --noremote --remote + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'release')" + return + ;; + publish) + __gitcomp_nl "$(__git_flow_list_branches 'release')" + return + ;; + track) + __gitcomp_nl "$(__git_flow_list_branches 'release')" + return + ;; + start) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + " + return + ;; + esac + return + ;; + *) + COMPREPLY=() + ;; + esac + +} + +__git_flow_hotfix () +{ + local subcommands="list start finish track publish help delete" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + finish) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + --sign + --signingkey + --message + --nomessagefile --messagefile= + --nopush --push + --nokeep --keep + --keepremote + --keeplocal + --noforce_delete --force_delete + --notag --tag + --nonobackmerge --nobackmerge + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'hotfix')" + return + ;; + rebase) + case "$cur" in + --*) + __gitcomp " + --nointeractive --interactive + --nopreserve-merges --preserve-merges + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'hotfix')" + return + ;; + delete) + case "$cur" in + --*) + __gitcomp " + --noforce --force + --noremote --remote + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'hotfix')" + return + ;; + publish) + __gitcomp_nl "$(__git_flow_list_branches 'hotfix')" + return + ;; + track) + __gitcomp_nl "$(__git_flow_list_branches 'hotfix')" + return + ;; + start) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + " + return + ;; + esac + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_support () +{ + local subcommands="list start help" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + start) + case "$cur" in + --*) + __gitcomp " + --nofetch --fetch + " + return + ;; + esac + return + ;; + rebase) + case "$cur" in + --*) + __gitcomp " + --nointeractive --interactive + --nopreserve-merges --preserve-merges + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches 'support')" + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_config () +{ + local subcommands="list set base" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + set) + case "$cur" in + --*) + __gitcomp " + $__git_flow_config_file_options + " + return + ;; + esac + __gitcomp " + master develop + feature hotfix release support + versiontagprefix + " + return + ;; + base) + case "$cur" in + --*) + __gitcomp " + set get + " + return + ;; + esac + __gitcomp_nl "$(__git_flow_list_local_branches)" + return + ;; + *) + COMPREPLY=() + ;; + esac +} + +__git_flow_prefix () +{ + case "$1" in + feature|release|hotfix|support) + git config "gitflow.prefix.$1" 2> /dev/null || echo "$1/" + return + ;; + esac +} + +__git_flow_list_local_branches () +{ + if [ -n "$1" ]; then + local prefix="$(__git_flow_prefix $1)" + git for-each-ref --shell --format="ref=%(refname:short)" refs/heads/$prefix | \ + while read -r entry; do + eval "$entry" + ref="${ref#$prefix}" + echo "$ref" + done | sort + else + git for-each-ref --format="ref=%(refname:short)" refs/heads/ | sort + + fi +} + +__git_flow_list_remote_branches () +{ + local prefix="$(__git_flow_prefix $1)" + local origin="$(git config gitflow.origin 2> /dev/null || echo "origin")" + git for-each-ref --shell --format='%(refname:short)' refs/remotes/$origin/$prefix | \ + while read -r entry; do + eval "$entry" + ref="${ref##$prefix}" + echo "$ref" + done | sort +} + +__git_flow_list_branches () +{ + local origin="$(git config gitflow.origin 2> /dev/null || echo "origin")" + if [ -n "$1" ]; then + local prefix="$(__git_flow_prefix $1)" + git for-each-ref --shell --format="ref=%(refname:short)" refs/heads/$prefix refs/remotes/$origin/$prefix | \ + while read -r entry; do + eval "$entry" + ref="${ref##$prefix}" + echo "$ref" + done | sort + else + git for-each-ref --format="%(refname:short)" refs/heads/ refs/remotes/$origin | sort + fi +} + +# alias __git_find_on_cmdline for backwards compatibility +if [ -z "`type -t __git_find_on_cmdline`" ]; then + alias __git_find_on_cmdline=__git_find_subcommand +fi diff --git a/completion/go.completion.sh b/completion/go.completion.sh new file mode 100644 index 0000000..e922cb5 --- /dev/null +++ b/completion/go.completion.sh @@ -0,0 +1,281 @@ +#!/usr/bin/env bash + +# bash completion for go tool +# https://github.com/thomasf/go-bash-completion + +# install in /etc/bash_completion.d/ or your personal directory + +complete -f -X '!*.8' 8l +complete -f -X '!*.6' 6l +complete -f -X '!*.5' 5l +complete -f -X '!*.go' 8g 6g 5g gofmt gccgo + +_go_clear_cache() { + unset _go_imports +} +_go_importpath_cache() { + if [ -z "$_go_imports" ]; then + _go_imports=$(go list all 2>/dev/null) + export _go_imports + fi +} + +_go_importpath() +{ + echo "$(compgen -W "$_go_imports" -- "$1")" +} + +_go() +{ + # TODO: Only allow flags before other arguments. run already does + # this. + + local cur=`_get_cword` + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + local cmd="${COMP_WORDS[1]}" + + local cmds="build clean doc env fix fmt get + install list run test tool version vet" + local addhelp="gopath importpath remote + testflag testfunc" + local other="help" + local env_vars="GOARCH GOBIN GOEXE GOHOSTARCH GOHOSTOS GOOS GOPATH GORACE + GOROOT GOTOOLDIR GO15VENDOREXPERIMENT CC GOGCCFLAGS CXX CGO_ENABLED" + + if [ "$COMP_CWORD" == 1 ]; then + for opt in $cmds; do + if [[ "$opt" == "$cmd" ]]; then + COMPREPLY=("$opt") + return + fi + done + fi + + case "$cmd" in + 'build') + case "$prev" in + '-o') + _filedir + ;; + '-p') + ;; + *) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-a -n -o -p -v -x" -- "$cur")) + else + local found=0 + for ((i=0; i < ${#COMP_WORDS[@]}; i++)); do + case "$i" in + 0|1|"$COMP_CWORD") + continue + ;; + esac + local opt="${COMP_WORDS[i]}" + if [[ "$opt" != -* ]]; then + if [[ "$opt" == *.go && -f "$opt" ]]; then + found=1 + break + else + found=2 + break + fi + fi + done + case "$found" in + 0) + _filedir go + _go_importpath_cache + COMPREPLY+=(`_go_importpath "$cur"`) + ;; + 1) + _filedir go + ;; + 2) + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + ;; + esac + fi + ;; + esac + ;; + 'clean') + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-i -r -n -x" -- "$cur")) + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + 'doc') + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + ;; + 'env') + COMPREPLY=($(compgen -W "$env_vars" -- "$cur")) + ;; + 'fix') + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + ;; + 'fmt') + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + ;; + 'get') + case "$prev" in + '-p') + ;; + *) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-a -d -fix -n -p -u -v -x" -- "$cur")) + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + esac + ;; + 'install') + case "$prev" in + '-p') + ;; + *) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-a -n -p -v -x" -- "$cur")) + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + esac + ;; + 'list') + case "$prev" in + '-f') + ;; + *) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-e -f -json" -- "$cur")) + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + esac + ;; + 'run') + if [[ "$cur" == -* && "$prev" != *.go ]]; then + COMPREPLY=($(compgen -W "-a -n -x" -- "$cur")) + else + _filedir + fi + ;; + 'test') # TODO: Support for testflags. + case "$prev" in + '-file') + _filedir go + ;; + '-p') + ;; + *) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-c -file -i -p -x" -- "$cur")) + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + esac + ;; + 'tool') + if [ "$COMP_CWORD" == 2 ]; then + COMPREPLY=($(compgen -W "$(go tool)" -- "$cur")) + else + case "${COMP_WORDS[2]}" in + [568]a) # TODO: Implement something. + #_go_tool_568a + ;; + [568]c) # TODO: Implement something. + #_go_tool_568c + ;; + [568]g) # TODO: Implement something. + #_go_tool_568g + ;; + [568]l) # TODO: Implement something. + #_go_tool_568l + ;; + 'api') # TODO: Implement something. + #_go_tool_api + ;; + 'cgo') # TODO: Implement something. + #_go_tool_cgo + ;; + 'cov') # TODO: Implement something. + #_go_tool_cov + ;; + 'dist') # TODO: Implement something. + #_go_tool_dist + ;; + 'ebnflint') # TODO: Implement something. + #_go_tool_ebnflint + ;; + 'fix') # TODO: Implement something. + #_go_tool_fix + ;; + 'gotype') # TODO: Implement something. + #_go_tool_gotype + ;; + 'nm') # TODO: Implement something. + #_go_tool_nm + ;; + 'pack') # TODO: Implement something. + #_go_tool_pack + ;; + 'pprof') # TODO: Implement something. + #_go_tool_pprof + ;; + 'prof') # TODO: Implement something. + #_go_tool_prof + ;; + 'vet') # TODO: Implement something. + #_go_tool_vet + ;; + 'yacc') # TODO: Implement something. + #_go_tool_yacc + ;; + esac + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "${COMPREPLY[*]} -h" -- "$cur")) + fi + fi + ;; + 'version') + ;; + 'vet') + if [[ "$cur" == -* ]]; then + : + else + _go_importpath_cache + COMPREPLY=(`_go_importpath "$cur"`) + fi + ;; + 'help') + if [ "$COMP_CWORD" == 2 ]; then + COMPREPLY=($(compgen -W "$cmds $addhelp" -- "$cur")) + fi + ;; + *) + if [ "$COMP_CWORD" == 1 ]; then + COMPREPLY=($(compgen -W "$cmds $other" -- "$cur")) + else + _filedir + fi + ;; + esac +} + +complete $filenames -F _go go + +# vim:ts=2 sw=2 et syn=sh diff --git a/completion/gradle.completion.sh b/completion/gradle.completion.sh new file mode 100644 index 0000000..2f55cad --- /dev/null +++ b/completion/gradle.completion.sh @@ -0,0 +1,50 @@ +function __gradle { + local cur=${COMP_WORDS[COMP_CWORD]} + local tasks='' + local cache_dir="$HOME/.gradle/completion_cache" + + case $OSTYPE in + darwin*) + local checksum_command="find . -name build.gradle -print0 | xargs -0 md5 -q | md5 -q" + ;; + *) + local checksum_command="find . -name build.gradle -print0 | xargs -0 md5sum | md5sum | cut -d ' ' -f 1" + ;; + esac + local parsing_command="gradle --console=plain --quiet tasks | grep -v Rules | sed -nE -e 's/^([a-zA-Z]+)($| - .+)/\1/p'" + + mkdir -p "${cache_dir}" + + local gradle_files_checksum='no_cache_file' + if [[ -f build.gradle ]]; then + gradle_files_checksum="$(eval "${checksum_command}")" + if [[ -f "${cache_dir}/${gradle_files_checksum}" ]]; then + newest_gradle_file="$(find . -type f -name build.gradle -newer "${cache_dir}/${gradle_files_checksum}")" + if [ -n "${newest_gradle_file}" ]; then + tasks="$(eval "${parsing_command}")" + [[ -n "${tasks}" ]] && echo "${tasks}" > "${cache_dir}/${gradle_files_checksum}" + else + tasks="$(cat "${cache_dir}/${gradle_files_checksum}")" + touch "${cache_dir}/${gradle_files_checksum}" + fi + else + tasks="$(eval "${parsing_command}")" + [[ -n "${tasks}" ]] && echo "${tasks}" > "${cache_dir}/${gradle_files_checksum}" + fi + else + tasks="$(eval "${parsing_command}")" + [[ -n "${tasks}" ]] && echo "${tasks}" > "${cache_dir}/${gradle_files_checksum}" + fi + COMPREPLY=( $(compgen -W "${tasks}" -- "${cur}") ) +} + +function __clear_gradle_cache { + local cache_dir="$HOME/.gradle/completion_cache" + [[ -d "${cache_dir}" ]] && find "${cache_dir}" -type f -mtime +7 -exec rm -f {} \; +} + +__clear_gradle_cache + +complete -F __gradle gradle +complete -F __gradle gradlew +complete -F __gradle ./gradlew diff --git a/completion/grunt.completion.sh b/completion/grunt.completion.sh new file mode 100644 index 0000000..99a96b5 --- /dev/null +++ b/completion/grunt.completion.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# grunt-cli +# http://gruntjs.com/ +# +# Copyright (c) 2012 Tyler Kellen, contributors +# Licensed under the MIT license. +# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + +# Usage: +# +# To enable bash completion for grunt, add the following line (minus the +# leading #, which is the bash comment character) to your ~/.bashrc file: +# +# eval "$(grunt --completion=bash)" + +# Search the current directory and all parent directories for a gruntfile. +function _grunt_gruntfile() { + local curpath="$PWD" + while [[ "$curpath" ]]; do + for gruntfile in "$curpath/"{G,g}runtfile.{js,coffee}; do + if [[ -e "$gruntfile" ]]; then + echo "$gruntfile" + return + fi + done + curpath="${curpath%/*}" + done + return 1 +} + +# Enable bash autocompletion. +function _grunt_completions() { + # The currently-being-completed word. + local cur="${COMP_WORDS[COMP_CWORD]}" + # The current gruntfile, if it exists. + local gruntfile="$(_grunt_gruntfile)" + # The current grunt version, available tasks, options, etc. + local gruntinfo="$(grunt --version --verbose 2>/dev/null)" + # Options and tasks. + local opts="$(echo "$gruntinfo" | awk '/Available options: / {$1=$2=""; print $0}')" + local compls="$(echo "$gruntinfo" | awk '/Available tasks: / {$1=$2=""; print $0}')" + # Only add -- or - options if the user has started typing - + [[ "$cur" == -* ]] && compls="$compls $opts" + # Tell complete what stuff to show. + COMPREPLY=($(compgen -W "$compls" -- "$cur")) +} + +complete -o default -F _grunt_completions grunt diff --git a/completion/gulp.completion.sh b/completion/gulp.completion.sh new file mode 100644 index 0000000..17e9176 --- /dev/null +++ b/completion/gulp.completion.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Borrowed from grunt-cli +# http://gruntjs.com/ +# +# Copyright (c) 2012 Tyler Kellen, contributors +# Licensed under the MIT license. +# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT +# Usage: +# +# To enable bash completion for gulp, add the following line (minus the +# leading #, which is the bash comment character) to your ~/.bashrc file: +# +# eval "$(gulp --completion=bash)" +# Enable bash autocompletion. +function _gulp_completions() { +# The currently-being-completed word. +local cur="${COMP_WORDS[COMP_CWORD]}" +#Grab tasks +local compls=$(gulp --tasks-simple) +# Tell complete what stuff to show. +COMPREPLY=($(compgen -W "$compls" -- "$cur")) +} +complete -o default -F _gulp_completions gulp diff --git a/completion/homesick.completion.sh b/completion/homesick.completion.sh new file mode 100644 index 0000000..d0ebbba --- /dev/null +++ b/completion/homesick.completion.sh @@ -0,0 +1,60 @@ +# Bash completion script for homesick +# +# The homebrew bash completion script was used as inspiration. +# Originally from https://github.com/liborw/homesick-completion + +_homesick_complete() +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + local options="--skip --force --pretend --quiet" + local actions="cd clone commit destroy diff generate help list open pull push rc show_path status symlink track unlink version" + local repos=$(\ls ~/.homesick/repos) + + # Subcommand list + [[ ${COMP_CWORD} -eq 1 ]] && { + COMPREPLY=( $(compgen -W "${options} ${actions}" -- ${cur}) ) + return + } + + # Find the first non-switch word + local prev_index=1 + local prev="${COMP_WORDS[prev_index]}" + while [[ $prev == -* ]]; do + prev_index=$((++prev_index)) + prev="${COMP_WORDS[prev_index]}" + done + + # Find the number of non-"--" commands + local num=0 + for word in ${COMP_WORDS[@]} + do + if [[ $word != -* ]]; then + num=$((++num)) + fi + done + + case "$prev" in + # Commands that take a castle + cd|commit|destroy|diff|open|pull|push|rc|show_path|status|symlink|unlink) + COMPREPLY=( $(compgen -W "${repos}" -- ${cur}) ) + return + ;; + # Commands that take command + help) + COMPREPLY=( $(compgen -W "${actions}" -- ${cur}) ) + return + ;; + # Track command take file and repo + track) + if [[ "$num" -eq 2 ]]; then + COMPREPLY=( $(compgen -X -f ${cur}) ) + elif [[ "$num" -ge 3 ]]; then + COMPREPLY=( $(compgen -W "${repos}" -- ${cur}) ) + fi + return + ;; + esac +} + +complete -o bashdefault -o default -F _homesick_complete homesick + diff --git a/completion/hub.completion.sh b/completion/hub.completion.sh new file mode 100644 index 0000000..bd84d32 --- /dev/null +++ b/completion/hub.completion.sh @@ -0,0 +1,367 @@ +# hub tab-completion script for bash. +# This script complements the completion script that ships with git. + +# If there is no git tab completion, but we have the _completion loader try to load it +if ! declare -F _git > /dev/null && declare -F _completion_loader > /dev/null; then + _completion_loader git +fi + +# Check that git tab completion is available +if declare -F _git > /dev/null; then + # Duplicate and rename the 'list_all_commands' function + eval "$(declare -f __git_list_all_commands | \ + sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')" + + # Wrap the 'list_all_commands' function with extra hub commands + __git_list_all_commands() { + cat <<-EOF +alias +pull-request +fork +create +browse +compare +ci-status +EOF + __git_list_all_commands_without_hub + } + + # Ensure cached commands are cleared + __git_all_commands="" + + ########################## + # hub command completions + ########################## + + # hub alias [-s] [SHELL] + _git_alias() { + local i c=2 s=-s sh shells="bash zsh sh ksh csh fish" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -s) + unset s + ;; + *) + for sh in $shells; do + if [ "$sh" = "$i" ]; then + unset shells + break + fi + done + ;; + esac + ((c++)) + done + __gitcomp "$s $shells" + } + + # hub browse [-u] [--|[USER/]REPOSITORY] [SUBPAGE] + _git_browse() { + local i c=2 u=-u repo subpage + local subpages_="commits issues tree wiki pulls branches stargazers + contributors network network/ graphs graphs/" + local subpages_network="members" + local subpages_graphs="commit-activity code-frequency punch-card" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -u) + unset u + ;; + *) + if [ -z "$repo" ]; then + repo=$i + else + subpage=$i + fi + ;; + esac + ((c++)) + done + if [ -z "$repo" ]; then + __gitcomp "$u -- $(__hub_github_repos '\p')" + elif [ -z "$subpage" ]; then + case "$cur" in + */*) + local pfx="${cur%/*}" cur_="${cur#*/}" + local subpages_var="subpages_$pfx" + __gitcomp "${!subpages_var}" "$pfx/" "$cur_" + ;; + *) + __gitcomp "$u ${subpages_}" + ;; + esac + else + __gitcomp "$u" + fi + } + + # hub compare [-u] [USER[/REPOSITORY]] [[START...]END] + _git_compare() { + local i c=$((cword - 1)) u=-u user remote owner repo arg_repo rev + while [ $c -gt 1 ]; do + i="${words[c]}" + case "$i" in + -u) + unset u + ;; + *) + if [ -z "$rev" ]; then + # Even though the logic below is able to complete both user/repo + # and revision in the right place, when there is only one argument + # (other than -u) in the command, that argument will be taken as + # revision. For example: + # $ hub compare -u upstream + # > https://github.com/USER/REPO/compare/upstream + if __hub_github_repos '\p' | grep -Eqx "^$i(/[^/]+)?"; then + arg_repo=$i + else + rev=$i + fi + elif [ -z "$arg_repo" ]; then + arg_repo=$i + fi + ;; + esac + ((c--)) + done + + # Here we want to find out the git remote name of user/repo, in order to + # generate an appropriate revision list + if [ -z "$arg_repo" ]; then + user=$(__hub_github_user) + if [ -z "$user" ]; then + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + if [ "$remote" = origin ]; then + break + fi + done + else + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + owner=${repo%%/*} + if [ "$user" = "$owner" ]; then + break + fi + done + fi + else + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + owner=${repo%%/*} + case "$arg_repo" in + "$repo"|"$owner") + break + ;; + esac + done + fi + + local pfx cur_="$cur" + case "$cur_" in + *..*) + pfx="${cur_%%..*}..." + cur_="${cur_##*..}" + __gitcomp_nl "$(__hub_revlist $remote)" "$pfx" "$cur_" + ;; + *) + if [ -z "${arg_repo}${rev}" ]; then + __gitcomp "$u $(__hub_github_repos '\o\n\p') $(__hub_revlist $remote)" + elif [ -z "$rev" ]; then + __gitcomp "$u $(__hub_revlist $remote)" + else + __gitcomp "$u" + fi + ;; + esac + } + + # hub create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE] + _git_create() { + local i c=2 name repo flags="-p -d -h" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-h) + ((c++)) + flags=${flags/$i/} + ;; + -p) + flags=${flags/$i/} + ;; + *) + name=$i + ;; + esac + ((c++)) + done + if [ -z "$name" ]; then + repo=$(basename "$(pwd)") + fi + case "$prev" in + -d|-h) + COMPREPLY=() + ;; + -p|*) + __gitcomp "$repo $flags" + ;; + esac + } + + # hub fork [--no-remote] + _git_fork() { + local i c=2 remote=yes + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --no-remote) + unset remote + ;; + esac + ((c++)) + done + if [ -n "$remote" ]; then + __gitcomp "--no-remote" + fi + } + + # hub pull-request [-f] [-m |-F |-i |] [-b ] [-h ] [-a ] [-M ] [-l ] + _git_pull_request() { + local i c=2 flags="-f -m -F -i -b -h -a -M -l" + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -m|-F|-i|-b|-h|-a|-M|-l) + ((c++)) + flags=${flags/$i/} + ;; + -f) + flags=${flags/$i/} + ;; + esac + ((c++)) + done + case "$prev" in + -i) + COMPREPLY=() + ;; + -b|-h|-a|-M|-l) + # (Doesn't seem to need this...) + # Uncomment the following line when 'owner/repo:[TAB]' misbehaved + #_get_comp_words_by_ref -n : cur + __gitcomp_nl "$(__hub_heads)" + # __ltrim_colon_completions "$cur" + ;; + -F) + COMPREPLY=( "$cur"* ) + ;; + -f|*) + __gitcomp "$flags" + ;; + esac + } + + ################### + # Helper functions + ################### + + # __hub_github_user [HOST] + # Return $GITHUB_USER or the default github user defined in hub config + # HOST - Host to be looked-up in hub config. Default is "github.com" + __hub_github_user() { + if [ -n "$GITHUB_USER" ]; then + echo $GITHUB_USER + return + fi + local line h k v host=${1:-github.com} config=${HUB_CONFIG:-~/.config/hub} + if [ -f "$config" ]; then + while read line; do + if [ "$line" = "---" ]; then + continue + fi + k=${line%%:*} + v=${line#*:} + if [ -z "$v" ]; then + if [ "$h" = "$host" ]; then + break + fi + h=$k + continue + fi + k=${k#* } + v=${v#* } + if [ "$h" = "$host" ] && [ "$k" = "user" ]; then + echo "$v" + break + fi + done < "$config" + fi + } + + # __hub_github_repos [FORMAT] + # List all github hosted repository + # FORMAT - Format string contains multiple of these: + # \m remote + # \p owner/repo + # \o owner + # escaped characters (\n, \t ...etc) work + # If omitted, prints all github repos in the format of "remote:owner/repo" + __hub_github_repos() { + local f format=$1 + if [ -z "$(__gitdir)" ]; then + return + fi + if [ -z "$format" ]; then + format='\1:\2' + else + format=${format//\m/\1} + format=${format//\p/\2} + format=${format//\o/\3} + fi + command git config --get-regexp 'remote\.[^.]*\.url' | + grep -E ' ((https?|git)://|git@)github\.com[:/][^:/]+/[^/]+$' | + sed -E 's#^remote\.([^.]+)\.url +.+[:/](([^/]+)/[^.]+)(\.git)?$#'"$format"'#' + } + + # __hub_heads + # List all local "branch", and remote "owner/repo:branch" + __hub_heads() { + local i remote repo branch dir=$(__gitdir) + if [ -d "$dir" ]; then + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/heads/" + for i in $(__hub_github_repos); do + remote=${i%%:*} + repo=${i#*:} + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/remotes/${remote}/" | while read branch; do + echo "${repo}:${branch#${remote}/}" + done + done + fi + } + + # __hub_revlist [REMOTE] + # List all tags, and branches under REMOTE, without the "remote/" prefix + # REMOTE - Remote name to search branches from. Default is "origin" + __hub_revlist() { + local i remote=${1:-origin} dir=$(__gitdir) + if [ -d "$dir" ]; then + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/remotes/${remote}/" | while read i; do + echo "${i#${remote}/}" + done + command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + "refs/tags/" + fi + } + + # Enable completion for hub even when not using the alias + complete -o bashdefault -o default -o nospace -F _git hub 2>/dev/null \ + || complete -o default -o nospace -F _git hub +fi diff --git a/completion/jboss7.completion.sh b/completion/jboss7.completion.sh new file mode 100644 index 0000000..66d0717 --- /dev/null +++ b/completion/jboss7.completion.sh @@ -0,0 +1,141 @@ +# Completions for JBoss Application Server 7 (EAP 6) +# VERSION: 0.6 +# DATE: 2012-10-30 +# rparree-at-edc4it-dot-com + + + + +_serverProfiles(){ + if [[ $COMP_WORDS == *standalone.sh* ]] + then + serverdir="../standalone/configuration/" + else + # assume is domain.sh + serverdir="../domain/configuration/" + fi + + for i in ${!COMP_WORDS[*]} + do + if [[ "${COMP_WORDS[i]}" == "-Djboss.server.base.dir" || "${COMP_WORDS[i]}" == "-Djboss.domain.base.dir" ]]; then + serverdir="${COMP_WORDS[i+2]}/configuration" + fi + + done + if [ -d "${serverdir}" ] + then + + IFS=$'\n' tmp="$(ls "${serverdir}" | grep xml)" + local fls="${tmp[@]// /\ }" + unset IFS + COMPREPLY=( $(compgen -W "${fls} initial boot last v" -- "$cur" )) + fi +} + +_bindingAddress(){ + # from /etc/bash_completion.d/ssh + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \ + "0.0.0.0 $( PATH="$PATH:/sbin" ifconfig -a | \ + sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' \ + -ne 's/.*inet[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p' )" \ + -- "$cur" ) ) +} + +_jboss(){ + + local cur prev words cword + COMPREPLY=() + _get_comp_words_by_ref -n = cur prev words cword + + case $cur in + + -Djboss.socket.binding.port-offset=*) + cur=${cur#*=} + #static list of common bindings sets + local bindings="100 200 300 400 10000 20000 30000 40000" + COMPREPLY=( $(compgen -W "${bindings}" -- ${cur}) ) + return 0 + ;; + -Djboss.default.jgroups.stack=*) + cur=${cur#*=} + #static list of standard JGroups stacks + local stacks="udp udp-async udp-sync tcp tcp-sync" + COMPREPLY=( $(compgen -W "${stacks}" -- ${cur}) ) + return 0 + ;; + + -Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef=*|-Dcom.sun.management.jmxremote.authenticate=*|-Dcom.sun.management.jmxremote.ssl=*) + cur=${cur#*=} + local booleans="true false" + COMPREPLY=( $(compgen -W "${booleans}" -- ${cur}) ) + return 0 + ;; + + -Djboss.server.base.dir=*|-Djboss.home.dir=*|-Djboss.domain.base.dir=*) + cur=${cur#*=} + _filedir -d + return 0 + ;; + + -Djboss.domain.master.address=*|-Djboss.bind.address*=*) + cur=${cur#*=} + _bindingAddress + return 0 + ;; + --server-config=*|-c=|--host-config=*) + cur=${cur#*=} + _serverProfiles + return 0 + + + esac + + + case $prev in + -u) + # a few from RFC 2365 IPv4 Local Scope () + local addresses="239.255.0.1 239.255.0.2 239.255.0.3" + COMPREPLY=( $(compgen -W "${addresses}" -- ${cur}) ) + return 0 + ;; + -b*) + _bindingAddress + return 0 + ;; + -c) + _serverProfiles + return 0 + ;; + *) + ;; + esac + # *** from jboss5 ******************** + # *** -modulepath -c -m -g -l -d -p -n -B -L -C -Djboss.platform.mbeanserver -Djboss.server.base.directory + # *** -Djboss.Domain -Djboss.modcluster.proxyList -Djboss.jvmRoute -Djboss.default.jgroups.stack -Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef -Djboss.platform.mbeanserver -Dcom.sun.management.jmxremote.port -Dcom.sun.management.jmxremote.ssl + # ************************************* + + # standard commands for standalone and domain mode + local commandsWithoutEqualSign='-b -bmanagement -bunsecure -bpublic --admin-only -h -help -u -version -V -v' + local commandsWithEqualSign='-P -Djboss.node.name -Djboss.home.dir -Djboss.socket.binding.port-offset -Djboss.bind.address.management -Djboss.bind.address -Djboss.bind.address.unsecure' + + if [[ $COMP_WORDS == *standalone.sh* ]] + then + commandsWithoutEqualSign="${commandsWithoutEqualSign} -c" + commandsWithEqualSign="${commandsWithEqualSign} --server-config -Djboss.server.base.dir -c" + else + # assume is domain.sh + commandsWithoutEqualSign="${commandsWithoutEqualSign} --backup --cached-dc" + commandsWithEqualSign="${commandsWithEqualSign} -Djboss.domain.master.address --host-config -Djboss.domain.master.port -Djboss.domain.base.dir " + fi + + + + + COMPREPLY=( $( compgen -W "$commandsWithoutEqualSign" -- "$cur" ) + $( compgen -W "$commandsWithEqualSign" -S '=' -- "$cur" ) ) + return 0 + + +} +complete -o nospace -F _jboss standalone.sh +complete -o nospace -F _jboss domain.sh diff --git a/completion/jungle.completion.sh b/completion/jungle.completion.sh new file mode 100644 index 0000000..351da28 --- /dev/null +++ b/completion/jungle.completion.sh @@ -0,0 +1 @@ +[[ -x "$(which jungle)" ]] && eval "$(_JUNGLE_COMPLETE=source jungle)" diff --git a/completion/kontena.completion.sh b/completion/kontena.completion.sh new file mode 100644 index 0000000..a1d24b3 --- /dev/null +++ b/completion/kontena.completion.sh @@ -0,0 +1 @@ +which kontena > /dev/null && . "$( kontena whoami --bash-completion-path )" diff --git a/completion/kubectl.completion.sh b/completion/kubectl.completion.sh new file mode 100644 index 0000000..e19d0dd --- /dev/null +++ b/completion/kubectl.completion.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# kubectl (Kubernetes CLI) completion + +if command -v kubectl &>/dev/null +then + eval "$(kubectl completion bash)" +fi diff --git a/completion/makefile.completion.sh b/completion/makefile.completion.sh new file mode 100644 index 0000000..c2a833a --- /dev/null +++ b/completion/makefile.completion.sh @@ -0,0 +1,3 @@ +# Add completion for Makefile +# see http://stackoverflow.com/a/38415982/1472048 +complete -W "\`grep -oE '^[a-zA-Z0-9_-]+:([^=]|$)' Makefile | sed 's/[^a-zA-Z0-9_-]*$//'\`" make diff --git a/completion/maven.completion.sh b/completion/maven.completion.sh new file mode 100644 index 0000000..75892f1 --- /dev/null +++ b/completion/maven.completion.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Bash Maven completion + +_mvn() +{ + local cmds cur colonprefixes + cmds="clean validate compile test package integration-test \ + verify install deploy test-compile site generate-sources \ + process-sources generate-resources process-resources \ + eclipse:eclipse eclipse:add-maven-repo eclipse:clean \ + idea:idea -DartifactId= -DgroupId= -Dmaven.test.skip=true \ + -Declipse.workspace= -DarchetypeArtifactId= \ + netbeans-freeform:generate-netbeans-project \ + tomcat:run tomcat:run-war tomcat:deploy jboss-as:deploy \ + versions:display-dependency-updates \ + versions:display-plugin-updates dependency:analyze \ + dependency:analyze-dep-mgt dependency:resolve \ + dependency:sources dependency:tree release:prepare \ + release:rollback release:perform --batch-mode" + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + # Work-around bash_completion issue where bash interprets a colon + # as a separator. + # Work-around borrowed from the darcs work-around for the same + # issue. + colonprefixes=${cur%"${cur##*:}"} + COMPREPLY=( $(compgen -W '$cmds' -- $cur)) + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colonprefixes"} + done + + return 0 +} && +complete -F _mvn mvn \ No newline at end of file diff --git a/completion/npm.completion.sh b/completion/npm.completion.sh new file mode 100644 index 0000000..8714685 --- /dev/null +++ b/completion/npm.completion.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# npm (Node Package Manager) completion +# https://docs.npmjs.com/cli/completion + +if command -v npm &>/dev/null +then + eval "$(npm completion)" +fi diff --git a/completion/nvm.completion.sh b/completion/nvm.completion.sh new file mode 100644 index 0000000..a82b82b --- /dev/null +++ b/completion/nvm.completion.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# nvm (Node Version Manager) completion + +if [ "$NVM_DIR" ] && [ -r "$NVM_DIR"/bash_completion ]; +then + . "$NVM_DIR"/bash_completion +fi diff --git a/completion/packer.completion.sh b/completion/packer.completion.sh new file mode 100644 index 0000000..99c221e --- /dev/null +++ b/completion/packer.completion.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +# Packer (http://www.packer.io) bash completion +# +# This script provides bash completion for packer and supports: +# +# - template filename completion (*.json) in cwd +# - support for basic options (i.e.. -debug) +# - support for complex options (i.e. -parallel=[true|false] +# +# The scirpt has been successfully tested with packer-0.6.0 and the +# following OS: +# +# - OS X 10.9 +# - CentOS-6.5 +# - Ubuntu 12.04 Server +# +# The script technically is heavily inspired by the git-completion.bash +# script. Kudos to Shawn O. Pearce and all other +# contributors for the inspiration and especially to the bash-completion +# team in general. +# +# Copyright (c) 2014 IT Services Department, University of Bern +# +# This script is licensed under the MIT License (MIT) +# For licsense details see the LICENSE file included in the repository +# or read the license text at http://opensource.org/licenses/MIT. +# + +# Generates completion reply, appending a space to possible completion words, +# if necessary. +# It accepts 2 arguments though the second is optional: +# 1: List of possible completion words. +# 2: Generate possible completion matches for this word (optional). +__packercomp () +{ + local cur_="${2-$cur}" + + case "$cur_" in + -*=) + ;; + *) + local c i=0 IFS=$' \t\n' + for c in $1; do + if [[ $c == "$cur_"* ]]; then + case $c in + -*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="$c" + fi + done + ;; + esac +} + +# Generates completion reply for template files in cwd. +__packercomp_template_file () +{ + local IFS=$'\n' + + COMPREPLY=($(compgen -S " " -A file -X '!*.json' -- "${cur}")) +} + +# Generates completion for the build command. +__packer_build () +{ + local builders=" + amazon-ebs amazon-instance amazon-chroot digitalocean docker + googlecompute openstack parallels-iso parallels-pvm qemu + virtualbox-iso virtualbox-ovf vmware-iso vmware-vmx" + + case "$cur" in + -parallel=*) + __packercomp "false true" "${cur##-parallel=}" + return + ;; + -except=*) + __packercomp "$builders" "${cur##-except=}" + return + ;; + -only=*) + __packercomp "$builders" "${cur##-only=}" + return + ;; + -*) + __packercomp "-debug -force -machine-readable -except= -only= -parallel= -var -var-file" + return + ;; + *) + esac + + __packercomp_template_file +} + +# Generates completion for the fix command. +__packer_fix () +{ + __packercomp_template_file +} + +# Generates completion for the inspect command. +__packer_inspect () +{ + case "$cur" in + -*) + __packercomp "-machine-readable" + return + ;; + *) + esac + + __packercomp_template_file +} + +# Generates completion for the validate command. +__packer_validate () +{ + __packercomp_template_file +} + +# Main function for packer completion. +# +# Searches for a command in $COMP_WORDS. If one is found +# the appropriate function from above is called, if not +# completion for global options is done. +_packer_completion () +{ + cur=${COMP_WORDS[COMP_CWORD]} + # Words containing an equal sign get split into tokens in bash > 4, which + # doesn't come in handy here. + # This is handled here. bash < 4 does not split. + declare -f _get_comp_words_by_ref >/dev/null && _get_comp_words_by_ref -n = cur + + COMPREPLY=() + local i c=1 command + + while [ $c -lt $COMP_CWORD ]; do + i="${COMP_WORDS[c]}" + case "$i" in + -*) ;; + *) command="$i"; break ;; + esac + ((c++)) + done + + if [ -z $command ]; then + case "$cur" in + '-'*) + __packercomp "-machine-readable --help --version" + ;; + *) + __packercomp "build fix inspect validate" + ;; + esac + return + fi + + local completion_func="__packer_${command}" + declare -f $completion_func >/dev/null && $completion_func +} + +complete -o nospace -F _packer_completion packer + diff --git a/completion/pip.completion.sh b/completion/pip.completion.sh new file mode 100644 index 0000000..ad3abb7 --- /dev/null +++ b/completion/pip.completion.sh @@ -0,0 +1,11 @@ + +# pip bash completion start +_pip_completion() +{ + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + PIP_AUTO_COMPLETE=1 $1 ) ) +} +complete -o default -F _pip_completion pip +# pip bash completion end + diff --git a/completion/pip3.completion.sh b/completion/pip3.completion.sh new file mode 100644 index 0000000..1800756 --- /dev/null +++ b/completion/pip3.completion.sh @@ -0,0 +1,11 @@ + +# pip bash completion start +_pip_completion() +{ + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + PIP_AUTO_COMPLETE=1 $1 ) ) +} +complete -o default -F _pip_completion pip3 +# pip bash completion end + diff --git a/completion/projects.completion.sh b/completion/projects.completion.sh new file mode 100644 index 0000000..71d740c --- /dev/null +++ b/completion/projects.completion.sh @@ -0,0 +1,39 @@ +_pj() { + [ -z "$PROJECT_PATHS" ] && return + shift + [ "$1" == "open" ] && shift + + local cur prev words cword + _init_completion || return + + local IFS=$'\n' i j k + + compopt -o filenames + + local -r mark_dirs=$(_rl_enabled mark-directories && echo y) + local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y) + + for i in ${PROJECT_PATHS//:/$'\n'}; do + # create an array of matched subdirs + k="${#COMPREPLY[@]}" + for j in $( compgen -d $i/$cur ); do + if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then + j+="/" + fi + COMPREPLY[k++]=${j#$i/} + done + done + + if [[ ${#COMPREPLY[@]} -eq 1 ]]; then + i=${COMPREPLY[0]} + if [[ "$i" == "$cur" && $i != "*/" ]]; then + COMPREPLY[0]="${i}/" + fi + fi + + return 0 +} + +complete -F _pj -o nospace pj +complete -F _pj -o nospace pjo + diff --git a/completion/rake.completion.sh b/completion/rake.completion.sh new file mode 100644 index 0000000..453354f --- /dev/null +++ b/completion/rake.completion.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# Bash completion support for Rake, Ruby Make. + +export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} + +_rakecomplete() { + if [ -f Rakefile ]; then + recent=`ls -t .rake_tasks~ Rakefile **/*.rake 2> /dev/null | head -n 1` + if [[ $recent != '.rake_tasks~' ]]; then + rake --silent --tasks | cut -d " " -f 2 > .rake_tasks~ + fi + COMPREPLY=($(compgen -W "`cat .rake_tasks~`" -- ${COMP_WORDS[COMP_CWORD]})) + return 0 + fi +} + +complete -o default -o nospace -F _rakecomplete rake diff --git a/completion/salt.completion.sh b/completion/salt.completion.sh new file mode 100644 index 0000000..e8cb5b2 --- /dev/null +++ b/completion/salt.completion.sh @@ -0,0 +1,329 @@ +# written by David Pravec +# - feel free to /msg alekibango on IRC if you want to talk about this file + +# TODO: check if --config|-c was used and use configured config file for queries +# TODO: solve somehow completion for salt -G pythonversion:[tab] +# (not sure what to do with lists) +# TODO: --range[tab] -- how? +# TODO: --compound[tab] -- how? +# TODO: use history to extract some words, esp. if ${cur} is empty +# TODO: TEST EVERYTHING a lot +# TODO: cache results of some functions? where? how long? +# TODO: is it ok to use '--timeout 2' ? + + +_salt_get_grains(){ + if [ "$1" = 'local' ] ; then + salt-call --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" |sed 's:\([a-z0-9]\) :\1\: :g' + else + salt '*' --timeout 2 --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" |sed 's:\([a-z0-9]\) :\1\: :g' + fi +} + +_salt_get_grain_values(){ + if [ "$1" = 'local' ] ; then + salt-call --out=txt -- grains.item $1 |sed 's/^\S*:\s//' |grep -v '^\s*$' + else + salt '*' --timeout 2 --out=txt -- grains.item $1 |sed 's/^\S*:\s//' |grep -v '^\s*$' + fi +} + + +_salt(){ + local cur prev opts _salt_grains _salt_coms pprev ppprev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + if [ ${COMP_CWORD} -gt 2 ]; then + pprev="${COMP_WORDS[COMP_CWORD-2]}" + fi + if [ ${COMP_CWORD} -gt 3 ]; then + ppprev="${COMP_WORDS[COMP_CWORD-3]}" + fi + + opts="-h --help -d --doc --documentation --version --versions-report -c \ + --config-dir= -v --verbose -t --timeout= -s --static -b --batch= \ + --batch-size= -E --pcre -L --list -G --grain --grain-pcre -N \ + --nodegroup -R --range -C --compound -I --pillar \ + --return= -a --auth= --eauth= --extended-auth= -T --make-token -S \ + --ipcidr --out=pprint --out=yaml --out=overstatestage --out=json \ + --out=raw --out=highstate --out=key --out=txt --no-color --out-indent= " + + if [[ "${cur}" == -* ]] ; then + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + fi + + # 2 special cases for filling up grain values + case "${pprev}" in + -G|--grain|--grain-pcre) + if [ "${cur}" = ":" ]; then + COMPREPLY=($(compgen -W "`_salt_get_grain_values ${prev}`" )) + return 0 + fi + ;; + esac + case "${ppprev}" in + -G|--grain|--grain-pcre) + if [ "${prev}" = ":" ]; then + COMPREPLY=( $(compgen -W "`_salt_get_grain_values ${pprev}`" -- ${cur}) ) + return 0 + fi + ;; + esac + + if [ "${cur}" = "=" ] && [[ "${prev}" == --* ]]; then + cur="" + fi + if [ "${prev}" = "=" ] && [[ "${pprev}" == --* ]]; then + prev="${pprev}" + fi + + case "${prev}" in + + -c|--config) + COMPREPLY=($(compgen -f -- ${cur})) + return 0 + ;; + salt) + COMPREPLY=($(compgen -W "\'*\' ${opts} `salt-key --no-color -l acc`" -- ${cur})) + return 0 + ;; + -E|--pcre) + COMPREPLY=($(compgen -W "`salt-key --no-color -l acc`" -- ${cur})) + return 0 + ;; + -G|--grain|--grain-pcre) + COMPREPLY=($(compgen -W "$(_salt_get_grains)" -- ${cur})) + return 0 + ;; + -C|--compound) + COMPREPLY=() # TODO: finish this one? how? + return 0 + ;; + -t|--timeout) + COMPREPLY=($( compgen -W "1 2 3 4 5 6 7 8 9 10 15 20 30 40 60 90 120 180" -- ${cur})) + return 0 + ;; + -b|--batch|--batch-size) + COMPREPLY=($(compgen -W "1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100 120 150 200")) + return 0 + ;; + -N|--nodegroup) + MASTER_CONFIG='/etc/salt/master' + COMPREPLY=($(compgen -W "`awk -F ':' 'BEGIN {print_line = 0}; /^nodegroups/ {print_line = 1;getline } print_line && /^ */ {print $1} /^[^ ]/ {print_line = 0}' <${MASTER_CONFIG}`" -- ${cur})) + return 0 + ;; + esac + + _salt_coms="$(salt '*' --timeout 2 --out=txt -- sys.list_functions | sed 's/^.*\[//' | tr -d ",']" )" + all="${opts} ${_salt_coms}" + COMPREPLY=( $(compgen -W "${all}" -- ${cur}) ) + + return 0 +} + +complete -F _salt salt + + +_saltkey(){ + local cur prev opts prev pprev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="-c --config-dir= -h --help --version --versions-report -q --quiet \ + -y --yes --gen-keys= --gen-keys-dir= --keysize= --key-logfile= \ + -l --list= -L --list-all -a --accept= -A --accept-all \ + -r --reject= -R --reject-all -p --print= -P --print-all \ + -d --delete= -D --delete-all -f --finger= -F --finger-all \ + --out=pprint --out=yaml --out=overstatestage --out=json --out=raw \ + --out=highstate --out=key --out=txt --no-color --out-indent= " + if [ ${COMP_CWORD} -gt 2 ]; then + pprev="${COMP_WORDS[COMP_CWORD-2]}" + fi + if [ ${COMP_CWORD} -gt 3 ]; then + ppprev="${COMP_WORDS[COMP_CWORD-3]}" + fi + if [[ "${cur}" == -* ]] ; then + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + fi + + if [ "${cur}" = "=" ] && [[ "${prev}" == --* ]]; then + cur="" + fi + if [ "${prev}" = "=" ] && [[ "${pprev}" == --* ]]; then + prev="${pprev}" + fi + + case "${prev}" in + -a|--accept) + COMPREPLY=($(compgen -W "$(salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur})) + return 0 + ;; + -r|--reject) + COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color)" -- ${cur})) + return 0 + ;; + -d|--delete) + COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color; salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur})) + return 0 + ;; + -c|--config) + COMPREPLY=($(compgen -f -- ${cur})) + return 0 + ;; + --keysize) + COMPREPLY=($(compgen -W "2048 3072 4096 5120 6144" -- ${cur})) + return 0 + ;; + --gen-keys) + return 0 + ;; + --gen-keys-dir) + COMPREPLY=($(compgen -d -- ${cur})) + return 0 + ;; + -p|--print) + COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color; salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur})) + return 0 + ;; + -l|--list) + COMPREPLY=($(compgen -W "pre un acc accepted unaccepted rej rejected all" -- ${cur})) + return 0 + ;; + --accept-all) + return 0 + ;; + esac + COMPREPLY=($(compgen -W "${opts} " -- ${cur})) + return 0 +} + +complete -F _saltkey salt-key + +_saltcall(){ + local cur prev opts _salt_coms pprev ppprev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="-h --help -d --doc --documentation --version --versions-report \ + -m --module-dirs= -g --grains --return= --local -c --config-dir= -l --log-level= \ + --out=pprint --out=yaml --out=overstatestage --out=json --out=raw \ + --out=highstate --out=key --out=txt --no-color --out-indent= " + if [ ${COMP_CWORD} -gt 2 ]; then + pprev="${COMP_WORDS[COMP_CWORD-2]}" + fi + if [ ${COMP_CWORD} -gt 3 ]; then + ppprev="${COMP_WORDS[COMP_CWORD-3]}" + fi + if [[ "${cur}" == -* ]] ; then + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + fi + + if [ "${cur}" = "=" ] && [[ ${prev} == --* ]]; then + cur="" + fi + if [ "${prev}" = "=" ] && [[ ${pprev} == --* ]]; then + prev="${pprev}" + fi + + case ${prev} in + -m|--module-dirs) + COMPREPLY=( $(compgen -d ${cur} )) + return 0 + ;; + -l|--log-level) + COMPREPLY=( $(compgen -W "info none garbage trace warning error debug" -- ${cur})) + return 0 + ;; + -g|grains) + return 0 + ;; + salt-call) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + esac + + _salt_coms="$(salt-call --out=txt -- sys.list_functions|sed 's/^.*\[//' | tr -d ",']" )" + COMPREPLY=( $(compgen -W "${opts} ${_salt_coms}" -- ${cur} )) + return 0 +} + +complete -F _saltcall salt-call + + +_saltcp(){ + local cur prev opts target prefpart postpart helper filt pprev ppprev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="-t --timeout= -s --static -b --batch= --batch-size= \ + -h --help --version --versions-report -c --config-dir= \ + -E --pcre -L --list -G --grain --grain-pcre -N --nodegroup \ + -R --range -C --compound -I --pillar \ + --out=pprint --out=yaml --out=overstatestage --out=json --out=raw \ + --out=highstate --out=key --out=txt --no-color --out-indent= " + if [[ "${cur}" == -* ]] ; then + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + fi + + if [ "${cur}" = "=" ] && [[ "${prev}" == --* ]]; then + cur="" + fi + if [ "${prev}" = "=" ] && [[ "${pprev}" == --* ]]; then + prev=${pprev} + fi + + case ${prev} in + salt-cp) + COMPREPLY=($(compgen -W "${opts} `salt-key -l acc --no-color`" -- ${cur})) + return 0 + ;; + -t|--timeout) + # those numbers are just a hint + COMPREPLY=($(compgen -W "2 3 4 8 10 15 20 25 30 40 60 90 120 180 240 300" -- ${cur} )) + return 0 + ;; + -E|--pcre) + COMPREPLY=($(compgen -W "`salt-key -l acc --no-color`" -- ${cur})) + return 0 + ;; + -L|--list) + # IMPROVEMENTS ARE WELCOME + prefpart="${cur%,*}," + postpart=${cur##*,} + filt="^\($(echo ${cur}| sed 's:,:\\|:g')\)$" + helper=($(salt-key -l acc --no-color | grep -v "${filt}" | sed "s/^/${prefpart}/")) + COMPREPLY=($(compgen -W "${helper[*]}" -- ${cur})) + + return 0 + ;; + -G|--grain|--grain-pcre) + COMPREPLY=($(compgen -W "$(_salt_get_grains)" -- ${cur})) + return 0 + ;; + # FIXME + -R|--range) + # FIXME ?? + return 0 + ;; + -C|--compound) + # FIXME ?? + return 0 + ;; + -c|--config) + COMPREPLY=($(compgen -f -- ${cur})) + return 0 + ;; + esac + + # default is using opts: + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) +} + +complete -F _saltcp salt-cp + diff --git a/completion/sdkman.completion.sh b/completion/sdkman.completion.sh new file mode 100644 index 0000000..95545b8 --- /dev/null +++ b/completion/sdkman.completion.sh @@ -0,0 +1,61 @@ +_sdkman_complete() +{ + local CANDIDATES + local CANDIDATE_VERSIONS + + COMPREPLY=() + + if [ $COMP_CWORD -eq 1 ]; then + COMPREPLY=( $(compgen -W "install uninstall rm list ls use current outdated version default selfupdate broadcast offline help flush" -- ${COMP_WORDS[COMP_CWORD]}) ) + elif [ $COMP_CWORD -eq 2 ]; then + case "${COMP_WORDS[COMP_CWORD-1]}" in + "install" | "uninstall" | "rm" | "list" | "ls" | "use" | "current" | "outdated" ) + CANDIDATES=$(echo "${SDKMAN_CANDIDATES_CSV}" | tr ',' ' ') + COMPREPLY=( $(compgen -W "$CANDIDATES" -- ${COMP_WORDS[COMP_CWORD]}) ) + ;; + "offline" ) + COMPREPLY=( $(compgen -W "enable disable" -- ${COMP_WORDS[COMP_CWORD]}) ) + ;; + "selfupdate" ) + COMPREPLY=( $(compgen -W "force" -P "[" -S "]" -- ${COMP_WORDS[COMP_CWORD]}) ) + ;; + "flush" ) + COMPREPLY=( $(compgen -W "candidates broadcast archives temp" -- ${COMP_WORDS[COMP_CWORD]}) ) + ;; + *) + ;; + esac + elif [ $COMP_CWORD -eq 3 ]; then + case "${COMP_WORDS[COMP_CWORD-2]}" in + "install" | "uninstall" | "rm" | "use" | "default" ) + _sdkman_candidate_versions ${COMP_WORDS[COMP_CWORD-1]} + COMPREPLY=( $(compgen -W "$CANDIDATE_VERSIONS" -- ${COMP_WORDS[COMP_CWORD]}) ) + ;; + *) + ;; + esac + fi + + return 0 +} + +_sdkman_candidate_versions(){ + + CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions $1) + if [ "$SDKMAN_OFFLINE_MODE" = "true" ]; then + CANDIDATE_VERSIONS=$CANDIDATE_LOCAL_VERSIONS + else + CANDIDATE_ONLINE_VERSIONS="$(curl -s "${SDKMAN_SERVICE}/candidates/$1" | tr ',' ' ')" + CANDIDATE_VERSIONS="$(echo $CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS |sort | uniq ) " + fi + +} + +__sdkman_cleanup_local_versions(){ + + __sdkman_build_version_csv $1 + echo $CSV | tr ',' ' ' + +} + +complete -F _sdkman_complete sdk diff --git a/completion/ssh.completion.sh b/completion/ssh.completion.sh new file mode 100644 index 0000000..a411f64 --- /dev/null +++ b/completion/ssh.completion.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Bash completion support for ssh. + +export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} + +_sshcomplete() { + local CURRENT_PROMPT="${COMP_WORDS[COMP_CWORD]}" + if [[ ${CURRENT_PROMPT} == *@* ]] ; then + local OPTIONS="-P ${CURRENT_PROMPT/@*/}@ -- ${CURRENT_PROMPT/*@/}" + else + local OPTIONS=" -- ${CURRENT_PROMPT}" + fi + + + # parse all defined hosts from .ssh/config + if [ -r "$HOME/.ssh/config" ]; then + COMPREPLY=($(compgen -W "$(grep ^Host "$HOME/.ssh/config" | awk '{for (i=2; i<=NF; i++) print $i}' )" ${OPTIONS}) ) + fi + + # parse all hosts found in .ssh/known_hosts + if [ -r "$HOME/.ssh/known_hosts" ]; then + if grep -v -q -e '^ ssh-rsa' "$HOME/.ssh/known_hosts" ; then + COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "$( awk '{print $1}' "$HOME/.ssh/known_hosts" | grep -v ^\| | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" ${OPTIONS}) ) + fi + fi + + # parse hosts defined in /etc/hosts + if [ -r /etc/hosts ]; then + COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "$( grep -v '^[[:space:]]*$' /etc/hosts | grep -v '^#' | awk '{for (i=2; i<=NF; i++) print $i}' )" ${OPTIONS}) ) + fi + + return 0 +} + +complete -o default -o nospace -F _sshcomplete ssh scp diff --git a/completion/svn.completion.sh b/completion/svn.completion.sh new file mode 100644 index 0000000..eabc15c --- /dev/null +++ b/completion/svn.completion.sh @@ -0,0 +1,1514 @@ +# ------------------------------------------------------------ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ------------------------------------------------------------ + +# Programmable completion for the Subversion svn command under bash. Source +# this file (or on some systems add it to ~/.bash_completion and start a new +# shell) and bash's completion mechanism will know all about svn's options! +# Provides completion for the svnadmin, svndumpfilter, svnlook and svnsync +# commands as well. Who wants to read man pages/help text... + +# Known to work with bash 3.* with programmable completion and extended +# pattern matching enabled (use 'shopt -s extglob progcomp' to enable +# these if they are not already enabled). + +shopt -s extglob + +# Tree helper functions which only use bash, to ease readability. + +# look for value associated to key from stdin in K/V hash file format +# val=$(_svn_read_hashfile svn:realmstring < some/file) +function _svn_read_hashfile() +{ + local tkey=$1 key= val= + while true; do + read tag len + [ $tag = 'END' ] && break + [ $tag != 'K' ] && { + #echo "unexpected tag '$tag' instead of 'K'" >&2 + return + } + read -r -n $len key ; read + read tag len + [ $tag != 'V' ] && { + #echo "unexpected tag '$tag' instead of 'V'" >&2 + return + } + read -r -n $len val ; read + if [[ $key = $tkey ]] ; then + echo "$val" + return + fi + done + #echo "target key '$tkey' not found" >&2 +} + +# _svn_grcut shell-regular-expression +# extract filenames from 'svn status' output +function _svn_grcut() +{ + local re=$1 line= old_IFS + # fix IFS, so that leading spaces are not ignored by next read. + # (there is a leading space in svn status output if only a prop is changed) + old_IFS="$IFS" + IFS=$'\n' + while read -r line ; do + [[ ! $re || $line == $re ]] && echo "${line/????????/}" + done + IFS="$old_IFS" +} + +# extract stuff from svn info output +# _svn_info (URL|Repository Root) +function _svn_info() +{ + local what=$1 line= + LANG=C LC_MESSAGES=C svn info --non-interactive 2> /dev/null | \ + while read line ; do + [[ $line == *"$what: "* ]] && echo ${line#*: } + done +} + +# _svn_lls (dir|file|all) files... +# list svn-managed files from list +# some 'svn status --all-files' would be welcome here? +function _svn_lls() +{ + local opt=$1 f= + shift + for f in "$@" ; do + # could try to check in .svn/entries? hmmm... + if [[ $opt == @(dir|all) && -d "$f" ]] ; then + echo "$f/" + elif [[ $opt == @(file|all) ]] ; then + # split f in directory/file names + local dn= fn="$f" + [[ "$f" == */* ]] && dn=${f%\/*}/ fn=${f##*\/} + # ??? this does not work for just added files, because they + # do not have a content reference yet... + [ -f "${dn}.svn/text-base/${fn}.svn-base" ] && echo "$f" + fi + done +} + +# This completion guides the command/option order along the one suggested +# by "svn help", although other syntaxes are allowed. +# +# - there is a "real" parser to check for what is available and deduce what +# can be suggested further. +# - the syntax should be coherent with subversion/svn/{cl.h,main.c} +# - although it is not a good practice, mixed options and arguments +# is supported by the completion as it is by the svn command. +# - the completion works in the middle of a line, +# but not really in the middle of an argument or option. +# - property names are completed: see comments about issues related to handling +# ":" within property names although it is a word completion separator. +# - unknown properties are assumed to be simple file properties. +# - --revprop and --revision options are forced to revision properties +# as they are mandatory in this case. +# - argument values are suggested to some other options, eg directory names +# for --config-dir. +# - values for some options can be extended with environment variables: +# SVN_BASH_FILE_PROPS: other properties on files/directories +# SVN_BASH_REV_PROPS: other properties on revisions +# SVN_BASH_ENCODINGS: encodings to be suggested +# SVN_BASH_MIME_TYPE: mime types to be suggested +# SVN_BASH_KEYWORDS: "svn:keywords" substitutions to be suggested +# SVN_BASH_USERNAME: usernames suggested for --username +# SVN_BASH_COMPL_EXT: completion extensions for file arguments, based on the +# current subcommand, so that for instance only modified files are +# suggested for 'revert', only not svn-managed files for 'add', and so on. +# Possible values are: +# - username: guess usernames from ~/.subversion/auth/... +# - urls: guess urls from ~/.subversion/auth/... or others +# - svnstatus: use 'svn status' for completion +# - recurse: allow recursion (expensive) +# - externals: recurse into externals (very expensive) +# Former options are reasonable, but beware that both later options +# may be unadvisable if used on large working copies. +# None of these costly completions are activated by default. +# Argument completion outside a working copy results in an error message. +# Filenames with spaces are not completed properly. +# +# TODO +# - other options? +# - obsolete options could be removed from auto-comp? (e.g. -N) +# - obsolete commands could be removed? (e.g. resolved) +# - completion does not work properly when editing in the middle of the line +# status/previous are those at the end of the line, not at the entry position +# - url completion should select more cases where it is relevant +# - url completion of http:// schemas could suggest sub directories? +# - add completion for experimental 'obliterate' feature? +_svn() +{ + local cur cmds cmdOpts pOpts mOpts rOpts qOpts nOpts optsParam opt + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + # Possible expansions, without pure-prefix abbreviations such as "up". + cmds='add blame annotate praise cat changelist cl checkout co cleanup' + cmds="$cmds commit ci copy cp delete remove rm diff export help import" + cmds="$cmds info list ls lock log merge mergeinfo mkdir move mv rename" + cmds="$cmds patch propdel pdel propedit pedit propget pget proplist" + cmds="$cmds plist propset pset relocate resolve resolved revert status" + cmds="$cmds switch unlock update upgrade" + + # help options have a strange command status... + local helpOpts='--help -h' + # all special options that have a command status + local specOpts="--version $helpOpts" + + # options that require a parameter + # note: continued lines must end '|' continuing lines must start '|' + optsParam="-r|--revision|--username|--password|--targets" + optsParam="$optsParam|-x|--extensions|-m|--message|-F|--file" + optsParam="$optsParam|--encoding|--diff-cmd|--diff3-cmd|--editor-cmd" + optsParam="$optsParam|--old|--new|--config-dir|--config-option" + optsParam="$optsParam|--native-eol|-l|--limit|-c|--change" + optsParam="$optsParam|--depth|--set-depth|--with-revprop" + optsParam="$optsParam|--cl|--changelist|--accept|--show-revs" + + # svn:* and other (env SVN_BASH_*_PROPS) properties + local svnProps revProps allProps psCmds propCmds + + # svn and user configured "file" (or directory) properties + # the "svn:mergeinfo" prop is not included by default because it is + # managed automatically, so there should be no need to edit it by hand. + svnProps="svn:keywords svn:executable svn:needs-lock svn:externals + svn:ignore svn:eol-style svn:mime-type $SVN_BASH_FILE_PROPS" + + # svn and user configured revision properties + revProps="svn:author svn:log svn:date $SVN_BASH_REV_PROPS" + + # all properties as an array variable + allProps=( $svnProps $revProps ) + + # subcommands that expect property names + psCmds='propset|pset|ps' + propCmds="$psCmds|propget|pget|pg|propedit|pedit|pe|propdel|pdel|pd" + + # possible URL schemas to access a subversion server + local urlSchemas='file:/// http:// https:// svn:// svn+ssh://' + + # Parse arguments and set various variables about what was found. + # + # cmd: the current command if available + # isPropCmd: whether it expects a property name argument + # isPsCmd: whether it also expects a property value argument + # isHelpCmd: whether it is about help + # nExpectArgs: how many arguments are expected by the command + # help: help requested about this command (if cmd=='help') + # prop: property name (if appropriate) + # isRevProp: is it a special revision property + # val: property value (if appropriate, under pset) + # options: all options encountered + # hasRevPropOpt: is --revprop set + # hasRevisionOpt: is --revision set + # hasRelocateOpt: is --relocate set + # hasReintegrateOpt: is --reintegrate set + # acceptOpt: the value of --accept + # nargs: how many arguments were found + # stat: status of parsing at the 'current' word + # + # prev: previous command in the loop + # last: status of last parameter analyzed + # i: index + local cmd= isPropCmd= isPsCmd= isHelpCmd= nExpectArgs= isCur= i=0 + local prev= help= prop= val= isRevProp= last='none' nargs=0 stat= + local options= hasRevPropOpt= hasRevisionOpt= hasRelocateOpt= + local acceptOpt= URL= hasReintegrateOpt= + + for opt in "${COMP_WORDS[@]}" + do + # get status of current word (from previous iteration) + [[ $isCur ]] && stat=$last + + # are we processing the current word + isCur= + [[ $i -eq $COMP_CWORD ]] && isCur=1 + let i++ + + # FIRST must be the "svn" command + [ $last = 'none' ] && { last='first'; continue ; } + + # SKIP option arguments + if [[ $prev == @($optsParam) ]] ; then + + # record accept value + [[ $prev = '--accept' ]] && acceptOpt=$opt + + prev='' + last='skip' + continue ; + fi + + # Argh... This looks like a bash bug... + # Redirections are passed to the completion function + # although it is managed by the shell directly... + # It matters because we want to tell the user when no more + # completion is available, so it does not necessary + # fallback to the default case. + if [[ $prev == @(<|>|>>|[12]>|[12]>>) ]] ; then + prev='' + last='skip' + continue ; + fi + prev=$opt + + # get the subCoMmanD + if [[ ! $cmd && $opt \ + && ( $opt != -* || $opt == @(${specOpts// /|}) ) ]] + then + cmd=$opt + [[ $cmd == @($propCmds) ]] && isPropCmd=1 + [[ $cmd == @($psCmds) ]] && isPsCmd=1 + [[ $cmd == @(${helpOpts// /|}) ]] && cmd='help' + [[ $cmd = 'help' ]] && isHelpCmd=1 + # HELP about a command asked with an option + if [[ $isHelpCmd && $cmd && $cmd != 'help' && ! $help ]] + then + help=$cmd + cmd='help' + fi + last='cmd' + continue + fi + + # HELP about a command + if [[ $isHelpCmd && ! $help && $opt && $opt != -* ]] + then + help=$opt + last='help' + continue + fi + + # PROPerty name + if [[ $isPropCmd && ! $prop && $opt && $opt != -* ]] + then + prop=$opt + [[ $prop == @(${revProps// /|}) ]] && isRevProp=1 + last='prop' + continue + fi + + # property VALue + if [[ $isPsCmd && $prop && ! $val && $opt != -* ]] ; + then + val=$opt + last='val' + continue + fi + + if [[ $last != 'onlyarg' ]] + then + # more OPTions + case $opt in + -r|--revision|--revision=*) + hasRevisionOpt=1 + ;; + --revprop) + hasRevPropOpt=1 + # restrict to revision properties! + allProps=( $revProps ) + # on revprops, only one URL is expected + nExpectArgs=1 + ;; + -h|--help) + isHelpCmd=1 + ;; + -F|--file) + val='-F' + ;; + --relocate) + hasRelocateOpt=1 + ;; + --reintegrate) + hasReintegrateOpt=1 + ;; + esac + + # no more options, only arguments, whatever they look like. + if [[ $opt = '--' && ! $isCur ]] ; then + last='onlyarg' + continue + fi + + # options are recorded... + if [[ $opt == -* ]] ; then + # but not the current one! + [[ ! $isCur ]] && options="$options $opt " + last='opt' + continue + fi + else + # onlyarg + let nargs++ + continue + fi + + # then we have an argument + if [[ $cmd = 'merge' && ! $URL ]] ; then + # fist argument is the source URL for the merge + URL=$opt + fi + + last='arg' + let nargs++ + done + # end opt option processing... + [[ $stat ]] || stat=$last + + # suggest all subcommands, including special help + if [[ ! $cmd || $stat = 'cmd' ]] + then + COMPREPLY=( $( compgen -W "$cmds $specOpts" -- $cur ) ) + return 0 + fi + + # suggest all subcommands + if [[ $stat = 'help' || ( $isHelpCmd && ! $help ) ]] + then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + fi + + # URL completion + if [[ $cmd == @(co|checkout|ls|list) && $stat = 'arg' && \ + $SVN_BASH_COMPL_EXT == *urls* ]] + then + # see about COMP_WORDBREAKS workaround in prop completion + if [[ $cur == file:* ]] + then + # file completion for file:// urls + local where=${cur/file:/} + COMPREPLY=( $(compgen -d -S '/' -X '*/.*' -- $where ) ) + return + elif [[ $cur == *:* ]] + then + # get known urls + local urls= file= + for file in ~/.subversion/auth/svn.simple/* ; do + if [ -r $file ] ; then + local url=$(_svn_read_hashfile svn:realmstring < $file) + url=${url/**/} + urls="$urls $url" + fi + done + + # only suggest/show possible suffixes + local prefix=${cur%:*} suffix=${cur#*:} c= choices= + for c in $urls ; do + [[ $c == $prefix:* ]] && choices="$choices ${c#*:}" + done + + COMPREPLY=( $(compgen -W "$choices" -- $suffix ) ) + return + else + # show schemas + COMPREPLY=( $(compgen -W "$urlSchemas" -- $cur) ) + return + fi + fi + + if [[ $cmd = 'merge' || $cmd = 'mergeinfo' ]] + then + local here=$(_svn_info URL) + # suggest a possible URL for merging + if [[ ! $URL && $stat = 'arg' ]] ; then + # we assume a 'standard' repos with branches and trunk + if [[ "$here" == */branches/* ]] ; then + # we guess that it is a merge from the trunk + COMPREPLY=( $(compgen -W ${here/\/branches\/*/\/trunk} -- $cur ) ) + return 0 + elif [[ "$here" == */trunk* ]] ; then + # we guess that it is a merge from a branch + COMPREPLY=( $(compgen -W ${here/\/trunk*/\/branches\/} -- $cur ) ) + return 0 + else + # no se, let us suggest the repository root... + COMPREPLY=( $(compgen -W $(_svn_info Root) -- $cur ) ) + return 0 + fi + elif [[ $URL == */branches/* && $here == */trunk* && \ + ! $hasReintegrateOpt && $cur = '' && $stat = 'arg' ]] ; then + # force --reintegrate only if the current word is empty + COMPREPLY=( $(compgen -W '--reintegrate' -- $cur ) ) + return 0 + fi + fi + + # help about option arguments + if [[ $stat = 'skip' ]] + then + local previous=${COMP_WORDS[COMP_CWORD-1]} + local values= dirs= beep= exes= + + [[ $previous = '--config-dir' ]] && dirs=1 + + # external editor, diff, diff3... + [[ $previous = --*-cmd ]] && exes=1 + + [[ $previous = '--native-eol' ]] && values='LF CR CRLF' + + # just to suggest that a number is expected. hummm. + [[ $previous = '--limit' ]] && values='0 1 2 3 4 5 6 7 8 9' + + # some special partial help about --revision option. + [[ $previous = '--revision' || $previous = '-r' ]] && \ + values='HEAD BASE PREV COMMITTED 0 {' + + [[ $previous = '--encoding' ]] && \ + values="latin1 utf8 $SVN_BASH_ENCODINGS" + + [[ $previous = '--extensions' || $previous = '-x' ]] && \ + values="--unified --ignore-space-change \ + --ignore-all-space --ignore-eol-style --show-c-functions" + + [[ $previous = '--depth' ]] && \ + values='empty files immediates infinity' + + [[ $previous = '--set-depth' ]] && \ + values='empty exclude files immediates infinity' + + [[ $previous = '--accept' ]] && \ + { + # the list is different for 'resolve' + if [[ $cmd = 'resolve' ]] ; then + # from svn help resolve + values='base working mine-full theirs-full' + else # checkout merge switch update + values="postpone base mine-full theirs-full edit launch \ + mine-conflict theirs-conflict" + fi + } + + [[ $previous = '--show-revs' ]] && values='merged eligible' + + if [[ $previous = '--username' ]] ; then + values="$SVN_BASH_USERNAME" + if [[ $SVN_BASH_COMPL_EXT == *username* ]] ; then + local file= + # digest? others? + for file in ~/.subversion/auth/svn.simple/* ; do + if [ -r $file ] ; then + values="$values $(_svn_read_hashfile username < $file)" + fi + done + fi + [[ ! "$values" ]] && beep=1 + fi + + # could look at ~/.subversion/ ? + # hmmm... this option should not exist + [[ $previous = '--password' ]] && beep=1 + + # TODO: provide help about other options such as: + # --old --new --with-revprop + + # if the previous option required a parameter, do something + # or fallback on ordinary filename expansion + [[ $values ]] && COMPREPLY=( $( compgen -W "$values" -- $cur ) ) + [[ $dirs ]] && COMPREPLY=( $( compgen -o dirnames -- $cur ) ) + [[ $exes ]] && COMPREPLY=( $( compgen -c -- $cur ) ) + [[ $beep ]] && + { + # 'no known completion'. hummm. + echo -en "\a" + COMPREPLY=( '' ) + } + return 0 + fi + + # provide allowed property names after property commands + if [[ $isPropCmd && ( ! $prop || $stat = 'prop' ) && $cur != -* ]] + then + # + # Ok, this part is pretty ugly. + # + # The issue is that ":" is a completion word separator, + # which is a good idea for file:// urls but not within + # property names... + # + # The first idea was to remove locally ":" from COMP_WORDBREAKS + # and then put it back in all cases but in property name + # completion. It does not always work. There is a strange bug + # where one may get "svn:svn:xxx" in some unclear cases. + # + # Thus the handling is reprogrammed here... + # The code assumes that property names look like *:*, + # but it also works reasonably well with simple names. + # + # This hack is broken in bash4... not sure what to do about it, + # especially while keeping the bash3 compatibility:-( + local choices= + + if [[ $cur == *:* ]] + then + # only suggest/show possible suffixes + local prefix=${cur%:*} suffix=${cur#*:} c= + for c in ${allProps[@]} ; do + [[ $c == $prefix:* ]] && choices="$choices ${c#*:}" + done + # everything will be appended to the prefix because ':' is + # a separator, so cur is restricted to the suffix part. + cur=$suffix + else + # only one choice is fine + COMPREPLY=( $( compgen -W "${allProps[*]}" -- $cur ) ) + [ ${#COMPREPLY[@]} -eq 1 ] && return 0 + + # no ':' so only suggest prefixes? + local seen= n=0 last= c= + for c in ${allProps[@]%:*} ; do + # do not put the same prefix twice... + if [[ $c == $cur* && ( ! $seen || $c != @($seen) ) ]] + then + let n++ + last=$c + choices="$choices $c:" + if [[ $seen ]] + then + seen="$seen|$c*" + else + seen="$c*" + fi + fi + done + + # supply two choices to force a partial completion and a beep + [[ $n -eq 1 ]] && choices="$last:1 $last:2" + fi + + COMPREPLY=( $( compgen -W "$choices" -- $cur ) ) + return 0 + fi + + # force mandatory --revprop option on revision properties + if [[ $isRevProp && ! $hasRevPropOpt ]] + then + COMPREPLY=( $( compgen -W '--revprop' -- $cur ) ) + return 0 + fi + + # force mandatory --revision option on revision properties + if [[ $isRevProp && $hasRevPropOpt && ! $hasRevisionOpt ]] + then + COMPREPLY=( $( compgen -W '--revision' -- $cur ) ) + return 0 + fi + + # possible completion when setting property values + if [[ $isPsCmd && $prop && ( ! $val || $stat = 'val' ) ]] + then + # ' is a reminder for an arbitrary value + local values="\' --file" + case $prop in + svn:keywords) + # just a subset? + values="Id Rev URL Date Author Header \' $SVN_BASH_KEYWORDS" + ;; + svn:executable|svn:needs-lock) + # hmmm... canonical value * is special to the shell. + values='\\*' + ;; + svn:eol-style) + values='native LF CR CRLF' + ;; + svn:mime-type) + # could read /etc/mime.types if available. overkill. + values="text/ text/plain text/html text/xml text/rtf + image/ image/png image/gif image/jpeg image/tiff + audio/ audio/midi audio/mpeg + video/ video/mpeg video/mp4 + application/ application/octet-stream + $SVN_BASH_MIME_TYPE" + ;; + esac + + COMPREPLY=( $( compgen -W "$values" -- $cur ) ) + # special case for --file... return even if within an option + [[ ${COMPREPLY} ]] && return 0 + fi + + # maximum number of additional arguments expected in various forms + case $cmd in + merge) + nExpectArgs=3 + ;; + mergeinfo) + nExpectArgs=1 + ;; + copy|cp|move|mv|rename|ren|export|import) + nExpectArgs=2 + ;; + switch|sw) + [[ ! $hasRelocateOpt ]] && nExpectArgs=2 + ;; + help|h) + nExpectArgs=0 + ;; + --version) + nExpectArgs=0 + ;; + esac + + # the maximum number of arguments is reached for a command + if [[ $nExpectArgs && $nargs -gt $nExpectArgs ]] + then + # some way to tell 'no completion at all'... is there a better one? + # Do not say 'file completion' here. + echo -en "\a" + COMPREPLY=( '' ) + return 0 + fi + + # if not typing an option, + # then fallback on filename expansion... + if [[ $cur != -* || $stat = 'onlyarg' ]] ; then + + # do we allow possible expensive completion here? + if [[ $SVN_BASH_COMPL_EXT == *svnstatus* ]] ; then + + # build status command and options + # "--quiet" removes 'unknown' files + local status='svn status --non-interactive' + + [[ $SVN_BASH_COMPL_EXT == *recurse* ]] || \ + status="$status --non-recursive" + + # I'm not sure that it can work with externals in call cases + # the output contains translatable sentences (even with quiet) + [[ $SVN_BASH_COMPL_EXT == *externals* ]] || \ + status="$status --ignore-externals" + + local cs= files= + # subtlety: must not set $cur* if $cur is empty in some cases + [[ $cur ]] && cs=$cur* + + # 'files' is set according to the current subcommand + case $cmd in + st*) # status completion must include all files + files=$cur* + ;; + ci|commit|revert|di*) # anything edited + files=$($status $cs| _svn_grcut '@([MADR!]*| M*|_M*)') + ;; + add) # unknown files + files=$($status $cs| _svn_grcut '\?*') + ;; + unlock) # unlock locked files + files=$($status $cs| _svn_grcut '@(??L*|?????[KOTB]*)') + ;; + resolve*) # files in conflict + files=$($status $cs| _svn_grcut '@(?C*|C*)') + ;; + praise|blame|ann*) # any svn file but added + files=$( _svn_lls all $cur* ) + ;; + p*) # prop commands + if [[ $cmd == @($propCmds) && \ + $prop == @(svn:ignore|svn:externals) ]] ; then + # directory specific props + files=$( _svn_lls dir . $cur* ) + else + # ??? added directories appear twice: foo foo/ + files="$( _svn_lls all $cur* ) + $($status $cs | _svn_grcut 'A*' )" + fi + ;; + info) # information on any file + files="$( _svn_lls all $cur* ) + $($status $cs | _svn_grcut 'A*' )" + ;; + remove|rm|del*|move|mv|rename) # changing existing files + files=$( _svn_lls all $cur* ) + ;; + mkdir) # completion in mkdir can only be for subdirs? + files=$( _svn_lls dir $cur* ) + ;; + log|lock|up*|cl*|switch) # misc, all but added files + files=$( _svn_lls all $cur* ) + ;; + merge) # may do a better job? URL/WCPATH + files=$( _svn_lls all $cur* ) + ;; + ls|list) # better job? what about URLs? + files=$( _svn_lls all $cur* ) + ;; + *) # other commands: changelist export import cat mergeinfo + local fallback=1 + ;; + esac + + # when not recursive, some relevant files may exist + # within subdirectories, so they are added here. + # should it be restricted to svn-managed subdirs? no?? + if [[ $SVN_BASH_COMPL_EXT != *recurse* ]] ; then + files="$files $( _svn_lls dir $cur* )" + fi + + # set completion depending on computed 'files' + if [[ $files ]] ; then + COMPREPLY=( $( compgen -W "$files" -- $cur ) ) + # if empty, set to nope? + [[ "${COMPREPLY[*]}" ]] || COMPREPLY=( '' ) + elif [[ ! $fallback ]] ; then + # this suggests no completion... + echo -en "\a" + COMPREPLY=( '' ) + fi + fi + # else fallback to ordinary filename completion... + return 0 + fi + + # otherwise build possible options for the command + pOpts="--username --password --no-auth-cache --non-interactive \ + --trust-server-cert --force-interactive" + mOpts="-m --message -F --file --encoding --force-log --with-revprop" + rOpts="-r --revision" + qOpts="-q --quiet" + nOpts="-N --non-recursive --depth" + gOpts="-g --use-merge-history" + cOpts="--cl --changelist" + + cmdOpts= + case $cmd in + --version) + cmdOpts="$qOpts" + ;; + add) + cmdOpts="--auto-props --no-auto-props --force --targets \ + --no-ignore --parents $nOpts $qOpts $pOpts" + ;; + blame|annotate|ann|praise) + cmdOpts="$rOpts $pOpts -v --verbose --incremental --xml \ + -x --extensions --force $gOpts" + ;; + cat) + cmdOpts="$rOpts $pOpts" + ;; + changelist|cl) + cmdOpts="--targets $pOpts $qOpts $cOpts \ + -R --recursive --depth --remove" + ;; + checkout|co) + cmdOpts="$rOpts $qOpts $nOpts $pOpts --ignore-externals \ + --force" + ;; + cleanup) + cmdOpts="--diff3-cmd $pOpts" + ;; + commit|ci) + cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts \ + --no-unlock $cOpts --keep-changelists \ + --include-externals" + ;; + copy|cp) + cmdOpts="$mOpts $rOpts $qOpts --editor-cmd $pOpts --parents \ + --ignore-externals" + ;; + delete|del|remove|rm) + cmdOpts="--force $mOpts $qOpts --targets --editor-cmd $pOpts \ + --keep-local" + ;; + diff|di) + cmdOpts="$rOpts -x --extensions --diff-cmd --no-diff-deleted \ + $nOpts $pOpts --force --old --new --notice-ancestry \ + -c --change --summarize $cOpts --xml --git \ + --internal-diff --show-copies-as-adds \ + --ignore-properties --properties-only --no-diff-added \ + --patch-compatible" + ;; + export) + cmdOpts="$rOpts $qOpts $pOpts $nOpts --force --native-eol \ + --ignore-externals --ignore-keywords" + ;; + help|h|\?) + cmdOpts= + ;; + import) + cmdOpts="--auto-props --no-auto-props $mOpts $qOpts $nOpts \ + --no-ignore --editor-cmd $pOpts --force" + ;; + info) + cmdOpts="$pOpts $rOpts --targets -R --recursive --depth \ + --incremental --xml $cOpts" + ;; + list|ls) + cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \ + --incremental --xml --depth --include-externals" + ;; + lock) + cmdOpts="-m --message -F --file --encoding --force-log \ + --targets --force $pOpts" + ;; + log) + cmdOpts="$rOpts -v --verbose --targets $pOpts --stop-on-copy \ + --incremental --xml $qOpts -l --limit -c --change \ + $gOpts --with-all-revprops --with-revprop --depth \ + --diff --diff-cmd -x --extensions --internal-diff \ + --with-no-revprops --search --search-and" + ;; + merge) + cmdOpts="$rOpts $nOpts $qOpts --force --dry-run --diff3-cmd \ + $pOpts --ignore-ancestry -c --change -x --extensions \ + --record-only --accept --reintegrate \ + --allow-mixed-revisions -v --verbose" + ;; + mergeinfo) + cmdOpts="$rOpts $pOpts --depth --show-revs -R --recursive" + ;; + mkdir) + cmdOpts="$mOpts $qOpts --editor-cmd $pOpts --parents" + ;; + move|mv|rename|ren) + cmdOpts="$mOpts $rOpts $qOpts --force --editor-cmd $pOpts \ + --parents --allow-mixed-revisions" + ;; + patch) + cmdOpts="$qOpts $pOpts --dry-run --ignore-whitespace \ + --reverse-diff --strip" + ;; + propdel|pdel|pd) + cmdOpts="$qOpts -R --recursive $rOpts $pOpts $cOpts \ + --depth" + [[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop" + ;; + propedit|pedit|pe) + cmdOpts="--editor-cmd $pOpts $mOpts --force" + [[ $isRevProp || ! $prop ]] && \ + cmdOpts="$cmdOpts --revprop $rOpts" + ;; + propget|pget|pg) + cmdOpts="-v --verbose -R --recursive $rOpts --strict \ + $pOpts $cOpts --depth --xml --show-inherited-props" + [[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop" + ;; + proplist|plist|pl) + cmdOpts="-v --verbose -R --recursive $rOpts --revprop $qOpts \ + $pOpts $cOpts --depth --xml --show-inherited-props" + ;; + propset|pset|ps) + cmdOpts="$qOpts --targets -R --recursive \ + --encoding $pOpts --force $cOpts --depth" + [[ $isRevProp || ! $prop ]] && \ + cmdOpts="$cmdOpts --revprop $rOpts" + [[ $val ]] || cmdOpts="$cmdOpts -F --file" + ;; + relocate) + cmdOpts="--ignore-externals $pOpts" + ;; + resolve) + cmdOpts="--targets -R --recursive $qOpts $pOpts --accept \ + --depth" + ;; + resolved) + cmdOpts="--targets -R --recursive $qOpts $pOpts --depth" + ;; + revert) + cmdOpts="--targets -R --recursive $qOpts $cOpts \ + --depth $pOpts" + ;; + status|stat|st) + cmdOpts="-u --show-updates -v --verbose $nOpts $qOpts $pOpts \ + --no-ignore --ignore-externals --incremental --xml \ + $cOpts" + ;; + switch|sw) + cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts --diff3-cmd \ + --force --accept --ignore-externals --set-depth \ + --ignore-ancestry" + ;; + unlock) + cmdOpts="--targets --force $pOpts" + ;; + update|up) + cmdOpts="$rOpts $nOpts $qOpts $pOpts --diff3-cmd \ + --ignore-externals --force --accept $cOpts \ + --parents --editor-cmd --set-depth" + ;; + upgrade) + cmdOpts="$qOpts $pOpts" + ;; + *) + ;; + esac + + # add options that are nearly always available + [[ "$cmd" != "--version" ]] && cmdOpts="$cmdOpts $helpOpts" + cmdOpts="$cmdOpts --config-dir --config-option" + + # --accept (edit|launch) incompatible with --non-interactive + if [[ $acceptOpt == @(edit|launch) ]] ; + then + cmdOpts=${cmdOpts/ --non-interactive / } + fi + + # take out options already given + for opt in $options + do + local optBase + + # remove leading dashes and arguments + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt:0:2} ;; + esac + + cmdOpts=" $cmdOpts " + cmdOpts=${cmdOpts/ ${optBase} / } + + # take out alternatives and mutually exclusives + case $optBase in + -v) cmdOpts=${cmdOpts/ --verbose / } ;; + --verbose) cmdOpts=${cmdOpts/ -v / } ;; + -N) cmdOpts=${cmdOpts/ --non-recursive / } ;; + --non-recursive) cmdOpts=${cmdOpts/ -N / } ;; + -R) cmdOpts=${cmdOpts/ --recursive / } ;; + --recursive) cmdOpts=${cmdOpts/ -R / } ;; + -x) cmdOpts=${cmdOpts/ --extensions / } ;; + --extensions) cmdOpts=${cmdOpts/ -x / } ;; + -q) cmdOpts=${cmdOpts/ --quiet / } ;; + --quiet) cmdOpts=${cmdOpts/ -q / } ;; + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + -l) cmdOpts=${cmdOpts/ --limit / } ;; + --limit) cmdOpts=${cmdOpts/ -l / } ;; + -r) cmdOpts=${cmdOpts/ --revision / } ;; + --revision) cmdOpts=${cmdOpts/ -r / } ;; + -c) cmdOpts=${cmdOpts/ --change / } ;; + --change) cmdOpts=${cmdOpts/ -c / } ;; + --auto-props) cmdOpts=${cmdOpts/ --no-auto-props / } ;; + --no-auto-props) cmdOpts=${cmdOpts/ --auto-props / } ;; + -g) cmdOpts=${cmdOpts/ --use-merge-history / } ;; + --use-merge-history) + cmdOpts=${cmdOpts/ -g / } ;; + -m|--message|-F|--file) + cmdOpts=${cmdOpts/ --message / } + cmdOpts=${cmdOpts/ -m / } + cmdOpts=${cmdOpts/ --file / } + cmdOpts=${cmdOpts/ -F / } + ;; + esac + + # remove help options within help subcommand + if [ $isHelpCmd ] ; then + cmdOpts=${cmdOpts/ -h / } + cmdOpts=${cmdOpts/ --help / } + fi + done + + # provide help about available options + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + return 0 +} +complete -F _svn -o default -X '@(*/.svn|*/.svn/|.svn|.svn/)' svn + +_svnadmin () +{ + local cur cmds cmdOpts optsParam opt helpCmds optBase i + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + # Possible expansions, without pure-prefix abbreviations such as "h". + cmds='crashtest create deltify dump freeze help hotcopy list-dblogs \ + list-unused-dblogs load lock lslocks lstxns pack recover rmlocks \ + rmtxns setlog setrevprop setuuid unlock upgrade verify --version' + + if [[ $COMP_CWORD -eq 1 ]] ; then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + fi + + # options that require a parameter + # note: continued lines must end '|' continuing lines must start '|' + optsParam="-r|--revision|--parent-dir|--fs-type|-M|--memory-cache-size" + optsParam="$optsParam|-F|--file" + + # if not typing an option, or if the previous option required a + # parameter, then fallback on ordinary filename expansion + helpCmds='help|--help|h|\?' + if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \ + [[ "$cur" != -* ]] || \ + [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then + return 0 + fi + + cmdOpts= + case ${COMP_WORDS[1]} in + create) + cmdOpts="--bdb-txn-nosync --bdb-log-keep --config-dir \ + --fs-type --pre-1.4-compatible --pre-1.5-compatible \ + --pre-1.6-compatible --compatible-version" + ;; + deltify) + cmdOpts="-r --revision -q --quiet" + ;; + dump) + cmdOpts="-r --revision --incremental -q --quiet --deltas \ + -M --memory-cache-size" + ;; + freeze) + cmdOpts="-F --file" + ;; + help|h|\?) + cmdOpts="$cmds" + ;; + hotcopy) + cmdOpts="--clean-logs" + ;; + load) + cmdOpts="--ignore-uuid --force-uuid --parent-dir -q --quiet \ + --use-pre-commit-hook --use-post-commit-hook \ + --bypass-prop-validation -M --memory-cache-size" + ;; + lock|unlock) + cmdOpts="--bypass-hooks" + ;; + recover) + cmdOpts="--wait" + ;; + rmtxns) + cmdOpts="-q --quiet" + ;; + setlog) + cmdOpts="-r --revision --bypass-hooks" + ;; + setrevprop) + cmdOpts="-r --revision --use-pre-revprop-change-hook \ + --use-post-revprop-change-hook" + ;; + verify) + cmdOpts="-r --revision -q --quiet" + ;; + *) + ;; + esac + + cmdOpts="$cmdOpts --help -h" + + # take out options already given + for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do + opt=${COMP_WORDS[$i]} + + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt:0:2} ;; + esac + + cmdOpts=" $cmdOpts " + cmdOpts=${cmdOpts/ ${optBase} / } + + # take out alternatives + case $optBase in + -q) cmdOpts=${cmdOpts/ --quiet / } ;; + --quiet) cmdOpts=${cmdOpts/ -q / } ;; + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + -r) cmdOpts=${cmdOpts/ --revision / } ;; + --revision) cmdOpts=${cmdOpts/ -r / } ;; + -F) cmdOpts=${cmdOpts/ --file / } ;; + --file) cmdOpts=${cmdOpts/ -F / } ;; + -M) cmdOpts=${cmdOpts/ --memory-cache-size / } ;; + --memory-cache-size) cmdOpts=${cmdOpts/ --M / } ;; + esac + + # skip next option if this one requires a parameter + if [[ $opt == @($optsParam) ]] ; then + ((++i)) + fi + done + + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + + return 0 +} +complete -F _svnadmin -o default svnadmin + +_svndumpfilter () +{ + local cur cmds cmdOpts optsParam opt helpCmds optBase i + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + # Possible expansions, without pure-prefix abbreviations such as "h". + cmds='exclude help include --version' + + if [[ $COMP_CWORD -eq 1 ]] ; then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + fi + + # options that require a parameter + # note: continued lines must end '|' continuing lines must start '|' + optsParam="--targets" + + # if not typing an option, or if the previous option required a + # parameter, then fallback on ordinary filename expansion + helpCmds='help|--help|h|\?' + if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \ + [[ "$cur" != -* ]] || \ + [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then + return 0 + fi + + cmdOpts= + case ${COMP_WORDS[1]} in + exclude|include) + cmdOpts="--drop-empty-revs --renumber-revs + --skip-missing-merge-sources --targets + --preserve-revprops --quiet" + ;; + help|h|\?) + cmdOpts="$cmds" + ;; + *) + ;; + esac + + cmdOpts="$cmdOpts --help -h" + + # take out options already given + for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do + opt=${COMP_WORDS[$i]} + + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt:0:2} ;; + esac + + cmdOpts=" $cmdOpts " + cmdOpts=${cmdOpts/ ${optBase} / } + + # take out alternatives + case $optBase in + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + esac + + # skip next option if this one requires a parameter + if [[ $opt == @($optsParam) ]] ; then + ((++i)) + fi + done + + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + + return 0 +} +complete -F _svndumpfilter -o default svndumpfilter + +_svnlook () +{ + local cur cmds cmdOpts optsParam opt helpCmds optBase i + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + # Possible expansions, without pure-prefix abbreviations such as "h". + cmds='author cat changed date diff dirs-changed help history info \ + lock log propget proplist tree uuid youngest --version' + + if [[ $COMP_CWORD -eq 1 ]] ; then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + fi + + # options that require a parameter + # note: continued lines must end '|' continuing lines must start '|' + optsParam="-r|--revision|-t|--transaction|-l|--limit|-x|--extensions" + + # if not typing an option, or if the previous option required a + # parameter, then fallback on ordinary filename expansion + helpCmds='help|--help|h|\?' + if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \ + [[ "$cur" != -* ]] || \ + [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then + return 0 + fi + + cmdOpts= + case ${COMP_WORDS[1]} in + author) + cmdOpts="-r --revision -t --transaction" + ;; + cat) + cmdOpts="-r --revision -t --transaction" + ;; + changed) + cmdOpts="-r --revision -t --transaction --copy-info" + ;; + date) + cmdOpts="-r --revision -t --transaction" + ;; + diff) + cmdOpts="-r --revision -t --transaction --diff-copy-from \ + --no-diff-added --no-diff-deleted -x --extensions" + ;; + dirs-changed) + cmdOpts="-r --revision -t --transaction" + ;; + help|h|\?) + cmdOpts="$cmds" + ;; + history) + cmdOpts="-r --revision -l --limit --show-ids" + ;; + info) + cmdOpts="-r --revision -t --transaction" + ;; + lock) + cmdOpts= + ;; + log) + cmdOpts="-r --revision -t --transaction" + ;; + propget|pget|pg) + cmdOpts="-r --revision -t --transaction --revprop" + ;; + proplist|plist|pl) + cmdOpts="-r --revision -t --transaction --revprop -v --verbose --xml" + ;; + tree) + cmdOpts="-r --revision -t --transaction --full-paths -N --non-recursive --show-ids" + ;; + uuid) + cmdOpts= + ;; + youngest) + cmdOpts= + ;; + *) + ;; + esac + + cmdOpts="$cmdOpts --help -h" + + # take out options already given + for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do + opt=${COMP_WORDS[$i]} + + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt:0:2} ;; + esac + + cmdOpts=" $cmdOpts " + cmdOpts=${cmdOpts/ ${optBase} / } + + # take out alternatives + case $optBase in + -N) cmdOpts=${cmdOpts/ --non-recursive / } ;; + --non-recursive) cmdOpts=${cmdOpts/ -N / } ;; + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + -l) cmdOpts=${cmdOpts/ --limit / } ;; + --limit) cmdOpts=${cmdOpts/ -l / } ;; + -r) cmdOpts=${cmdOpts/ --revision / } ;; + --revision) cmdOpts=${cmdOpts/ -r / } ;; + -t) cmdOpts=${cmdOpts/ --transaction / } ;; + --transaction) cmdOpts=${cmdOpts/ -t / } ;; + -v) cmdOpts=${cmdOpts/ --verbose / } ;; + --verbose) cmdOpts=${cmdOpts/ -v / } ;; + -x) cmdOpts=${cmdOpts/ --extensions / } ;; + --extensions) cmdOpts=${cmdOpts/ -x / } ;; + esac + + # skip next option if this one requires a parameter + if [[ $opt == @($optsParam) ]] ; then + ((++i)) + fi + done + + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + + return 0 +} +complete -F _svnlook -o default svnlook + +_svnsync () +{ + local cur cmds cmdOpts optsParam opt helpCmds optBase i + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + + # Possible expansions, without pure-prefix abbreviations such as "h". + cmds='copy-revprops help info initialize synchronize --version' + + if [[ $COMP_CWORD -eq 1 ]] ; then + COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + return 0 + fi + + # options that require a parameter + # note: continued lines must end '|' continuing lines must start '|' + optsParam="--config-dir|--config-option|--source-username|--source-password" + optsParam="$optsParam|--sync-username|--sync-password" + + # if not typing an option, or if the previous option required a + # parameter, then fallback on ordinary filename expansion + helpCmds='help|--help|h|\?' + if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \ + [[ "$cur" != -* ]] || \ + [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then + return 0 + fi + + cmdOpts= + case ${COMP_WORDS[1]} in + copy-revprops|initialize|init|synchronize|sync) + cmdOpts="--non-interactive --no-auth-cache --trust-server-cert \ + --source-username --source-password --sync-username \ + --sync-password --config-dir --config-option -q --quiet" + ;; + help|h|\?) + cmdOpts="$cmds" + ;; + info) + cmdOpts="--non-interactive --no-auth-cache --trust-server-cert \ + --source-username --source-password --sync-username \ + --sync-password --config-dir --config-option" + ;; + *) + ;; + esac + + cmdOpts="$cmdOpts --help -h" + + # take out options already given + for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do + opt=${COMP_WORDS[$i]} + + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt:0:2} ;; + esac + + cmdOpts=" $cmdOpts " + cmdOpts=${cmdOpts/ ${optBase} / } + + # take out alternatives + case $optBase in + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + -q) cmdOpts=${cmdOpts/ --quiet / } ;; + --quiet) cmdOpts=${cmdOpts/ -q / } ;; + esac + + # skip next option if this one requires a parameter + if [[ $opt == @($optsParam) ]] ; then + ((++i)) + fi + done + + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + + return 0 +} +complete -F _svnsync -o default svnsync + +# reasonable completion for 'svnversion' +_svnversion () +{ + local cmdOpts=" -n --no-newline -c --committed -h --help --version " + local cur=${COMP_WORDS[COMP_CWORD]} + + COMPREPLY=() + + # parse current options + local options= wcpath= trailurl= last='none' stat= opt= i=-1 isCur= + for opt in ${COMP_WORDS[@]} + do + [[ $i -eq $COMP_CWORD ]] && stat=$last + let i++ + + # are we processing the current word? + isCur= + [[ $i -eq $COMP_CWORD ]] && isCur=1 + + # skip first command, should be 'svnversion' + if [ $last = 'none' ] ; then + last='first' + continue + fi + + # get options + if [[ $last != 'arg' && $opt == -* ]] + then + # if '--' is at the current position, it means that we are looking + # for '--*' options, and not the end of option processing. + if [[ $opt = '--' && ! $isCur ]] + then + last='arg' + else + options="$options $opt " + last='opt' + fi + continue + fi + # get arguments + if [[ $opt != -* ]] + then + last='arg' + if [[ ! $wcpath ]] + then + wcpath=$opt + elif [[ ! $trailurl ]] + then + trailurl=$opt + fi + fi + done + [[ $stat ]] || stat=$last + + # argument part + if [[ $cur != -* || $stat = 'arg' ]] + then + [[ $wcpath && $trailurl ]] && COMPREPLY=( '' ) + return 0 + fi + + # suggest options, and take out already given options + for opt in $options + do + # take out options + cmdOpts=${cmdOpts/ $opt / } + + # take out alternatives + case $opt in + -n) cmdOpts=${cmdOpts/ --no-newline / } ;; + --no-newline) cmdOpts=${cmdOpts/ -n / } ;; + -h) cmdOpts=${cmdOpts/ --help / } ;; + --help) cmdOpts=${cmdOpts/ -h / } ;; + -c) cmdOpts=${cmdOpts/ --committed / } ;; + --committed) cmdOpts=${cmdOpts/ -c / } ;; + esac + done + + COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) + + return 0 +} +# -X option does not seem to work? +complete -F _svnversion -o dirnames -X '*.svn*' svnversion diff --git a/completion/system.completion.sh b/completion/system.completion.sh new file mode 100644 index 0000000..b044627 --- /dev/null +++ b/completion/system.completion.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Loads the system's Bash completion modules. +# If Homebrew is installed (OS X), its Bash completion modules are loaded. + +if [ -f /etc/bash_completion ]; then + . /etc/bash_completion +fi + +# Some distribution makes use of a profile.d script to import completion. +if [ -f /etc/profile.d/bash_completion.sh ]; then + . /etc/profile.d/bash_completion.sh +fi + + +if [ $(uname) = "Darwin" ] && command -v brew &>/dev/null ; then + BREW_PREFIX=$(brew --prefix) + + if [ -f "$BREW_PREFIX"/etc/bash_completion ]; then + . "$BREW_PREFIX"/etc/bash_completion + fi + + # homebrew/versions/bash-completion2 (required for projects.completion.bash) is installed to this path + if [ -f "$BREW_PREFIX"/share/bash-completion/bash_completion ]; then + . "$BREW_PREFIX"/share/bash-completion/bash_completion + fi +fi diff --git a/completion/terraform.completion.sh b/completion/terraform.completion.sh new file mode 100644 index 0000000..807a709 --- /dev/null +++ b/completion/terraform.completion.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Bash Terraform completion + +_terraform() +{ + local cmds cur colonprefixes + cmds="apply destroy fmt get graph import init \ + output plan push refresh remote show taint \ + untaint validate version state" + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + # Work-around bash_completion issue where bash interprets a colon + # as a separator. + # Work-around borrowed from the darcs work-around for the same + # issue. + colonprefixes=${cur%"${cur##*:}"} + COMPREPLY=( $(compgen -W '$cmds' -- $cur)) + local i=${#COMPREPLY[*]} + while [ $((--i)) -ge 0 ]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colonprefixes"} + done + + return 0 +} && +complete -F _terraform terraform diff --git a/completion/test_kitchen.completion.sh b/completion/test_kitchen.completion.sh new file mode 100644 index 0000000..2420aab --- /dev/null +++ b/completion/test_kitchen.completion.sh @@ -0,0 +1,31 @@ +__kitchen_instance_list () { + # cache to .kitchen.list.yml + if [[ .kitchen.yml -nt .kitchen.list.yml || .kitchen.local.yml -nt .kitchen.list.yml ]]; then + # update list if config has updated + kitchen list --bare > .kitchen.list.yml + fi + cat .kitchen.list.yml +} + +__kitchen_options () { + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + COMPREPLY=() + + case $prev in + converge|create|destroy|diagnose|list|login|setup|test|verify) + COMPREPLY=( $(compgen -W "$(__kitchen_instance_list)" -- ${cur} )) + return 0 + ;; + driver) + COMPREPLY=( $(compgen -W "create discover help" -- ${cur} )) + return 0 + ;; + *) + COMPREPLY=( $(compgen -W "console converge create destroy driver help init list login setup test verify version" -- ${cur} )) + return 0 + ;; + esac +} +complete -F __kitchen_options kitchen + diff --git a/completion/tmux.completion.sh b/completion/tmux.completion.sh new file mode 100644 index 0000000..ddadcbd --- /dev/null +++ b/completion/tmux.completion.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env bash + +# tmux completion +# See: http://www.debian-administration.org/articles/317 for how to write more. +# Usage: Put "source bash_completion_tmux.sh" into your .bashrc +# Based upon the example at http://paste-it.appspot.com/Pj4mLycDE + +_tmux_expand () +{ + [ "$cur" != "${cur%\\}" ] && cur="$cur"'\'; + if [[ "$cur" == \~*/* ]]; then + eval cur=$cur; + else + if [[ "$cur" == \~* ]]; then + cur=${cur#\~}; + COMPREPLY=($( compgen -P '~' -u $cur )); + return ${#COMPREPLY[@]}; + fi; + fi +} + +_tmux_filedir () +{ + local IFS=' +'; + _tmux_expand || return 0; + if [ "$1" = -d ]; then + COMPREPLY=(${COMPREPLY[@]} $( compgen -d -- $cur )); + return 0; + fi; + COMPREPLY=(${COMPREPLY[@]} $( eval compgen -f -- \"$cur\" )) +} + +function _tmux_complete_client() { + local IFS=$'\n' + local cur="${1}" + COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "$(tmux -q list-clients 2>/dev/null | cut -f 1 -d ':')" -- "${cur}") ) +} +function _tmux_complete_session() { + local IFS=$'\n' + local cur="${1}" + COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "$(tmux -q list-sessions 2>/dev/null | cut -f 1 -d ':')" -- "${cur}") ) +} +function _tmux_complete_window() { + local IFS=$'\n' + local cur="${1}" + local session_name="$(echo "${cur}" | sed 's/\\//g' | cut -d ':' -f 1)" + local sessions + + sessions="$(tmux -q list-sessions 2>/dev/null | sed -re 's/([^:]+:).*$/\1/')" + if [[ -n "${session_name}" ]]; then + sessions="${sessions} + $(tmux -q list-windows -t "${session_name}" 2>/dev/null | sed -re 's/^([^:]+):.*$/'"${session_name}"':\1/')" + fi + cur="$(echo "${cur}" | sed -e 's/:/\\\\:/')" + sessions="$(echo "${sessions}" | sed -e 's/:/\\\\:/')" + COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${sessions}" -- "${cur}") ) +} + +_tmux() { + local cur prev + local i cmd cmd_index option option_index + local opts="" + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [ ${prev} == -f ]; then + _tmux_filedir + else + # Search for the command + local skip_next=0 + for ((i=1; $i<=$COMP_CWORD; i++)); do + if [[ ${skip_next} -eq 1 ]]; then + #echo "Skipping" + skip_next=0; + elif [[ ${COMP_WORDS[i]} != -* ]]; then + cmd="${COMP_WORDS[i]}" + cmd_index=${i} + break + elif [[ ${COMP_WORDS[i]} == -f ]]; then + skip_next=1 + fi + done + + # Search for the last option command + skip_next=0 + for ((i=1; $i<=$COMP_CWORD; i++)); do + if [[ ${skip_next} -eq 1 ]]; then + #echo "Skipping" + skip_next=0; + elif [[ ${COMP_WORDS[i]} == -* ]]; then + option="${COMP_WORDS[i]}" + option_index=${i} + if [[ ${COMP_WORDS[i]} == -- ]]; then + break; + fi + elif [[ ${COMP_WORDS[i]} == -f ]]; then + skip_next=1 + fi + done + + if [[ $COMP_CWORD -le $cmd_index ]]; then + # The user has not specified a command yet + COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "$(tmux start-server \; list-commands | cut -d' ' -f1)" -- "${cur}") ) + else + case ${cmd} in + attach-session|attach) + case "$prev" in + -t) _tmux_complete_session "${cur}" ;; + *) options="-t -d" ;; + esac ;; + detach-client|detach) + case "$prev" in + -t) _tmux_complete_client "${cur}" ;; + *) options="-t" ;; + esac ;; + lock-client|lockc) + case "$prev" in + -t) _tmux_complete_client "${cur}" ;; + *) options="-t" ;; + esac ;; + lock-session|locks) + case "$prev" in + -t) _tmux_complete_session "${cur}" ;; + *) options="-t -d" ;; + esac ;; + new-session|new) + case "$prev" in + -t) _tmux_complete_session "${cur}" ;; + -[n|d|s]) options="-d -n -s -t --" ;; + *) + if [[ ${COMP_WORDS[option_index]} == -- ]]; then + _command_offset ${option_index} + else + options="-d -n -s -t --" + fi + ;; + esac + ;; + refresh-client|refresh) + case "$prev" in + -t) _tmux_complete_client "${cur}" ;; + *) options="-t" ;; + esac ;; + rename-session|rename) + case "$prev" in + -t) _tmux_complete_session "${cur}" ;; + *) options="-t" ;; + esac ;; + source-file|source) _tmux_filedir ;; + has-session|has|kill-session) + case "$prev" in + -t) _tmux_complete_session "${cur}" ;; + *) options="-t" ;; + esac ;; + suspend-client|suspendc) + case "$prev" in + -t) _tmux_complete_client "${cur}" ;; + *) options="-t" ;; + esac ;; + switch-client|switchc) + case "$prev" in + -c) _tmux_complete_client "${cur}" ;; + -t) _tmux_complete_session "${cur}" ;; + *) options="-l -n -p -c -t" ;; + esac ;; + + send-keys|send) + case "$option" in + -t) _tmux_complete_window "${cur}" ;; + *) options="-t" ;; + esac ;; + esac # case ${cmd} + fi # command specified + fi # not -f + + if [[ -n "${options}" ]]; then + COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${options}" -- "${cur}") ) + fi + + return 0 + +} +complete -F _tmux tmux + +# END tmux completion + diff --git a/completion/todo.completion.sh b/completion/todo.completion.sh new file mode 100644 index 0000000..6e38c6f --- /dev/null +++ b/completion/todo.completion.sh @@ -0,0 +1,70 @@ +# link: https://github.com/ginatrapani/todo.txt-cli/blob/master/todo_completion + +_todo() +{ + local cur prev opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + local -r OPTS="-@ -@@ -+ -++ -d -f -h -p -P -PP -a -n -t -v -vv -V -x" + local -r COMMANDS="\ + add a addto addm append app archive command del \ + rm depri dp do help list ls listaddons listall lsa listcon \ + lsc listfile lf listpri lsp listproj lsprj move \ + mv prepend prep pri p replace report shorthelp" + local -r MOVE_COMMAND_PATTERN='^(move|mv)$' + + local _todo_sh=${_todo_sh:-todo.sh} + local completions + if [ $COMP_CWORD -eq 1 ]; then + completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons) $OPTS" + elif [[ $COMP_CWORD -gt 2 && ( \ + "${COMP_WORDS[COMP_CWORD-2]}" =~ $MOVE_COMMAND_PATTERN || \ + "${COMP_WORDS[COMP_CWORD-3]}" =~ $MOVE_COMMAND_PATTERN ) ]]; then + completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile) + else + case "$prev" in + command) + completions=$COMMANDS;; + help) + completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons)";; + addto|listfile|lf) + completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile);; + -*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons) $OPTS";; + *) case "$cur" in + +*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listproj) + COMPREPLY=( $( compgen -W "$completions" -- $cur )) + [ ${#COMPREPLY[@]} -gt 0 ] && return 0 + completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listproj) + ;; + @*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listcon) + COMPREPLY=( $( compgen -W "$completions" -- $cur )) + [ ${#COMPREPLY[@]} -gt 0 ] && return 0 + completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listcon) + ;; + *) if [[ "$cur" =~ ^[0-9]+$ ]]; then + local todo=$( \ + eval TODOTXT_VERBOSE=0 $_todo_sh '-@ -+ -p -x command ls "^ *${cur} "' | \ + sed -e 's/^ *[0-9]\{1,\} //' -e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/' \ + -e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/' \ + -e 's/[[:space:]]*$//' \ + -e '1q' \ + ) + [ "$todo" ] && COMPREPLY[0]="$cur # $todo" + return 0 + else + return 0 + fi + ;; + esac + ;; + esac + fi + + COMPREPLY=( $( compgen -W "$completions" -- $cur )) + return 0 +} + +complete -F _todo todo.sh +complete -F _todo t diff --git a/completion/vagrant.completion.sh b/completion/vagrant.completion.sh new file mode 100644 index 0000000..e0abb7a --- /dev/null +++ b/completion/vagrant.completion.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +__pwdln() { + pwdmod="${PWD}/" + itr=0 + until [[ -z "$pwdmod" ]];do + itr=$(($itr+1)) + pwdmod="${pwdmod#*/}" + done + echo -n $(($itr-1)) +} + +__vagrantinvestigate() { + if [ -f "${PWD}/.vagrant" -o -d "${PWD}/.vagrant" ];then + echo "${PWD}/.vagrant" + return 0 + else + pwdmod2="${PWD}" + for (( i=2; i<=$(__pwdln); i++ ));do + pwdmod2="${pwdmod2%/*}" + if [ -f "${pwdmod2}/.vagrant" -o -d "${pwdmod2}/.vagrant" ];then + echo "${pwdmod2}/.vagrant" + return 0 + fi + done + fi + return 1 +} + +_vagrant() { + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + commands="snapshot box connect destroy docker-logs docker-run global-status halt help init list-commands login package plugin provision rdp reload resume rsync rsync-auto share ssh ssh-config status suspend up version" + + if [ $COMP_CWORD == 1 ] + then + COMPREPLY=($(compgen -W "${commands}" -- ${cur})) + return 0 + fi + + if [ $COMP_CWORD == 2 ] + then + case "$prev" in + "init") + local box_list=$(find "$HOME/.vagrant.d/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;|sed -e 's/-VAGRANTSLASH-/\//') + COMPREPLY=($(compgen -W "${box_list}" -- ${cur})) + return 0 + ;; + "up") + vagrant_state_file=$(__vagrantinvestigate) || return 1 + if [[ -d $vagrant_state_file ]] + then + vm_list=$(find $vagrant_state_file/machines -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + fi + local up_commands="--no-provision" + COMPREPLY=($(compgen -W "${up_commands} ${vm_list}" -- ${cur})) + return 0 + ;; + "ssh"|"provision"|"reload"|"halt"|"suspend"|"resume"|"ssh-config") + vagrant_state_file=$(__vagrantinvestigate) || return 1 + if [[ -f $vagrant_state_file ]] + then + running_vm_list=$(grep 'active' $vagrant_state_file | sed -e 's/"active"://' | tr ',' '\n' | cut -d '"' -f 2 | tr '\n' ' ') + else + running_vm_list=$(find $vagrant_state_file -type f -name "id" | awk -F"/" '{print $(NF-2)}') + fi + COMPREPLY=($(compgen -W "${running_vm_list}" -- ${cur})) + return 0 + ;; + "box") + box_commands="add help list remove repackage" + COMPREPLY=($(compgen -W "${box_commands}" -- ${cur})) + return 0 + ;; + "plugin") + plugin_commands="install license list uninstall update" + COMPREPLY=($(compgen -W "${plugin_commands}" -- ${cur})) + return 0 + ;; + "help") + COMPREPLY=($(compgen -W "${commands}" -- ${cur})) + return 0 + ;; + "snapshot") + snapshot_commands="back delete go list take" + COMPREPLY=($(compgen -W "${snapshot_commands}" -- ${cur})) + return 0 + ;; + *) + ;; + esac + fi + + if [ $COMP_CWORD == 3 ] + then + action="${COMP_WORDS[COMP_CWORD-2]}" + case "$action" in + "up") + if [ "$prev" == "--no-provision" ]; then + COMPREPLY=($(compgen -W "${vm_list}" -- ${cur})) + return 0 + fi + ;; + "box") + case "$prev" in + "remove"|"repackage") + local box_list=$(find "$HOME/.vagrant.d/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;|sed -e 's/-VAGRANTSLASH-/\//') + COMPREPLY=($(compgen -W "${box_list}" -- ${cur})) + return 0 + ;; + *) + esac + ;; + "snapshot") + if [ "$prev" == "go" ]; then + local snapshot_list=$(vagrant snapshot list | awk '/Name:/ { print $2 }') + COMPREPLY=($(compgen -W "${snapshot_list}" -- ${cur})) + return 0 + fi + ;; + esac + fi +} +complete -F _vagrant vagrant diff --git a/completion/vault.completion.sh b/completion/vault.completion.sh new file mode 100644 index 0000000..f0c747c --- /dev/null +++ b/completion/vault.completion.sh @@ -0,0 +1,51 @@ +# --------------------------------------------------------------------------- +# vault-bash-completion +# +# This adds bash completions for [HashiCorp Vault](https://www.vaultproject.io/) +# +# see https://github.com/iljaweis/vault-bash-completion +# --------------------------------------------------------------------------- + +function _vault_mounts() { + ( + set -euo pipefail + if ! vault mounts 2> /dev/null | awk 'NR > 1 {print $1}'; then + echo "secret" + fi + ) +} + +function _vault() { + local VAULT_COMMANDS=$(vault 2>&1 | egrep '^ +' | awk '{print $1}') + + local cur + local prev + + if [ $COMP_CWORD -gt 0 ]; then + cur=${COMP_WORDS[COMP_CWORD]} + prev=${COMP_WORDS[COMP_CWORD-1]} + fi + + local line=${COMP_LINE} + + if [[ $prev =~ ^(policies|policy-write|policy-delete) ]]; then + local policies=$(vault policies 2> /dev/null) + COMPREPLY=($(compgen -W "$policies" -- $cur)) + elif [ "$(echo $line | wc -w)" -le 2 ]; then + if [[ "$line" =~ ^vault\ (read|write|delete|list)\ $ ]]; then + COMPREPLY=($(compgen -W "$(_vault_mounts)" -- '')) + else + COMPREPLY=($(compgen -W "$VAULT_COMMANDS" -- $cur)) + fi + elif [[ "$line" =~ ^vault\ (read|write|delete|list)\ (.*)$ ]]; then + path=${BASH_REMATCH[2]} + if [[ "$path" =~ ^([^ ]+)/([^ /]*)$ ]]; then + list=$(vault list -format=yaml ${BASH_REMATCH[1]} 2> /dev/null | awk '{ print $2 }') + COMPREPLY=($(compgen -W "$list" -P "${BASH_REMATCH[1]}/" -- ${BASH_REMATCH[2]})) + else + COMPREPLY=($(compgen -W "$(_vault_mounts)" -- $path)) + fi + fi +} + +complete -o default -o nospace -F _vault vault diff --git a/completion/virtualbox.completion.sh b/completion/virtualbox.completion.sh new file mode 100644 index 0000000..4a660ac --- /dev/null +++ b/completion/virtualbox.completion.sh @@ -0,0 +1,222 @@ +#!/usr/bin/bash +_vboxmanage_realopts() { + echo $(vboxmanage|grep -i vboxmanage|cut -d' ' -f2|grep '\['|tr -s '[\[\|\]\n' ' ') + echo " " +} + +__vboxmanage_startvm() { + RUNNING=$(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"') + TOTAL=$(vboxmanage list vms | cut -d' ' -f1 | tr -d '"') + + AVAILABLE="" + for VM in $TOTAL; do + MATCH=0; + for RUN in $RUNNING "x"; do + if [ "$VM" == "$RUN" ]; then + MATCH=1 + fi + done + (( $MATCH == 0 )) && AVAILABLE="$AVAILABLE $VM " + done + echo $AVAILABLE +} + +__vboxmanage_list() { + INPUT=$(vboxmanage list | tr -s '[\[\]\|\n]' ' ' | cut -d' ' -f4-) + + PRUNED="" + if [ "$1" == "long" ]; then + for WORD in $INPUT; do + [ "$WORD" == "-l" ] && continue; + [ "$WORD" == "--long" ] && continue; + + PRUNED="$PRUNED $WORD" + done + else + PRUNED=$INPUT + fi + + echo $PRUNED +} + + +__vboxmanage_list_vms() { + VMS="" + if [ "x$1" == "x" ]; then + SEPARATOR=" " + else + SEPARATOR=$1 + fi + + for VM in $(vboxmanage list vms | cut -d' ' -f1 | tr -d '"'); do + [ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}" + VMS="${VMS}${VM}" + done + + echo $VMS +} + +__vboxmanage_list_runningvms() { + VMS="" + if [ "$1" == "" ]; then + SEPARATOR=" " + else + SEPARATOR=$1 + fi + + for VM in $(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"'); do + [ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}" + VMS="${VMS}${VM}" + done + + echo $VMS + +} + +__vboxmanage_controlvm() { + echo "pause resume reset poweroff savestate acpipowerbutton" + echo "acpisleepbutton keyboardputscancode guestmemoryballoon" + echo "gueststatisticsinterval usbattach usbdetach vrde vrdeport" + echo "vrdeproperty vrdevideochannelquality setvideomodehint" + echo "screenshotpng setcredentials teleport plugcpu unplugcpu" + echo "cpuexecutioncap" + +# setlinkstate<1-N> +# nic<1-N> null|nat|bridged|intnet|hostonly|generic +# [] | + # nictrace<1-N> on|off + # nictracefile<1-N> + # nicproperty<1-N> name=[value] + # natpf<1-N> [],tcp|udp,[], + # ,[], + # natpf<1-N> delete + +} + +__vboxmanage_default() { + realopts=$(_vboxmanage_realopts) + opts=$realopts$(vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | grep -v '\[' | sort | uniq) + pruned="" + + # echo "" + # echo "DEBUG: cur: $cur, prev: $prev" + # echo "DEBUG: default: |$p1|$p2|$p3|$p4|" + case ${cur} in + -*) + echo $opts + # COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + esac; + + for WORD in $opts; do + MATCH=0 + for OPT in ${COMP_WORDS[@]}; do + # opts=$(echo ${opts} | grep -v $OPT); + if [ "$OPT" == "$WORD" ]; then + MATCH=1 + break; + fi + if [ "$OPT" == "-v" ] && [ "$WORD" == "--version" ]; then + MATCH=1 + break; + fi + if [ "$OPT" == "--version" ] && [ "$WORD" == "-v" ]; then + MATCH=1 + break; + fi + if [ "$OPT" == "-q" ] && [ "$WORD" == "--nologo" ]; then + MATCH=1 + break; + fi + if [ "$OPT" == "--nologo" ] && [ "$WORD" == "-q" ]; then + MATCH=1 + break; + fi + done + (( $MATCH == 1 )) && continue; + pruned="$pruned $WORD" + + done + + # COMPREPLY=($(compgen -W "${pruned}" -- ${cur})) + echo $pruned + return 0 +} + +_vboxmanage() { + # vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | sort | uniq + local cur p1 p2 p3 p4 opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # echo "cur: |$cur|" + # echo "prev: |$prev|" + + # In case current is complete command + case $cur in + startvm|list|controlvm) + COMPREPLY=($(compgen -W "$cur ")) + return 0 + ;; + esac + + case $prev in + -v|--version) + return 0 + ;; + + -l|--long) + opts=$(__vboxmanage_list "long") + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + startvm|list) + opts=$(__vboxmanage_$prev) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + --type) + COMPREPLY=($(compgen -W "gui headless" -- ${cur})) + return 0 + ;; + gui|headless) + # Done. no more completion possible + return 0 + ;; + vboxmanage|-q|--nologo) + # echo "Got vboxmanage" + opts=$(__vboxmanage_default) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + controlvm) + opts=$(__vboxmanage_list_vms) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + esac + + for VM in $(__vboxmanage_list_vms); do + if [ "$VM" == "$prev" ]; then + pprev=${COMP_WORDS[COMP_CWORD-2]} + # echo "previous: $pprev" + case $pprev in + startvm) + opts="--type" + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + controlvm) + opts=$(__vboxmanage_controlvm) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0; + ;; + esac + fi + done + + # echo "Got to end withoug completion" +} +complete -F _vboxmanage vboxmanage \ No newline at end of file diff --git a/custom/aliases/example.aliases.sh b/custom/aliases/example.aliases.sh new file mode 100644 index 0000000..f980ab7 --- /dev/null +++ b/custom/aliases/example.aliases.sh @@ -0,0 +1,2 @@ +# Add your own custom alias in the custom/aliases directory. Aliases placed +# here will override ones with the same name in the main alias directory. diff --git a/custom/completion/example.completion.sh b/custom/completion/example.completion.sh new file mode 100644 index 0000000..8d69898 --- /dev/null +++ b/custom/completion/example.completion.sh @@ -0,0 +1,2 @@ +# Add your own custom completion in the custom/completion directory. Completions placed +# here will override ones with the same name in the main completion directory. diff --git a/custom/themes/example/example.theme.sh b/custom/themes/example/example.theme.sh new file mode 100644 index 0000000..553df97 --- /dev/null +++ b/custom/themes/example/example.theme.sh @@ -0,0 +1,2 @@ +# Add your own custom themes in the custom/themes directory. Themes placed +# here will override ones with the same name in the main themes directory. diff --git a/lib/history.sh b/lib/history.sh index f78102b..0bc2f23 100644 --- a/lib/history.sh +++ b/lib/history.sh @@ -10,12 +10,12 @@ HISTSIZE=10000 SAVEHIST=10000 # Show history -case $HIST_STAMPS in - "mm/dd/yyyy") alias history='fc -fl 1' ;; - "dd.mm.yyyy") alias history='fc -El 1' ;; - "yyyy-mm-dd") alias history='fc -il 1' ;; - *) alias history='fc -l 1' ;; -esac +#case $HIST_STAMPS in + #"mm/dd/yyyy") alias history='fc -fl 1' ;; + #"dd.mm.yyyy") alias history='fc -El 1' ;; + #"yyyy-mm-dd") alias history='fc -il 1' ;; + #*) alias history='fc -l 1' ;; +#esac #shopt append_history #shopt extended_history diff --git a/lib/theme-and-appearance.sh b/lib/theme-and-appearance.sh new file mode 100644 index 0000000..1f5873e --- /dev/null +++ b/lib/theme-and-appearance.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# colored ls +export LSCOLORS='Gxfxcxdxdxegedabagacad' + +if [[ "$DISABLE_LS_COLORS" != "true" ]]; then + # Find the option for using colors in ls, depending on the version + if [[ "$OSTYPE" == netbsd* ]]; then + # On NetBSD, test if "gls" (GNU ls) is installed (this one supports colors); + # otherwise, leave ls as is, because NetBSD's ls doesn't support -G + gls --color -d . &>/dev/null && alias ls='gls --color=tty' + elif [[ "$OSTYPE" == openbsd* ]]; then + # On OpenBSD, "gls" (ls from GNU coreutils) and "colorls" (ls from base, + # with color and multibyte support) are available from ports. "colorls" + # will be installed on purpose and can't be pulled in by installing + # coreutils, so prefer it to "gls". + gls --color -d . &>/dev/null && alias ls='gls --color=tty' + colorls -G -d . &>/dev/null && alias ls='colorls -G' + elif [[ "$OSTYPE" == darwin* ]]; then + # this is a good alias, it works by default just using $LSCOLORS + ls -G . &>/dev/null && alias ls='ls -G' + + # only use coreutils ls if there is a dircolors customization present ($LS_COLORS or .dircolors file) + # otherwise, gls will use the default color scheme which is ugly af + [[ -n "$LS_COLORS" || -f "$HOME/.dircolors" ]] && gls --color -d . &>/dev/null && alias ls='gls --color=tty' + else + # For GNU ls, we use the default ls color theme. They can later be overwritten by themes. + if [[ -z "$LS_COLORS" ]]; then + (( $+commands[dircolors] )) && eval "$(dircolors -b)" + fi + + #ls --color -d . &>/dev/null && alias ls='ls --color=tty' || { ls -G . &>/dev/null && alias ls='ls -G' } + + # Take advantage of $LS_COLORS for completion as well. + #zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" + fi +fi diff --git a/lib/utils.sh b/lib/utils.sh index 9bef6c6..7f58b56 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -158,10 +158,10 @@ is_confirmed() { # fi # type_exists() { -if [ "$(type -P "$1")" ]; then - return 0 -fi -return 1 + if [ "$(type -P "$1")" ]; then + return 0 + fi + return 1 } # @@ -170,10 +170,10 @@ return 1 # Usage: if is_os 'darwin'; then # is_os() { -if [[ "${OSTYPE}" == $1* ]]; then - return 0 -fi -return 1 + if [[ "${OSTYPE}" == $1* ]]; then + return 0 + fi + return 1 } # diff --git a/oh-my-bash.sh b/oh-my-bash.sh index fecdd3c..0d860ab 100644 --- a/oh-my-bash.sh +++ b/oh-my-bash.sh @@ -65,6 +65,20 @@ for plugin in ${plugins[@]}; do fi done +# Load all of the completion & aliases files in ~/.oh-my-bash/{completion,aliases} +# that end in .completion.sh & .aliases.sh +# TIP: Add files you don't want in git to .gitignore +for alias_file in $OSH/aliases/*.sh; do + custom_alias_file="${OSH_CUSTOM}/aliases/${alias_file:t}" + [ -f "${custom_alias_file}" ] && alias_file=${custom_alias_file} + source $alias_file +done +for completion_file in $OSH/completion/*.sh; do + custom_completion_file="${OSH_CUSTOM}/completion/${completion_file:t}" + [ -f "${custom_completion_file}" ] && completion_file=${custom_completion_file} + source $completion_file +done + # Load all of your custom configurations from custom/ for config_file in $OSH_CUSTOM/*.sh; do if [ -f config_file ]; then @@ -72,23 +86,54 @@ for config_file in $OSH_CUSTOM/*.sh; do fi done unset config_file +# Load all of your custom aliases from custom/ +for alias_file in $OSH_CUSTOM/*.sh; do + if [ -f alias_file ]; then + source $alias_file + fi +done +unset alias_file +# Load all of your custom completions from custom/ +for completion_file in $OSH_CUSTOM/*.sh; do + if [ -f completion_file ]; then + source $completion_file + fi +done +unset completion_file + +# Load colors first so they can be use in base theme +source "${OSH}/themes/colours.theme.sh" +source "${OSH}/themes/base.theme.sh" # Load the theme if [ "$OSH_THEME" = "random" ]; then - themes=($OSH/themes/*theme.sh) + themes=($OSH/themes/*/*theme.sh) N=${#themes[@]} - ((N=(RANDOM%N)+1)) + ((N=(RANDOM%N))) RANDOM_THEME=${themes[$N]} source "$RANDOM_THEME" echo "[oh-my-bash] Random theme '$RANDOM_THEME' loaded..." else if [ ! "$OSH_THEME" = "" ]; then - if [ -f "$OSH_CUSTOM/$OSH_THEME.theme.sh" ]; then - source "$OSH_CUSTOM/$OSH_THEME.theme.sh" - elif [ -f "$OSH_CUSTOM/themes/$OSH_THEME.theme.sh" ]; then - source "$OSH_CUSTOM/themes/$OSH_THEME.theme.sh" + if [ -f "$OSH_CUSTOM/$OSH_THEME/$OSH_THEME.theme.sh" ]; then + source "$OSH_CUSTOM/$OSH_THEME/$OSH_THEME.theme.sh" + elif [ -f "$OSH_CUSTOM/themes/$OSH_THEME/$OSH_THEME.theme.sh" ]; then + source "$OSH_CUSTOM/themes/$OSH_THEME/$OSH_THEME.theme.sh" else - source "$OSH/themes/$OSH_THEME.theme.sh" + source "$OSH/themes/$OSH_THEME/$OSH_THEME.theme.sh" fi fi fi + +if [[ $PROMPT ]]; then + export PS1="\["$PROMPT"\]" +fi + +if ! type_exists '__git_ps1' ; then + source "$OSH/tools/git-prompt.sh" +fi + +# Adding Support for other OSes +PREVIEW="less" +[ -s /usr/bin/gloobus-preview ] && PREVIEW="gloobus-preview" +[ -s /Applications/Preview.app ] && PREVIEW="/Applications/Preview.app" diff --git a/plugins/battery/battery.plugin.sh b/plugins/battery/battery.plugin.sh new file mode 100644 index 0000000..88f1dc1 --- /dev/null +++ b/plugins/battery/battery.plugin.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash + +ac_adapter_connected(){ + if _command_exists upower; + then + upower -i $(upower -e | grep BAT) | grep 'state' | grep -q 'charging\|fully-charged' + return $? + elif _command_exists acpi; + then + acpi -a | grep -q "on-line" + return $? + elif _command_exists pmset; + then + pmset -g batt | grep -q 'AC Power' + return $? + elif _command_exists ioreg; + then + ioreg -n AppleSmartBattery -r | grep -q '"ExternalConnected" = Yes' + return $? + elif _command_exists WMIC; + then + WMIC Path Win32_Battery Get BatteryStatus /Format:List | grep -q 'BatteryStatus=2' + return $? + fi +} + +ac_adapter_disconnected(){ + if _command_exists upower; + then + upower -i $(upower -e | grep BAT) | grep 'state' | grep -q 'discharging' + return $? + elif _command_exists acpi; + then + acpi -a | grep -q "off-line" + return $? + elif _command_exists pmset; + then + pmset -g batt | grep -q 'Battery Power' + return $? + elif _command_exists ioreg; + then + ioreg -n AppleSmartBattery -r | grep -q '"ExternalConnected" = No' + return $? + elif _command_exists WMIC; + then + WMIC Path Win32_Battery Get BatteryStatus /Format:List | grep -q 'BatteryStatus=1' + return $? + fi +} + +battery_percentage(){ + about 'displays battery charge as a percentage of full (100%)' + group 'battery' + + if _command_exists upower; + then + local UPOWER_OUTPUT=$(upower --show-info $(upower --enumerate | grep BAT) | grep percentage | tail --bytes 5) + echo ${UPOWER_OUTPUT: : -1} + elif _command_exists acpi; + then + local ACPI_OUTPUT=$(acpi -b) + case $ACPI_OUTPUT in + *" Unknown"*) + local PERC_OUTPUT=$(echo $ACPI_OUTPUT | head -c 22 | tail -c 2) + case $PERC_OUTPUT in + *%) + echo "0${PERC_OUTPUT}" | head -c 2 + ;; + *) + echo ${PERC_OUTPUT} + ;; + esac + ;; + + *" Charging"* | *" Discharging"*) + local PERC_OUTPUT=$(echo $ACPI_OUTPUT | awk -F, '/,/{gsub(/ /, "", $0); gsub(/%/,"", $0); print $2}' ) + echo ${PERC_OUTPUT} + ;; + *" Full"*) + echo '100' + ;; + *) + echo '-1' + ;; + esac + elif _command_exists pmset; + then + local PMSET_OUTPUT=$(pmset -g ps | sed -n 's/.*[[:blank:]]+*\(.*%\).*/\1/p') + case $PMSET_OUTPUT in + 100*) + echo '100' + ;; + *) + echo $PMSET_OUTPUT | head -c 2 + ;; + esac + elif _command_exists ioreg; + then + local IOREG_OUTPUT=$(ioreg -n AppleSmartBattery -r | awk '$1~/Capacity/{c[$1]=$3} END{OFMT="%05.2f%%"; max=c["\"MaxCapacity\""]; print (max>0? 100*c["\"CurrentCapacity\""]/max: "?")}') + case $IOREG_OUTPUT in + 100*) + echo '100' + ;; + *) + echo $IOREG_OUTPUT | head -c 2 + ;; + esac + elif _command_exists WMIC; + then + local WINPC=$(echo porcent=$(WMIC PATH Win32_Battery Get EstimatedChargeRemaining /Format:List) | grep -o '[0-9]*') + case $WINPC in + 100*) + echo '100' + ;; + *) + echo $WINPC + ;; + esac + else + echo "no" + fi +} + +battery_charge(){ + about 'graphical display of your battery charge' + group 'battery' + + # Full char + local F_C='▸' + # Depleted char + local D_C='▹' + local DEPLETED_COLOR="${normal}" + local FULL_COLOR="${green}" + local HALF_COLOR="${yellow}" + local DANGER_COLOR="${red}" + local BATTERY_OUTPUT="${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${D_C}" + local BATTERY_PERC=$(battery_percentage) + + case $BATTERY_PERC in + no) + echo "" + ;; + 9*) + echo "${FULL_COLOR}${F_C}${F_C}${F_C}${F_C}${F_C}${normal}" + ;; + 8*) + echo "${FULL_COLOR}${F_C}${F_C}${F_C}${F_C}${HALF_COLOR}${F_C}${normal}" + ;; + 7*) + echo "${FULL_COLOR}${F_C}${F_C}${F_C}${F_C}${DEPLETED_COLOR}${D_C}${normal}" + ;; + 6*) + echo "${FULL_COLOR}${F_C}${F_C}${F_C}${HALF_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${normal}" + ;; + 5*) + echo "${FULL_COLOR}${F_C}${F_C}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${normal}" + ;; + 4*) + echo "${FULL_COLOR}${F_C}${F_C}${HALF_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${normal}" + ;; + 3*) + echo "${FULL_COLOR}${F_C}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${normal}" + ;; + 2*) + echo "${FULL_COLOR}${F_C}${HALF_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${normal}" + ;; + 1*) + echo "${FULL_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + 05) + echo "${DANGER_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + 04) + echo "${DANGER_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + 03) + echo "${DANGER_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + 02) + echo "${DANGER_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + 0*) + echo "${HALF_COLOR}${F_C}${DEPLETED_COLOR}${D_C}${D_C}${D_C}${D_C}${normal}" + ;; + *) + echo "${DANGER_COLOR}UNPLG${normal}" + ;; + esac +} diff --git a/plugins/core/core.plugin.sh b/plugins/core/core.plugin.sh index 6527a96..61a3beb 100644 --- a/plugins/core/core.plugin.sh +++ b/plugins/core/core.plugin.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # --------------------------------------------------------------------------- # -# Description: This file holds all my BASH configurations and aliases +# Description: This file holds all base BASH functions # # Sections: # 1. Make Terminal Better (remapping defaults and adding functionality) @@ -12,7 +12,9 @@ # 6. System Operations & Information # 7. Date & Time Management # 8. Web Development -# 9. Reminders & Notes +# 9. +# +# X. Reminders & Notes # # --------------------------------------------------------------------------- @@ -20,58 +22,45 @@ # 1. MAKE TERMINAL BETTER # ----------------------------- -alias cp='cp -iv' # Preferred 'cp' implementation -alias mv='mv -iv' # Preferred 'mv' implementation -alias mkdir='mkdir -pv' # Preferred 'mkdir' implementation -alias ll='ls -lAFh' # Preferred 'ls' implementation -alias less='less -FSRXc' # Preferred 'less' implementation -alias nano='nano -W -$' # Preferred 'nano' implementation -alias wget='wget -c' # Preferred 'wget' implementation (resume download) -cd() { builtin cd "$@"; ll; } # Always list directory contents upon 'cd' -alias cd..='cd ../' # Go back 1 directory level (for fast typers) -alias ..='cd ../' # Go back 1 directory level -alias ...='cd ../../' # Go back 2 directory levels -alias .3='cd ../../../' # Go back 3 directory levels -alias .4='cd ../../../../' # Go back 4 directory levels -alias .5='cd ../../../../../' # Go back 5 directory levels -alias .6='cd ../../../../../../' # Go back 6 directory levels -alias dud='du -d 1 -h' # Short and human-readable file listing -alias duf='du -sh *' # Short and human-readable directory listing -alias ~="cd ~" # ~: Go Home -alias c='clear' # c: Clear terminal display -alias path='echo -e ${PATH//:/\\n}' # path: Echo all executable Paths -alias show_options='shopt' # Show_options: display bash options settings -alias fix_stty='stty sane' # fix_stty: Restore terminal settings when screwed up -alias cic='set completion-ignore-case On' # cic: Make tab-completion case-insensitive -alias h='history | grep $1' # h: Find an executed command in .bash_history -alias src='source ~/.bashrc' # src: Reload .bashrc file -mcd () { mkdir -p "$1" && cd "$1"; } # mcd: Makes new Dir and jumps inside - -# lr: Full Recursive Directory Listing -# ------------------------------------------ -alias lr='ls -R | grep ":$" | sed -e '\''s/:$//'\'' -e '\''s/[^-][^\/]*\//--/g'\'' -e '\''s/^/ /'\'' -e '\''s/-/|/'\'' | less' +# mcd: Makes new Dir and jumps inside +# -------------------------------------------------------------------- + mcd () { builtin mkdir -p -- "$*" ; builtin cd -- "$*" ; } # mans: Search manpage given in agument '1' for term given in argument '2' (case insensitive) -# displays paginated result with colored search terms and two lines surrounding each hit. Example: mans mplayer codec +# displays paginated result with colored search terms and two lines surrounding each hit. +# Example: mans mplayer codec # -------------------------------------------------------------------- - mans () { - man $1 | grep -iC2 --color=always $2 | less - } + mans () { man $1 | grep -iC2 --color=always $2 | less ; } # showa: to remind yourself of an alias (given some part of it) # ------------------------------------------------------------ showa () { /usr/bin/grep --color=always -i -a1 $@ ~/Library/init/bash/aliases.bash | grep -v '^\s*$' | less -FSRXc ; } +# quiet: mute output of a command +# ------------------------------------------------------------ + quiet () { + $* &> /dev/null & + } + +# lsgrep: search through directory contents with grep +# ------------------------------------------------------------ + lsgrep () { ls | grep "$*" ; } + +# banish-cookies: redirect .adobe and .macromedia files to /dev/null +# ------------------------------------------------------------ + banish-cookies () + { + rm -r ~/.macromedia ~/.adobe + ln -s /dev/null ~/.adobe + ln -s /dev/null ~/.macromedia + } + # ------------------------------- # 2. FILE AND FOLDER MANAGEMENT # ------------------------------- zipf () { zip -r "$1".zip "$1" ; } # zipf: To create a ZIP archive of a folder -alias numFiles='echo $(ls -1 | wc -l)' # numFiles: Count of non-hidden files in current dir -alias make1mb='truncate -s 1m ./1MB.dat' # make1mb: Creates a file of 1mb size (all zeros) -alias make5mb='truncate -s 5m ./5MB.dat' # make5mb: Creates a file of 5mb size (all zeros) -alias make10mb='truncate -s 10m ./10MB.dat' # make10mb: Creates a file of 10mb size (all zeros) # extract: Extract most know archives with one command # --------------------------------------------------------- @@ -96,12 +85,44 @@ alias make10mb='truncate -s 10m ./10MB.dat' # make10mb: Creates a file of 1 fi } +# buf: back up file with timestamp +# --------------------------------------------------------- + buf () { + local filename=$1 + local filetime=$(date +%Y%m%d_%H%M%S) + cp -a "${filename}" "${filename}_${filetime}" + } + +# del: move files to hidden folder in tmp, that gets cleared on each reboot +# --------------------------------------------------------- + del() { + mkdir -p /tmp/.trash && mv "$@" /tmp/.trash; + } + +# mkiso: creates iso from current dir in the parent dir (unless defined) +# --------------------------------------------------------- + mkiso () { + if type "mkisofs" > /dev/null; then + [ -z ${1+x} ] && local isoname=${PWD##*/} || local isoname=$1 + [ -z ${2+x} ] && local destpath=../ || local destpath=$2 + [ -z ${3+x} ] && local srcpath=${PWD} || local srcpath=$3 + + if [ ! -f "${destpath}${isoname}.iso" ]; then + echo "writing ${isoname}.iso to ${destpath} from ${srcpath}" + mkisofs -V ${isoname} -iso-level 3 -r -o "${destpath}${isoname}.iso" "${srcpath}" + else + echo "${destpath}${isoname}.iso already exists" + fi + else + echo "mkisofs cmd does not exist, please install cdrtools" + fi + } + # --------------------------- # 3. SEARCHING # --------------------------- -alias qfind="find . -name " # qfind: Quickly search for file ff () { /usr/bin/find . -name "$@" ; } # ff: Find file under the current directory ffs () { /usr/bin/find . -name "$@"'*' ; } # ffs: Find file whose name starts with a given string ffe () { /usr/bin/find . -name '*'"$@" ; } # ffe: Find file whose name ends with a given string @@ -119,26 +140,6 @@ ffe () { /usr/bin/find . -name '*'"$@" ; } # ffe: Find file whose name end # ----------------------------------------------------- findPid () { lsof -t -c "$@" ; } -# memHogsTop, memHogsPs: Find memory hogs -# ----------------------------------------------------- - alias memHogsTop='top -l 1 -o rsize | head -20' - alias memHogsPs='ps wwaxm -o pid,stat,vsize,rss,time,command | head -10' - -# cpuHogs: Find CPU hogs -# ----------------------------------------------------- - alias cpu_hogs='ps wwaxr -o pid,stat,%cpu,time,command | head -10' - -# topForever: Continual 'top' listing (every 10 seconds) -# ----------------------------------------------------- - alias topForever='top -l 9999999 -s 10 -o cpu' - -# ttop: Recommended 'top' invocation to minimize resources -# ------------------------------------------------------------ -# Taken from this macosxhints article -# http://www.macosxhints.com/article.php?story=20060816123853639 -# ------------------------------------------------------------ - alias ttop="top -R -F -s 10 -o rsize" - # my_ps: List processes owned by my user: # ------------------------------------------------------------ my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,start,time,bsdtime,command ; } @@ -148,15 +149,32 @@ ffe () { /usr/bin/find . -name '*'"$@" ; } # ffe: Find file whose name end # 5. NETWORKING # --------------------------- -alias myip='curl ifconfig.co' # myip: Public facing IP Address -alias netCons='lsof -i' # netCons: Show all open TCP/IP sockets -alias lsock='sudo /usr/sbin/lsof -i -P' # lsock: Display open sockets -alias lsockU='sudo /usr/sbin/lsof -nP | grep UDP' # lsockU: Display only open UDP sockets -alias lsockT='sudo /usr/sbin/lsof -nP | grep TCP' # lsockT: Display only open TCP sockets -alias ipInfo0='ifconfig getpacket en0' # ipInfo0: Get info on connections for en0 -alias ipInfo1='ifconfig getpacket en1' # ipInfo1: Get info on connections for en1 -alias openPorts='sudo lsof -i | grep LISTEN' # openPorts: All listening connections -alias showBlocked='sudo ipfw list' # showBlocked: All ipfw rules inc/ blocked IPs +# ips: display all ip addresses for this host +# ------------------------------------------------------------------- + ips () { + if command -v ifconfig &>/dev/null + then + ifconfig | awk '/inet /{ print $2 }' + elif command -v ip &>/dev/null + then + ip addr | grep -oP 'inet \K[\d.]+' + else + echo "You don't have ifconfig or ip command installed!" + fi + } + +# down4me: checks whether a website is down for you, or everybody +# ------------------------------------------------------------------- + down4me () { + curl -s "http://www.downforeveryoneorjustme.com/$1" | sed '/just you/!d;s/<[^>]*>//g' + } + +# myip: displays your ip address, as seen by the Internet +# ------------------------------------------------------------------- + myip () { + res=$(curl -s checkip.dyndns.org | grep -Eo '[0-9\.]+') + echo -e "Your public IP is: ${echo_bold_green} $res ${echo_normal}" + } # ii: display useful host related informaton # ------------------------------------------------------------------- @@ -177,16 +195,6 @@ alias showBlocked='sudo ipfw list' # showBlocked: All ip # 6. SYSTEMS OPERATIONS & INFORMATION # --------------------------------------- -alias mountReadWrite='/sbin/mount -uw /' # mountReadWrite: For use when booted into single-user -alias perm='stat --printf "%a %n \n "' # perm: Show permission of target in number -alias 000='chmod 000' # ---------- (no fucking permissions) -alias 640='chmod 640' # -rw-r----- (user: rw, group: r, other: -) -alias 644='chmod 644' # -rw-r--r-- (user: rw, group: r, other: -) -alias 755='chmod 755' # -rwxr-xr-x (user: rwx, group: rx, other: x) -alias 775='chmod 775' # -rwxrwxr-x (user: rwx, group: rwx, other: rx) -alias mx='chmod a+x' # ---x--x--x (user: --x, group: --x, other: --x) -alias ux='chmod u+x' # ---x------ (user: --x, group: -, other: -) - # batch_chmod: Batch chmod for all files & sub-directories in the current one # ------------------------------------------------------------------- batch_chmod() @@ -199,32 +207,62 @@ alias ux='chmod u+x' # ---x------ (user: --x, group: -, o echo "$(tput sgr0)" } +# usage: disk usage per directory, in Mac OS X and Linux +# ------------------------------------------------------------------- + usage () { + if [ $(uname) = "Darwin" ]; then + if [ -n "$1" ]; then + du -hd 1 "$1" + else + du -hd 1 + fi - # --------------------------------------- - # 7. DATE & TIME MANAGEMENT - # --------------------------------------- -alias bdate="date '+%a, %b %d %Y %T %Z'" -alias cal='cal -3' -alias da='date "+%Y-%m-%d %A %T %Z"' -alias daysleft='echo "There are $(($(date +%j -d"Dec 31, $(date +%Y)")-$(date +%j))) left in year $(date +%Y)."' -alias epochtime='date +%s' -alias mytime='date +%H:%M:%S' -alias secconvert='date -d@1234567890' -alias stamp='date "+%Y%m%d%a%H%M"' -alias timestamp='date "+%Y%m%dT%H%M%S"' -alias today='date +"%A, %B %-d, %Y"' -alias weeknum='date +%V' + elif [ $(uname) = "Linux" ]; then + if [ -n "$1" ]; then + du -h --max-depth=1 "$1" + else + du -h --max-depth=1 + fi + fi + } + +# command_exists: checks for existence of a command (0 = true, 1 = false) +# ------------------------------------------------------------------- + command_exists () { + type "$1" &> /dev/null ; + } + +# pickfrom: picks random line from file +# ------------------------------------------------------------------- + pickfrom () { + local file=$1 + [ -z "$file" ] && reference $FUNCNAME && return + length=$(cat $file | wc -l) + n=$(expr $RANDOM \* $length \/ 32768 + 1) + head -n $n $file | tail -1 + } + +# passgen: generates random password from dictionary words +# Note default length of generated password is 4, you can pass it to the command +# E.g. passgen 15 +# ------------------------------------------------------------------- + passgen () { + local i pass length=${1:-4} + pass=$(echo $(for i in $(eval echo "{1..$length}"); do pickfrom /usr/share/dict/words; done)) + echo "With spaces (easier to memorize): $pass" + echo "Without (use this as the password): $(echo $pass | tr -d ' ')" + } + + +# --------------------------------------- +# 7. DATE & TIME MANAGEMENT +# --------------------------------------- # --------------------------------------- # 8. WEB DEVELOPMENT # --------------------------------------- -alias apacheEdit='sudo edit /etc/httpd/httpd.conf' # apacheEdit: Edit httpd.conf -alias apacheRestart='sudo apachectl graceful' # apacheRestart: Restart Apache -alias editHosts='sudo edit /etc/hosts' # editHosts: Edit /etc/hosts file -alias herr='tail /var/log/httpd/error_log' # herr: Tails HTTP error logs -alias apacheLogs="less +F /var/log/apache2/error_log" # Apachelogs: Shows apache error logs httpHeaders () { /usr/bin/curl -I -L $@ ; } # httpHeaders: Grabs headers from web page # httpDebug: Download a web page and show info on what took time @@ -232,8 +270,10 @@ httpHeaders () { /usr/bin/curl -I -L $@ ; } # httpHeaders: Grab httpDebug () { /usr/bin/curl $@ -o /dev/null -w "dns: %{time_namelookup} connect: %{time_connect} pretransfer: %{time_pretransfer} starttransfer: %{time_starttransfer} total: %{time_total}\n" ; } + + # --------------------------------------- -# 9. REMINDERS & NOTES +# X. REMINDERS & NOTES # --------------------------------------- # remove_disk: spin down unneeded disk diff --git a/templates/bashrc.osh-template b/templates/bashrc.osh-template index f6623a9..c1f5ce6 100644 --- a/templates/bashrc.osh-template +++ b/templates/bashrc.osh-template @@ -6,7 +6,7 @@ export OSH=$HOME/.oh-my-bash # Set name of the theme to load. Optionally, if you set this to "random" # it'll load a random theme each time that oh-my-bash is loaded. -OSH_THEME="powerline" +OSH_THEME="font" # Uncomment the following line to use case-sensitive completion. # CASE_SENSITIVE="true" diff --git a/themes/90210/90210.theme.sh b/themes/90210/90210.theme.sh new file mode 100644 index 0000000..e683e0e --- /dev/null +++ b/themes/90210/90210.theme.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +# Nicely formatted terminal prompt +function prompt_command(){ + export PS1="\n${bold_black}[${blue}\@${bold_black}]-${bold_black}[${green}\u${yellow}@${green}\h${bold_black}]-${bold_black}[${purple}\w${bold_black}]-$(scm_prompt_info)\n${reset_color}\$ " +} + +safe_append_prompt_command prompt_command diff --git a/themes/axin/axin.theme.sh b/themes/axin/axin.theme.sh new file mode 100644 index 0000000..edca238 --- /dev/null +++ b/themes/axin/axin.theme.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Axin Bash Prompt, inspired by theme "Sexy" and "Bobby" +# thanks to them + +if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then export TERM=gnome-256color +elif [[ $TERM != dumb ]] && infocmp xterm-256color >/dev/null 2>&1; then export TERM=xterm-256color +fi + +if tput setaf 1 &> /dev/null; then + if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then + MAGENTA=$(tput setaf 9) + ORANGE=$(tput setaf 172) + GREEN=$(tput setaf 190) + PURPLE=$(tput setaf 141) + WHITE=$(tput setaf 0) + else + MAGENTA=$(tput setaf 5) + ORANGE=$(tput setaf 4) + GREEN=$(tput setaf 2) + PURPLE=$(tput setaf 1) + WHITE=$(tput setaf 7) + fi + BOLD=$(tput bold) + RESET=$(tput sgr0) +else + MAGENTA="\033[1;31m" + ORANGE="\033[1;33m" + GREEN="\033[1;32m" + PURPLE="\033[1;35m" + WHITE="\033[1;37m" + BOLD="" + RESET="\033[m" +fi + +function prompt_command() { + PS1="\[${BOLD}${MAGENTA}\]\u \[$WHITE\]@ \[$ORANGE\]\h \[$WHITE\]in \[$GREEN\]\w\[$WHITE\]\[$SCM_THEME_PROMPT_PREFIX\]$(clock_prompt) \[$PURPLE\]\$(scm_prompt_info) \n\$ \[$RESET\]" +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"${white}"} + +safe_append_prompt_command prompt_command diff --git a/themes/bakke/bakke.theme.sh b/themes/bakke/bakke.theme.sh new file mode 100644 index 0000000..5758598 --- /dev/null +++ b/themes/bakke/bakke.theme.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="|" + +function prompt_command() { + #PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} " + #PS1="\n${purple}\h: ${reset_color} ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} " + #PS1="\n${cyan}\h: ${reset_color} ${yellow}\w\n${red}$(scm_char)${red}$(scm_prompt_info) ${green}→${reset_color} " + PS1="\n${cyan}\h: ${reset_color} ${yellow}\w ${green}$(scm_prompt_info)\n${reset_color}→ " +} + +safe_append_prompt_command prompt_command diff --git a/themes/base.theme.sh b/themes/base.theme.sh new file mode 100644 index 0000000..bc53666 --- /dev/null +++ b/themes/base.theme.sh @@ -0,0 +1,521 @@ +#!/usr/bin/env bash + +CLOCK_CHAR_THEME_PROMPT_PREFIX='' +CLOCK_CHAR_THEME_PROMPT_SUFFIX='' +CLOCK_THEME_PROMPT_PREFIX='' +CLOCK_THEME_PROMPT_SUFFIX='' + +THEME_PROMPT_HOST='\H' + +SCM_CHECK=${SCM_CHECK:=true} + +SCM_THEME_PROMPT_DIRTY=' ✗' +SCM_THEME_PROMPT_CLEAN=' ✓' +SCM_THEME_PROMPT_PREFIX=' |' +SCM_THEME_PROMPT_SUFFIX='|' +SCM_THEME_BRANCH_PREFIX='' +SCM_THEME_TAG_PREFIX='tag:' +SCM_THEME_DETACHED_PREFIX='detached:' +SCM_THEME_BRANCH_TRACK_PREFIX=' → ' +SCM_THEME_BRANCH_GONE_PREFIX=' ⇢ ' +SCM_THEME_CURRENT_USER_PREFFIX=' ☺︎ ' +SCM_THEME_CURRENT_USER_SUFFIX='' +SCM_THEME_CHAR_PREFIX='' +SCM_THEME_CHAR_SUFFIX='' + +THEME_BATTERY_PERCENTAGE_CHECK=${THEME_BATTERY_PERCENTAGE_CHECK:=true} + +SCM_GIT_SHOW_DETAILS=${SCM_GIT_SHOW_DETAILS:=true} +SCM_GIT_SHOW_REMOTE_INFO=${SCM_GIT_SHOW_REMOTE_INFO:=auto} +SCM_GIT_IGNORE_UNTRACKED=${SCM_GIT_IGNORE_UNTRACKED:=false} +SCM_GIT_SHOW_CURRENT_USER=${SCM_GIT_SHOW_CURRENT_USER:=false} +SCM_GIT_SHOW_MINIMAL_INFO=${SCM_GIT_SHOW_MINIMAL_INFO:=false} + +SCM_GIT='git' +SCM_GIT_CHAR='±' +SCM_GIT_DETACHED_CHAR='⌿' +SCM_GIT_AHEAD_CHAR="↑" +SCM_GIT_BEHIND_CHAR="↓" +SCM_GIT_UNTRACKED_CHAR="?:" +SCM_GIT_UNSTAGED_CHAR="U:" +SCM_GIT_STAGED_CHAR="S:" + +SCM_HG='hg' +SCM_HG_CHAR='☿' + +SCM_SVN='svn' +SCM_SVN_CHAR='⑆' + +SCM_NONE='NONE' +SCM_NONE_CHAR='○' + +RVM_THEME_PROMPT_PREFIX=' |' +RVM_THEME_PROMPT_SUFFIX='|' + +THEME_SHOW_USER_HOST=${THEME_SHOW_USER_HOST:=false} +USER_HOST_THEME_PROMPT_PREFIX='' +USER_HOST_THEME_PROMPT_SUFFIX='' + +VIRTUALENV_THEME_PROMPT_PREFIX=' |' +VIRTUALENV_THEME_PROMPT_SUFFIX='|' + +RBENV_THEME_PROMPT_PREFIX=' |' +RBENV_THEME_PROMPT_SUFFIX='|' + +RBFU_THEME_PROMPT_PREFIX=' |' +RBFU_THEME_PROMPT_SUFFIX='|' + +function scm { + if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE + elif [[ -f .git/HEAD ]]; then SCM=$SCM_GIT + elif which git &> /dev/null && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then SCM=$SCM_GIT + elif [[ -d .hg ]]; then SCM=$SCM_HG + elif which hg &> /dev/null && [[ -n "$(hg root 2> /dev/null)" ]]; then SCM=$SCM_HG + elif [[ -d .svn ]]; then SCM=$SCM_SVN + else SCM=$SCM_NONE + fi +} + +function scm_prompt_char { + if [[ -z $SCM ]]; then scm; fi + if [[ $SCM == $SCM_GIT ]]; then SCM_CHAR=$SCM_GIT_CHAR + elif [[ $SCM == $SCM_HG ]]; then SCM_CHAR=$SCM_HG_CHAR + elif [[ $SCM == $SCM_SVN ]]; then SCM_CHAR=$SCM_SVN_CHAR + else SCM_CHAR=$SCM_NONE_CHAR + fi +} + +function scm_prompt_vars { + scm + scm_prompt_char + SCM_DIRTY=0 + SCM_STATE='' + [[ $SCM == $SCM_GIT ]] && git_prompt_vars && return + [[ $SCM == $SCM_HG ]] && hg_prompt_vars && return + [[ $SCM == $SCM_SVN ]] && svn_prompt_vars && return +} + +function scm_prompt_info { + scm + scm_prompt_char + scm_prompt_info_common +} + +function scm_prompt_char_info { + scm_prompt_char + echo -ne "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" + scm_prompt_info_common +} + +function scm_prompt_info_common { + SCM_DIRTY=0 + SCM_STATE='' + + if [[ ${SCM} == ${SCM_GIT} ]]; then + if [[ ${SCM_GIT_SHOW_MINIMAL_INFO} == true ]]; then + # user requests minimal git status information + git_prompt_minimal_info + else + # more detailed git status + git_prompt_info + fi + return + fi + + # TODO: consider adding minimal status information for hg and svn + [[ ${SCM} == ${SCM_HG} ]] && hg_prompt_info && return + [[ ${SCM} == ${SCM_SVN} ]] && svn_prompt_info && return +} + +# This is added to address bash shell interpolation vulnerability described +# here: https://github.com/njhartwell/pw3nage +function git_clean_branch { + local unsafe_ref=$(command git symbolic-ref -q HEAD 2> /dev/null) + local stripped_ref=${unsafe_ref##refs/heads/} + local clean_ref=${stripped_ref//[^a-zA-Z0-9\/]/-} + echo $clean_ref +} + +function git_prompt_minimal_info { + local ref + local status + local git_status_flags=('--porcelain') + SCM_STATE=${SCM_THEME_PROMPT_CLEAN} + + if [[ "$(command git config --get bash-it.hide-status)" != "1" ]]; then + # Get the branch reference + ref=$(git_clean_branch) || \ + ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0 + SCM_BRANCH=${SCM_THEME_BRANCH_PREFIX}${ref} + + # Get the status + [[ "${SCM_GIT_IGNORE_UNTRACKED}" = "true" ]] && git_status_flags+='-untracked-files=no' + status=$(command git status ${git_status_flags} 2> /dev/null | tail -n1) + + if [[ -n ${status} ]]; then + SCM_DIRTY=1 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + fi + + # Output the git prompt + SCM_PREFIX=${SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${SCM_THEME_PROMPT_SUFFIX} + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" + fi +} + +function git_status_summary { + awk ' + BEGIN { + untracked=0; + unstaged=0; + staged=0; + } + { + if (!after_first && $0 ~ /^##.+/) { + print $0 + seen_header = 1 + } else if ($0 ~ /^\?\? .+/) { + untracked += 1 + } else { + if ($0 ~ /^.[^ ] .+/) { + unstaged += 1 + } + if ($0 ~ /^[^ ]. .+/) { + staged += 1 + } + } + after_first = 1 + } + END { + if (!seen_header) { + print + } + print untracked "\t" unstaged "\t" staged + }' +} + +function git_prompt_vars { + local details='' + SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + if [[ "$(git config --get bash-it.hide-status)" != "1" ]]; then + [[ "${SCM_GIT_IGNORE_UNTRACKED}" = "true" ]] && local git_status_flags='-uno' + local status_lines=$((git status --porcelain ${git_status_flags} -b 2> /dev/null || + git status --porcelain ${git_status_flags} 2> /dev/null) | git_status_summary) + local status=$(awk 'NR==1' <<< "$status_lines") + local counts=$(awk 'NR==2' <<< "$status_lines") + IFS=$'\t' read untracked_count unstaged_count staged_count <<< "$counts" + if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then + SCM_DIRTY=1 + if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then + [[ "${staged_count}" -gt 0 ]] && details+=" ${SCM_GIT_STAGED_CHAR}${staged_count}" && SCM_DIRTY=3 + [[ "${unstaged_count}" -gt 0 ]] && details+=" ${SCM_GIT_UNSTAGED_CHAR}${unstaged_count}" && SCM_DIRTY=2 + [[ "${untracked_count}" -gt 0 ]] && details+=" ${SCM_GIT_UNTRACKED_CHAR}${untracked_count}" && SCM_DIRTY=1 + fi + SCM_STATE=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + fi + fi + + [[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && details+="$(git_user_info)" + + SCM_CHANGE=$(git rev-parse --short HEAD 2>/dev/null) + + local ref=$(git_clean_branch) + + if [[ -n "$ref" ]]; then + SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}${ref}" + local tracking_info="$(grep -- "${SCM_BRANCH}\.\.\." <<< "${status}")" + if [[ -n "${tracking_info}" ]]; then + [[ "${tracking_info}" =~ .+\[gone\]$ ]] && local branch_gone="true" + tracking_info=${tracking_info#\#\# ${SCM_BRANCH}...} + tracking_info=${tracking_info% [*} + local remote_name=${tracking_info%%/*} + local remote_branch=${tracking_info#${remote_name}/} + local remote_info="" + local num_remotes=$(git remote | wc -l 2> /dev/null) + [[ "${SCM_BRANCH}" = "${remote_branch}" ]] && local same_branch_name=true + if ([[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "auto" ]] && [[ "${num_remotes}" -ge 2 ]]) || + [[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "true" ]]; then + remote_info="${remote_name}" + [[ "${same_branch_name}" != "true" ]] && remote_info+="/${remote_branch}" + elif [[ ${same_branch_name} != "true" ]]; then + remote_info="${remote_branch}" + fi + if [[ -n "${remote_info}" ]];then + if [[ "${branch_gone}" = "true" ]]; then + SCM_BRANCH+="${SCM_THEME_BRANCH_GONE_PREFIX}${remote_info}" + else + SCM_BRANCH+="${SCM_THEME_BRANCH_TRACK_PREFIX}${remote_info}" + fi + fi + fi + SCM_GIT_DETACHED="false" + else + local detached_prefix="" + ref=$(git describe --tags --exact-match 2> /dev/null) + if [[ -n "$ref" ]]; then + detached_prefix=${SCM_THEME_TAG_PREFIX} + else + ref=$(git describe --contains --all HEAD 2> /dev/null) + ref=${ref#remotes/} + [[ -z "$ref" ]] && ref=${SCM_CHANGE} + detached_prefix=${SCM_THEME_DETACHED_PREFIX} + fi + SCM_BRANCH=${detached_prefix}${ref} + SCM_GIT_DETACHED="true" + fi + + local ahead_re='.+ahead ([0-9]+).+' + local behind_re='.+behind ([0-9]+).+' + [[ "${status}" =~ ${ahead_re} ]] && SCM_BRANCH+=" ${SCM_GIT_AHEAD_CHAR}${BASH_REMATCH[1]}" + [[ "${status}" =~ ${behind_re} ]] && SCM_BRANCH+=" ${SCM_GIT_BEHIND_CHAR}${BASH_REMATCH[1]}" + + local stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')" + [[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" {${stash_count}}" + + SCM_BRANCH+=${details} + + SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${GIT_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} +} + +function svn_prompt_vars { + if [[ -n $(svn status 2> /dev/null) ]]; then + SCM_DIRTY=1 + SCM_STATE=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + SCM_DIRTY=0 + SCM_STATE=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + SCM_PREFIX=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${SVN_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + SCM_BRANCH=$(svn info 2> /dev/null | awk -F/ '/^URL:/ { for (i=0; i<=NF; i++) { if ($i == "branches" || $i == "tags" ) { print $(i+1); break }; if ($i == "trunk") { print $i; break } } }') || return + SCM_CHANGE=$(svn info 2> /dev/null | sed -ne 's#^Revision: ##p' ) +} + +# this functions returns absolute location of .hg directory if one exists +# It starts in the current directory and moves its way up until it hits /. +# If we get to / then no Mercurial repository was found. +# Example: +# - lets say we cd into ~/Projects/Foo/Bar +# - .hg is located in ~/Projects/Foo/.hg +# - get_hg_root starts at ~/Projects/Foo/Bar and sees that there is no .hg directory, so then it goes into ~/Projects/Foo +function get_hg_root { + local CURRENT_DIR=$(pwd) + + while [ "$CURRENT_DIR" != "/" ]; do + if [ -d "$CURRENT_DIR/.hg" ]; then + echo "$CURRENT_DIR/.hg" + return + fi + + CURRENT_DIR=$(dirname $CURRENT_DIR) + done +} + +function hg_prompt_vars { + if [[ -n $(hg status 2> /dev/null) ]]; then + SCM_DIRTY=1 + SCM_STATE=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + SCM_DIRTY=0 + SCM_STATE=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + SCM_PREFIX=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${HG_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + + HG_ROOT=$(get_hg_root) + + if [ -f "$HG_ROOT/branch" ]; then + # Mercurial holds it's current branch in .hg/branch file + SCM_BRANCH=$(cat "$HG_ROOT/branch") + else + SCM_BRANCH=$(hg summary 2> /dev/null | grep branch: | awk '{print $2}') + fi + + if [ -f "$HG_ROOT/dirstate" ]; then + # Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState + SCM_CHANGE=$(hexdump -n 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12) + else + SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}') + fi +} + +function rvm_version_prompt { + if which rvm &> /dev/null; then + rvm=$(rvm-prompt) || return + if [ -n "$rvm" ]; then + echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX" + fi + fi +} + +function rbenv_version_prompt { + if which rbenv &> /dev/null; then + rbenv=$(rbenv version-name) || return + $(rbenv commands | grep -q gemset) && gemset=$(rbenv gemset active 2> /dev/null) && rbenv="$rbenv@${gemset%% *}" + if [ $rbenv != "system" ]; then + echo -e "$RBENV_THEME_PROMPT_PREFIX$rbenv$RBENV_THEME_PROMPT_SUFFIX" + fi + fi +} + +function rbfu_version_prompt { + if [[ $RBFU_RUBY_VERSION ]]; then + echo -e "${RBFU_THEME_PROMPT_PREFIX}${RBFU_RUBY_VERSION}${RBFU_THEME_PROMPT_SUFFIX}" + fi +} + +function chruby_version_prompt { + if declare -f -F chruby &> /dev/null; then + if declare -f -F chruby_auto &> /dev/null; then + chruby_auto + fi + + ruby_version=$(ruby --version | awk '{print $1, $2;}') || return + + if [[ ! $(chruby | grep '*') ]]; then + ruby_version="${ruby_version} (system)" + fi + echo -e "${CHRUBY_THEME_PROMPT_PREFIX}${ruby_version}${CHRUBY_THEME_PROMPT_SUFFIX}" + fi +} + +function ruby_version_prompt { + echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)" +} + +function virtualenv_prompt { + if [[ -n "$VIRTUAL_ENV" ]]; then + virtualenv=`basename "$VIRTUAL_ENV"` + echo -e "$VIRTUALENV_THEME_PROMPT_PREFIX$virtualenv$VIRTUALENV_THEME_PROMPT_SUFFIX" + fi +} + +function condaenv_prompt { + if [[ $CONDA_DEFAULT_ENV ]]; then + echo -e "${CONDAENV_THEME_PROMPT_PREFIX}${CONDA_DEFAULT_ENV}${CONDAENV_THEME_PROMPT_SUFFIX}" + fi +} + +function py_interp_prompt { + py_version=$(python --version 2>&1 | awk '{print "py-"$2;}') || return + echo -e "${PYTHON_THEME_PROMPT_PREFIX}${py_version}${PYTHON_THEME_PROMPT_SUFFIX}" +} + +function python_version_prompt { + echo -e "$(virtualenv_prompt)$(condaenv_prompt)$(py_interp_prompt)" +} + +function git_user_info { + # support two or more initials, set by 'git pair' plugin + SCM_CURRENT_USER=$(git config user.initials | sed 's% %+%') + # if `user.initials` weren't set, attempt to extract initials from `user.name` + [[ -z "${SCM_CURRENT_USER}" ]] && SCM_CURRENT_USER=$(printf "%s" $(for word in $(git config user.name | tr 'A-Z' 'a-z'); do printf "%1.1s" $word; done)) + [[ -n "${SCM_CURRENT_USER}" ]] && printf "%s" "$SCM_THEME_CURRENT_USER_PREFFIX$SCM_CURRENT_USER$SCM_THEME_CURRENT_USER_SUFFIX" +} + +function clock_char { + CLOCK_CHAR=${THEME_CLOCK_CHAR:-"⌚"} + CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$normal"} + SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"} + + if [[ "${SHOW_CLOCK_CHAR}" = "true" ]]; then + echo -e "${CLOCK_CHAR_COLOR}${CLOCK_CHAR_THEME_PROMPT_PREFIX}${CLOCK_CHAR}${CLOCK_CHAR_THEME_PROMPT_SUFFIX}" + fi +} + +function clock_prompt { + CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$normal"} + CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"} + [ -z $THEME_SHOW_CLOCK ] && THEME_SHOW_CLOCK=${THEME_CLOCK_CHECK:-"true"} + SHOW_CLOCK=$THEME_SHOW_CLOCK + + if [[ "${SHOW_CLOCK}" = "true" ]]; then + CLOCK_STRING=$(date +"${CLOCK_FORMAT}") + echo -e "${CLOCK_COLOR}${CLOCK_THEME_PROMPT_PREFIX}${CLOCK_STRING}${CLOCK_THEME_PROMPT_SUFFIX}" + fi +} + +function user_host_prompt { + if [[ "${THEME_SHOW_USER_HOST}" = "true" ]]; then + echo -e "${USER_HOST_THEME_PROMPT_PREFIX}\u@\h${USER_HOST_THEME_PROMPT_SUFFIX}" + fi +} + +# backwards-compatibility +function git_prompt_info { + git_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" +} + +function svn_prompt_info { + svn_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" +} + +function hg_prompt_info() { + hg_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE#*:}${SCM_STATE}${SCM_SUFFIX}" +} + +function scm_char { + scm_prompt_char + echo -e "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" +} + +function prompt_char { + scm_char +} + +function battery_char { + if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then + echo -e "${bold_red}$(battery_percentage)%" + fi +} + +if ! type_exists 'battery_charge' ; then + # if user has installed battery plugin, skip this... + function battery_charge (){ + # no op + echo -n + } +fi + +# The battery_char function depends on the presence of the battery_percentage function. +# If battery_percentage is not defined, then define battery_char as a no-op. +if ! type_exists 'battery_percentage' ; then + function battery_char (){ + # no op + echo -n + } +fi + +function aws_profile { + if [[ $AWS_DEFAULT_PROFILE ]]; then + echo -e "${AWS_DEFAULT_PROFILE}" + else + echo -e "default" + fi +} + +function safe_append_prompt_command { + local prompt_re + + # Set OS dependent exact match regular expression + if [[ ${OSTYPE} == darwin* ]]; then + # macOS + prompt_re="[[:<:]]${1}[[:>:]]" + else + # Linux, FreeBSD, etc. + prompt_re="\<${1}\>" + fi + + if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then + return + elif [[ -z ${PROMPT_COMMAND} ]]; then + PROMPT_COMMAND="${1}" + else + PROMPT_COMMAND="${1};${PROMPT_COMMAND}" + fi +} diff --git a/themes/binaryanomaly/binaryanomaly.theme.sh b/themes/binaryanomaly/binaryanomaly.theme.sh new file mode 100644 index 0000000..4c580eb --- /dev/null +++ b/themes/binaryanomaly/binaryanomaly.theme.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# Set term to 256color mode, if 256color is not supported, colors won't work properly +if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then + export TERM=gnome-256color +elif infocmp xterm-256color >/dev/null 2>&1; then + export TERM=xterm-256color +fi + +# Detect whether a rebbot is required +function show_reboot_required() { + if [ ! -z "$_bf_prompt_reboot_info" ]; then + if [ -f /var/run/reboot-required ]; then + printf "Reboot required!" + fi + fi +} + +# Set different host color for local and remote sessions +function set_host_color() { + # Detect if connection is through SSH + if [[ ! -z $SSH_CLIENT ]]; then + printf "${lime_yellow}" + else + printf "${light_orange}" + fi +} + +# Set different username color for users and root +function set_user_color() { + case $(id -u) in + 0) + printf "${red}" + ;; + *) + printf "${cyan}" + ;; + esac +} + +scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)$(scm_prompt_info)]" + fi +} + +# Define custom colors we need +# non-printable bytes in PS1 need to be contained within \[ \]. +# Otherwise, bash will count them in the length of the prompt +function set_custom_colors() { + dark_grey="\[$(tput setaf 8)\]" + light_grey="\[$(tput setaf 248)\]" + + light_orange="\[$(tput setaf 172)\]" + bright_yellow="\[$(tput setaf 220)\]" + lime_yellow="\[$(tput setaf 190)\]" + + powder_blue="\[$(tput setaf 153)\]" +} + +__ps_time() { + echo "$(clock_prompt)${normal}\n" +} + +function prompt_command() { + ps_reboot="${bright_yellow}$(show_reboot_required)${normal}\n" + + ps_username="$(set_user_color)\u${normal}" + ps_uh_separator="${dark_grey}@${normal}" + ps_hostname="$(set_host_color)\h${normal}" + + ps_path="${yellow}\w${normal}" + ps_scm_prompt="${light_grey}$(scm_prompt)" + + ps_user_mark="${normal} ${normal}" + ps_user_input="${normal}" + + # Set prompt + PS1="$ps_reboot$(__ps_time)$ps_username$ps_uh_separator$ps_hostname $ps_path $ps_scm_prompt$ps_user_mark$ps_user_input" +} + +# Initialize custom colors +set_custom_colors + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$dark_grey"} + +# scm theming +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${light_grey}" +SCM_THEME_PROMPT_CLEAN=" ${green}✓${light_grey}" +SCM_GIT_CHAR="${green}±${light_grey}" +SCM_SVN_CHAR="${bold_cyan}⑆${light_grey}" +SCM_HG_CHAR="${bold_red}☿${light_grey}" + +safe_append_prompt_command prompt_command diff --git a/themes/bobby-python/bobby-python.theme.sh b/themes/bobby-python/bobby-python.theme.sh new file mode 100644 index 0000000..e2e5a97 --- /dev/null +++ b/themes/bobby-python/bobby-python.theme.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +CONDAENV_THEME_PROMPT_SUFFIX="|" + +function prompt_command() { + #PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} " + PS1="\n${yellow}$(python_version_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} " +} + +safe_append_prompt_command prompt_command diff --git a/themes/bobby/bobby.theme.sh b/themes/bobby/bobby.theme.sh new file mode 100644 index 0000000..0e70f8a --- /dev/null +++ b/themes/bobby/bobby.theme.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" ${green}|" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="|" + +__bobby_clock() { + printf "$(clock_prompt) " + + if [ "${THEME_SHOW_CLOCK_CHAR}" == "true" ]; then + printf "$(clock_char) " + fi +} + +function prompt_command() { + #PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} " + PS1="\n$(battery_char) $(__bobby_clock)${yellow}$(ruby_version_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_prompt_char_info) ${green}→${reset_color} " +} + +THEME_SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"} +THEME_CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$red"} +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$bold_cyan"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%Y-%m-%d %H:%M:%S"} + +safe_append_prompt_command prompt_command diff --git a/themes/brainy/README.md b/themes/brainy/README.md new file mode 100644 index 0000000..dc6eaec --- /dev/null +++ b/themes/brainy/README.md @@ -0,0 +1,123 @@ +# Brainy theme + +Simple colorful terminal prompt theme (inspired by a number of themes). + +## Features + +### Prompt Segments + +- Username & Hostname +- Current Directory +- SCM Information +- Battery Charge +- Clock +- [Todo.txt](https://github.com/ginatrapani/todo.txt-cli) status +- Ruby Environment +- Python Environment +- Exit Code + +### Others + +- Indicator for cached `sudo` credential +- Indicator for ssh login +- `brainy` command for showing/hiding various prompt segments on-the-fly + +## Configuration + +Various prompt segments can be shown/hidden or modified according to your choice. There are two ways for doing that: + +1. On-the-fly using `brainy` command +2. Theme Environment Variables + +### On-the-fly using `brainy` command + +This theme provides a command for showing/hiding prompt segments. + +`brainy show ` + +`brainy hide ` + +Tab-completion for this command is enabled by default. + +Configuration specified by this command will only be applied to current and subsequent child shells. + +### Theme Environment Variables + +This is used for permanent settings that apply to all terminal sessions. You have to define the value of specific theme variables in your `bashrc` (or equivalent) file. + +The name of the variables are listed below along with their default values. + +#### User Information + +Indicator for cached `sudo` credential (see `sudo` manpage for more information): + +`THEME_SHOW_SUDO=true` + +#### SCM Information + +Information about SCM repository status: + +`THEME_SHOW_SCM=true` + +#### Ruby Environment + +Ruby environment version information: + +`THEME_SHOW_RUBY=false` + +#### Python Environment + +Python environment version information: + +`THEME_SHOW_PYTHON=false` + +#### ToDo.txt status + +[Todo.txt](https://github.com/ginatrapani/todo.txt-cli) status: + +`THEME_SHOW_TODO=false` + +#### Clock + +`THEME_SHOW_CLOCK=true` + +`THEME_CLOCK_COLOR=$bold_cyan` + +Format of the clock (see `date` manpage for more information): + +`THEME_CLOCK_FORMAT="%H:%M:%S"` + +#### Battery Charge + +Battery charge percentage: + +`THEME_SHOW_BATTERY=false` + +#### Exit Code + +Exit code of the last command: + +`THEME_SHOW_EXITCODE=true` + +## Prompt Segments Order + +Currently available prompt segments are: + +- battery +- char +- clock +- dir +- exitcode +- python +- ruby +- scm +- todo +- user_info + +Three environment variables can be defined to rearrange the segments order. The default values are: + +`___BRAINY_TOP_LEFT="user_info dir scm"` + +`___BRAINY_TOP_RIGHT="python ruby todo clock battery"` + +`___BRAINY_BOTTOM="exitcode char"` diff --git a/themes/brainy/brainy.theme.sh b/themes/brainy/brainy.theme.sh new file mode 100644 index 0000000..8562646 --- /dev/null +++ b/themes/brainy/brainy.theme.sh @@ -0,0 +1,295 @@ +#!/usr/bin/env bash + +# Brainy Bash Prompt for Bash-it +# by MunifTanjim + +############# +## Parsers ## +############# + +____brainy_top_left_parse() { + ifs_old="${IFS}" + IFS="|" + args=( $1 ) + IFS="${ifs_old}" + if [ -n "${args[3]}" ]; then + _TOP_LEFT+="${args[2]}${args[3]}" + fi + _TOP_LEFT+="${args[0]}${args[1]}" + if [ -n "${args[4]}" ]; then + _TOP_LEFT+="${args[2]}${args[4]}" + fi + _TOP_LEFT+=" " +} + +____brainy_top_right_parse() { + ifs_old="${IFS}" + IFS="|" + args=( $1 ) + IFS="${ifs_old}" + _TOP_RIGHT+=" " + if [ -n "${args[3]}" ]; then + _TOP_RIGHT+="${args[2]}${args[3]}" + fi + _TOP_RIGHT+="${args[0]}${args[1]}" + if [ -n "${args[4]}" ]; then + _TOP_RIGHT+="${args[2]}${args[4]}" + fi + __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1 )) + (( __SEG_AT_RIGHT += 1 )) +} + +____brainy_bottom_parse() { + ifs_old="${IFS}" + IFS="|" + args=( $1 ) + IFS="${ifs_old}" + _BOTTOM+="${args[0]}${args[1]}" + [ ${#args[1]} -gt 0 ] && _BOTTOM+=" " +} + +____brainy_top() { + _TOP_LEFT="" + _TOP_RIGHT="" + __TOP_RIGHT_LEN=0 + __SEG_AT_RIGHT=0 + + for seg in ${___BRAINY_TOP_LEFT}; do + info="$(___brainy_prompt_"${seg}")" + [ -n "${info}" ] && ____brainy_top_left_parse "${info}" + done + + ___cursor_right="\033[500C" + _TOP_LEFT+="${___cursor_right}" + + for seg in ${___BRAINY_TOP_RIGHT}; do + info="$(___brainy_prompt_"${seg}")" + [ -n "${info}" ] && ____brainy_top_right_parse "${info}" + done + + [ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN - 1 )) + ___cursor_adjust="\033[${__TOP_RIGHT_LEN}D" + _TOP_LEFT+="${___cursor_adjust}" + + printf "%s%s" "${_TOP_LEFT}" "${_TOP_RIGHT}" +} + +____brainy_bottom() { + _BOTTOM="" + for seg in $___BRAINY_BOTTOM; do + info="$(___brainy_prompt_"${seg}")" + [ -n "${info}" ] && ____brainy_bottom_parse "${info}" + done + printf "\n%s" "${_BOTTOM}" +} + +############## +## Segments ## +############## + +___brainy_prompt_user_info() { + color=$bold_blue + if [ "${THEME_SHOW_SUDO}" == "true" ]; then + if [ $(sudo -n id -u 2>&1 | grep 0) ]; then + color=$bold_red + fi + fi + box="[|]" + info="\u@\H" + if [ -n "${SSH_CLIENT}" ]; then + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" + else + printf "%s|%s" "${color}" "${info}" + fi +} + +___brainy_prompt_dir() { + color=$bold_yellow + box="[|]" + info="\w" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" +} + +___brainy_prompt_scm() { + [ "${THEME_SHOW_SCM}" != "true" ] && return + color=$bold_green + box="$(scm_char) " + info="$(scm_prompt_info)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" +} + +___brainy_prompt_python() { + [ "${THEME_SHOW_PYTHON}" != "true" ] && return + color=$bold_yellow + box="[|]" + info="$(python_version_prompt)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_blue}" "${box}" +} + +___brainy_prompt_ruby() { + [ "${THEME_SHOW_RUBY}" != "true" ] && return + color=$bold_white + box="[|]" + info="rb-$(ruby_version_prompt)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_red}" "${box}" +} + +___brainy_prompt_todo() { + [ "${THEME_SHOW_TODO}" != "true" ] || + [ -z "$(which todo.sh)" ] && return + color=$bold_white + box="[|]" + info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }' )" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}" +} + +___brainy_prompt_clock() { + [ "${THEME_SHOW_CLOCK}" != "true" ] && return + color=$THEME_CLOCK_COLOR + box="[|]" + info="$(date +"${THEME_CLOCK_FORMAT}")" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_purple}" "${box}" +} + +___brainy_prompt_battery() { + [ ! -e $OSH/plugins/battery/battery.plugin.sh ] || + [ "${THEME_SHOW_BATTERY}" != "true" ] && return + info=$(battery_percentage) + color=$bold_green + if [ "$info" -lt 50 ]; then + color=$bold_yellow + elif [ "$info" -lt 25 ]; then + color=$bold_red + fi + box="[|]" + ac_adapter_connected && info+="+" + [ "$info" == "100+" ] && info="AC" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" +} + +___brainy_prompt_exitcode() { + [ "${THEME_SHOW_EXITCODE}" != "true" ] && return + color=$bold_purple + [ "$exitcode" -ne 0 ] && printf "%s|%s" "${color}" "${exitcode}" +} + +___brainy_prompt_char() { + color=$bold_white + prompt_char="${__BRAINY_PROMPT_CHAR_PS1}" + printf "%s|%s" "${color}" "${prompt_char}" +} + +######### +## cli ## +######### + +__brainy_show() { + typeset _seg=${1:-} + shift + export THEME_SHOW_${_seg}=true +} + +__brainy_hide() { + typeset _seg=${1:-} + shift + export THEME_SHOW_${_seg}=false +} + +_brainy_completion() { + local cur _action actions segments + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + _action="${COMP_WORDS[1]}" + actions="show hide" + segments="battery clock exitcode python ruby scm sudo todo" + case "${_action}" in + show) + COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) + return 0 + ;; + hide) + COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) + return 0 + ;; + esac + + COMPREPLY=( $(compgen -W "${actions}" -- "${cur}") ) + return 0 +} + +brainy() { + typeset action=${1:-} + shift + typeset segs=${*:-} + typeset func + case $action in + show) + func=__brainy_show;; + hide) + func=__brainy_hide;; + esac + for seg in ${segs}; do + seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]') + $func "${seg}" + done +} + +complete -F _brainy_completion brainy + +############### +## Variables ## +############### + +export SCM_THEME_PROMPT_PREFIX="" +export SCM_THEME_PROMPT_SUFFIX="" + +export RBENV_THEME_PROMPT_PREFIX="" +export RBENV_THEME_PROMPT_SUFFIX="" +export RBFU_THEME_PROMPT_PREFIX="" +export RBFU_THEME_PROMPT_SUFFIX="" +export RVM_THEME_PROMPT_PREFIX="" +export RVM_THEME_PROMPT_SUFFIX="" + +export SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +export SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" + +THEME_SHOW_SUDO=${THEME_SHOW_SUDO:-"true"} +THEME_SHOW_SCM=${THEME_SHOW_SCM:-"true"} +THEME_SHOW_RUBY=${THEME_SHOW_RUBY:-"false"} +THEME_SHOW_PYTHON=${THEME_SHOW_PYTHON:-"false"} +THEME_SHOW_CLOCK=${THEME_SHOW_CLOCK:-"true"} +THEME_SHOW_TODO=${THEME_SHOW_TODO:-"false"} +THEME_SHOW_BATTERY=${THEME_SHOW_BATTERY:-"false"} +THEME_SHOW_EXITCODE=${THEME_SHOW_EXITCODE:-"true"} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$bold_white"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"} + +__BRAINY_PROMPT_CHAR_PS1=${THEME_PROMPT_CHAR_PS1:-">"} +__BRAINY_PROMPT_CHAR_PS2=${THEME_PROMPT_CHAR_PS2:-"\\"} + +___BRAINY_TOP_LEFT=${___BRAINY_TOP_LEFT:-"user_info dir scm"} +___BRAINY_TOP_RIGHT=${___BRAINY_TOP_RIGHT:-"python ruby todo clock battery"} +___BRAINY_BOTTOM=${___BRAINY_BOTTOM:-"exitcode char"} + +############ +## Prompt ## +############ + +__brainy_ps1() { + printf "%s%s%s" "$(____brainy_top)" "$(____brainy_bottom)" "${normal}" +} + +__brainy_ps2() { + color=$bold_white + printf "%s%s%s" "${color}" "${__BRAINY_PROMPT_CHAR_PS2} " "${normal}" +} + +_brainy_prompt() { + exitcode="$?" + + PS1="$(__brainy_ps1)" + PS2="$(__brainy_ps2)" +} + +safe_append_prompt_command _brainy_prompt diff --git a/themes/brunton/brunton.theme.sh b/themes/brunton/brunton.theme.sh new file mode 100644 index 0000000..baa0578 --- /dev/null +++ b/themes/brunton/brunton.theme.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo " $(scm_char) (${white}$(scm_prompt_info)${normal})" + fi +} + +prompt() { + PS1="${white}${background_blue} \u${normal}${background_blue}@${red}${background_blue}\h $(clock_prompt) ${reset_color}${normal} $(battery_charge)\n${bold_black}${background_white} \w ${normal}$(scm_prompt)$(is_vim_shell)\n${white}>${normal} " +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$blue$background_white"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-" %H:%M:%S"} + +safe_append_prompt_command prompt diff --git a/themes/candy/candy.theme.sh b/themes/candy/candy.theme.sh new file mode 100644 index 0000000..f3f0abf --- /dev/null +++ b/themes/candy/candy.theme.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +function prompt_command() { + PS1="${green}\u@\h $(clock_prompt) ${reset_color}${white}\w${reset_color}$(scm_prompt_info)${blue} →${bold_blue} ${reset_color} "; +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$blue"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%I:%M:%S"} + +safe_append_prompt_command prompt_command diff --git a/themes/clean/clean.theme.sh b/themes/clean/clean.theme.sh new file mode 100644 index 0000000..b4cd7b5 --- /dev/null +++ b/themes/clean/clean.theme.sh @@ -0,0 +1,20 @@ +# git theming +ZSH_THEME_GIT_PROMPT_PREFIX="${bold_blue}(${yellow}%B" +ZSH_THEME_GIT_PROMPT_SUFFIX="%b${bold_blue})${reset_color} " +ZSH_THEME_GIT_PROMPT_CLEAN="" +ZSH_THEME_GIT_PROMPT_DIRTY="${bold_red}✗" + + +# LS colors, made with http://geoff.greer.fm/lscolors/ +export LSCOLORS="Gxfxcxdxbxegedabagacad" +export LS_COLORS='no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:' + +function prompt_command() { + + if [ "$(whoami)" = root ]; then no_color=$red; else no_color=$white; fi + + PS1="${no_color}\u${reset_color}:${blue}\W/${reset_color} \[\$(scm_prompt_info)\]$ " + RPROMPT='[\t]' +} + +safe_append_prompt_command prompt_command diff --git a/themes/colours.theme.sh b/themes/colours.theme.sh new file mode 100644 index 0000000..697d0ef --- /dev/null +++ b/themes/colours.theme.sh @@ -0,0 +1,271 @@ +#!/usr/bin/env bash + +function __ { + echo "$@" +} + +function __make_ansi { + next=$1; shift + echo "\[\e[$(__$next $@)m\]" +} + +function __make_echo { + next=$1; shift + echo "\033[$(__$next $@)m" +} + + +function __reset { + next=$1; shift + out="$(__$next $@)" + echo "0${out:+;${out}}" +} + +function __bold { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}1" +} + +function __faint { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}2" +} + +function __italic { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}3" +} + +function __underline { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}4" +} + +function __negative { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}7" +} + +function __crossed { + next=$1; shift + out="$(__$next $@)" + echo "${out:+${out};}8" +} + + +function __color_normal_fg { + echo "3$1" +} + +function __color_normal_bg { + echo "4$1" +} + +function __color_bright_fg { + echo "9$1" +} + +function __color_bright_bg { + echo "10$1" +} + + +function __color_black { + echo "0" +} + +function __color_red { + echo "1" +} + +function __color_green { + echo "2" +} + +function __color_yellow { + echo "3" +} + +function __color_blue { + echo "4" +} + +function __color_magenta { + echo "5" +} + +function __color_cyan { + echo "6" +} + +function __color_white { + echo "7" +} + +function __color_rgb { + r=$1 && g=$2 && b=$3 + [[ r == g && g == b ]] && echo $(( $r / 11 + 232 )) && return # gray range above 232 + echo "8;5;$(( ($r * 36 + $b * 6 + $g) / 51 + 16 ))" +} + +function __color { + color=$1; shift + case "$1" in + fg|bg) side="$1"; shift ;; + *) side=fg;; + esac + case "$1" in + normal|bright) mode="$1"; shift;; + *) mode=normal;; + esac + [[ $color == "rgb" ]] && rgb="$1 $2 $3"; shift 3 + + next=$1; shift + out="$(__$next $@)" + echo "$(__color_${mode}_${side} $(__color_${color} $rgb))${out:+;${out}}" +} + + +function __black { + echo "$(__color black $@)" +} + +function __red { + echo "$(__color red $@)" +} + +function __green { + echo "$(__color green $@)" +} + +function __yellow { + echo "$(__color yellow $@)" +} + +function __blue { + echo "$(__color blue $@)" +} + +function __magenta { + echo "$(__color magenta $@)" +} + +function __cyan { + echo "$(__color cyan $@)" +} + +function __white { + echo "$(__color white $@)" +} + +function __rgb { + echo "$(__color rgb $@)" +} + + +function __color_parse { + next=$1; shift + echo "$(__$next $@)" +} + +function color { + echo "$(__color_parse make_ansi $@)" +} + +function echo_color { + echo "$(__color_parse make_echo $@)" +} + + +black="\[\e[0;30m\]" +red="\[\e[0;31m\]" +green="\[\e[0;32m\]" +yellow="\[\e[0;33m\]" +blue="\[\e[0;34m\]" +purple="\[\e[0;35m\]" +cyan="\[\e[0;36m\]" +white="\[\e[0;37m\]" +orange="\[\e[0;91m\]" + +bold_black="\[\e[30;1m\]" +bold_red="\[\e[31;1m\]" +bold_green="\[\e[32;1m\]" +bold_yellow="\[\e[33;1m\]" +bold_blue="\[\e[34;1m\]" +bold_purple="\[\e[35;1m\]" +bold_cyan="\[\e[36;1m\]" +bold_white="\[\e[37;1m\]" +bold_orange="\[\e[91;1m\]" + +underline_black="\[\e[30;4m\]" +underline_red="\[\e[31;4m\]" +underline_green="\[\e[32;4m\]" +underline_yellow="\[\e[33;4m\]" +underline_blue="\[\e[34;4m\]" +underline_purple="\[\e[35;4m\]" +underline_cyan="\[\e[36;4m\]" +underline_white="\[\e[37;4m\]" +underline_orange="\[\e[91;4m\]" + +background_black="\[\e[40m\]" +background_red="\[\e[41m\]" +background_green="\[\e[42m\]" +background_yellow="\[\e[43m\]" +background_blue="\[\e[44m\]" +background_purple="\[\e[45m\]" +background_cyan="\[\e[46m\]" +background_white="\[\e[47;1m\]" +background_orange="\[\e[101m\]" + +normal="\[\e[0m\]" +reset_color="\[\e[39m\]" + +# These colors are meant to be used with `echo -e` +echo_black="\033[0;30m" +echo_red="\033[0;31m" +echo_green="\033[0;32m" +echo_yellow="\033[0;33m" +echo_blue="\033[0;34m" +echo_purple="\033[0;35m" +echo_cyan="\033[0;36m" +echo_white="\033[0;37;1m" +echo_orange="\033[0;91m" + +echo_bold_black="\033[30;1m" +echo_bold_red="\033[31;1m" +echo_bold_green="\033[32;1m" +echo_bold_yellow="\033[33;1m" +echo_bold_blue="\033[34;1m" +echo_bold_purple="\033[35;1m" +echo_bold_cyan="\033[36;1m" +echo_bold_white="\033[37;1m" +echo_bold_orange="\033[91;1m" + +echo_underline_black="\033[30;4m" +echo_underline_red="\033[31;4m" +echo_underline_green="\033[32;4m" +echo_underline_yellow="\033[33;4m" +echo_underline_blue="\033[34;4m" +echo_underline_purple="\033[35;4m" +echo_underline_cyan="\033[36;4m" +echo_underline_white="\033[37;4m" +echo_underline_orange="\033[91;4m" + +echo_background_black="\033[40m" +echo_background_red="\033[41m" +echo_background_green="\033[42m" +echo_background_yellow="\033[43m" +echo_background_blue="\033[44m" +echo_background_purple="\033[45m" +echo_background_cyan="\033[46m" +echo_background_white="\033[47;1m" +echo_background_orange="\033[101m" + +echo_normal="\033[0m" +echo_reset_color="\033[39m" + diff --git a/themes/cooperkid/cooperkid.theme.sh b/themes/cooperkid/cooperkid.theme.sh new file mode 100644 index 0000000..1ffb95a --- /dev/null +++ b/themes/cooperkid/cooperkid.theme.sh @@ -0,0 +1,39 @@ +# ------------------------------------------------------------------# +# FILE: cooperkid.zsh-theme # +# BY: Alfredo Bejarano # +# BASED ON: Mr Briggs by Matt Brigg (matt@mattbriggs.net) # +# ------------------------------------------------------------------# + +SCM_THEME_PROMPT_DIRTY="${red} ✗${reset_color}" +SCM_THEME_PROMPT_AHEAD="${yellow} ↑${reset_color}" +SCM_THEME_PROMPT_CLEAN="${green} ✓${reset_color}" +SCM_THEME_PROMPT_PREFIX=" " +SCM_THEME_PROMPT_SUFFIX="" +GIT_SHA_PREFIX="${blue}" +GIT_SHA_SUFFIX="${reset_color}" + +function rvm_version_prompt { + if which rvm &> /dev/null; then + rvm=$(rvm-prompt) || return + if [ -n "$rvm" ]; then + echo -e "$rvm" + fi + fi +} + +function git_short_sha() { + SHA=$(git rev-parse --short HEAD 2> /dev/null) && echo "$GIT_SHA_PREFIX$SHA$GIT_SHA_SUFFIX" +} + +function prompt() { + local return_status="" + local ruby="${red}$(ruby_version_prompt)${reset_color}" + local user_host="${green}\h @ \w${reset_color}" + local git_branch="$(git_short_sha)${cyan}$(scm_prompt_info)${reset_color}" + local prompt_symbol=' ' + local prompt_char="${purple}>_${reset_color} " + + PS1="\n${user_host}${prompt_symbol}${ruby} ${git_branch} ${return_status}\n${prompt_char}" +} + +safe_append_prompt_command prompt diff --git a/themes/cupcake/cupcake.theme.sh b/themes/cupcake/cupcake.theme.sh new file mode 100644 index 0000000..852f978 --- /dev/null +++ b/themes/cupcake/cupcake.theme.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Emoji-based theme to display source control management and +# virtual environment info beside the ordinary bash prompt. + +# Theme inspired by: +# - Naming your Terminal tabs in OSX Lion - http://thelucid.com/2012/01/04/naming-your-terminal-tabs-in-osx-lion/ +# - Bash_it sexy theme + +# Demo: +# ┌ⓔ virtualenv 💁user @ 💻 host in 📁directory on 🌿branch {1} ↑1 ↓1 +1 •1 ⌀1 ✗ +# └❯ cd .bash-it/themes/cupcake + +# virtualenv prompts +VIRTUALENV_CHAR="ⓔ " +VIRTUALENV_THEME_PROMPT_PREFIX="" +VIRTUALENV_THEME_PROMPT_SUFFIX="" + +# SCM prompts +SCM_NONE_CHAR="" +SCM_GIT_CHAR="[±] " +SCM_GIT_BEHIND_CHAR="${red}↓${normal}" +SCM_GIT_AHEAD_CHAR="${bold_green}↑${normal}" +SCM_GIT_UNTRACKED_CHAR="⌀" +SCM_GIT_UNSTAGED_CHAR="${bold_yellow}•${normal}" +SCM_GIT_STAGED_CHAR="${bold_green}+${normal}" + +SCM_THEME_PROMPT_DIRTY="" +SCM_THEME_PROMPT_CLEAN="" +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +# Git status prompts +GIT_THEME_PROMPT_DIRTY=" ${red}✗${normal}" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +GIT_THEME_PROMPT_PREFIX="" +GIT_THEME_PROMPT_SUFFIX="" + +# ICONS ======================================================================= + +icon_start="┌" +icon_user="💁 " +icon_host=" @ 💻 " +icon_directory=" in 📁 " +icon_branch="🌿" +icon_end="└❯ " + +# extra spaces ensure legiblity in prompt + +# FUNCTIONS =================================================================== + +# Display virtual environment info +function virtualenv_prompt { + if [[ -n "$VIRTUAL_ENV" ]]; then + virtualenv=`basename "$VIRTUAL_ENV"` + echo -e "$VIRTUALENV_CHAR$virtualenv " + fi +} + +# Rename tab +function tabname { + printf "\e]1;$1\a" +} + +# Rename window +function winname { + printf "\e]2;$1\a" +} + +# PROMPT OUTPUT =============================================================== + +# Displays the current prompt +function prompt_command() { + PS1="\n${icon_start}$(virtualenv_prompt)${icon_user}${bold_red}\u${normal}${icon_host}${bold_cyan}\h${normal}${icon_directory}${bold_purple}\W${normal}\$([[ -n \$(git branch 2> /dev/null) ]] && echo \" on ${icon_branch} \")${white}$(scm_prompt_info)${normal}\n${icon_end}" + PS2="${icon_end}" +} + +# Runs prompt (this bypasses oh-my-bash $PROMPT setting) +safe_append_prompt_command prompt_command diff --git a/themes/demula/demula.theme.sh b/themes/demula/demula.theme.sh new file mode 100644 index 0000000..ce79be7 --- /dev/null +++ b/themes/demula/demula.theme.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +# Theme inspired on: +# - Ronacher's dotfiles (mitsuhikos) - http://github.com/mitsuhiko/dotfiles/tree/master/bash/ +# - Glenbot - http://theglenbot.com/custom-bash-shell-for-development/ +# - My extravagant zsh - http://stevelosh.com/blog/2010/02/my-extravagant-zsh-prompt/ +# - Monokai colors - http://monokai.nl/blog/2006/07/15/textmate-color-theme/ +# - Bash_it modern theme +# +# Screenshot: http://goo.gl/VCmX5 +# by Jesus de Mula + +# For the real Monokai colors you should add these to your .XDefaults or +# terminal configuration: +#! ----------------------------------------------------------- TERMINAL COLORS +#! monokai - http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/ +#*background: #272822 +#*foreground: #E2DA6E +#*color0: black +#! mild red +#*color1: #CD0000 +#! light green +#*color2: #A5E02D +#! orange (yellow) +#*color3: #FB951F +#! "dark" blue +#*color4: #076BCC +#! hot pink +#*color5: #F6266C +#! cyan +#*color6: #64D9ED +#! gray +#*color7: #E5E5E5 + +# ----------------------------------------------------------------- COLOR CONF +D_DEFAULT_COLOR="${normal}" +D_INTERMEDIATE_COLOR="${white}" +D_USER_COLOR="${purple}" +D_SUPERUSER_COLOR="${red}" +D_MACHINE_COLOR="${cyan}" +D_DIR_COLOR="${green}" +D_SCM_COLOR="${yellow}" +D_BRANCH_COLOR="${yellow}" +D_CHANGES_COLOR="${white}" +D_CMDFAIL_COLOR="${red}" +D_VIMSHELL_COLOR="${cyan}" + +# ------------------------------------------------------------------ FUNCTIONS +case $TERM in + xterm*) + TITLEBAR="\033]0;\w\007" + ;; + *) + TITLEBAR="" + ;; +esac + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ]; + then + echo "${D_INTERMEDIATE_COLOR}on ${D_VIMSHELL_COLOR}\ +vim shell${D_DEFAULT_COLOR} " + fi +} + +mitsuhikos_lastcommandfailed() { + code=$? + if [ $code != 0 ]; + then + echo "${D_INTERMEDIATE_COLOR}exited ${D_CMDFAIL_COLOR}\ +$code ${D_DEFAULT_COLOR}" + fi +} + +# vcprompt for scm instead of oh-my-bash default +demula_vcprompt() { + if [ ! -z "$VCPROMPT_EXECUTABLE" ]; + then + local D_VCPROMPT_FORMAT="on ${D_SCM_COLOR}%s${D_INTERMEDIATE_COLOR}:\ +${D_BRANCH_COLOR}%b %r ${D_CHANGES_COLOR}%m%u ${D_DEFAULT_COLOR}" + $VCPROMPT_EXECUTABLE -f "$D_VCPROMPT_FORMAT" + fi +} + +# checks if the plugin is installed before calling battery_charge +safe_battery_charge() { + if [ -e "${OSH}/plugins/battery/battery.plugin.sh" ]; + then + battery_charge + fi +} + +# -------------------------------------------------------------- PROMPT OUTPUT +prompt() { + local LAST_COMMAND_FAILED=$(mitsuhikos_lastcommandfailed) + local SAVE_CURSOR='\033[s' + local RESTORE_CURSOR='\033[u' + local MOVE_CURSOR_RIGHTMOST='\033[500C' + local MOVE_CURSOR_5_LEFT='\033[5D' + + if [ $(uname) = "Linux" ]; + then + PS1="${TITLEBAR} +${SAVE_CURSOR}${MOVE_CURSOR_RIGHTMOST}${MOVE_CURSOR_5_LEFT}\ +$(safe_battery_charge)${RESTORE_CURSOR}\ +${D_USER_COLOR}\u ${D_INTERMEDIATE_COLOR}\ +at ${D_MACHINE_COLOR}\h ${D_INTERMEDIATE_COLOR}\ +in ${D_DIR_COLOR}\w ${D_INTERMEDIATE_COLOR}\ +${LAST_COMMAND_FAILED}\ +$(demula_vcprompt)\ +$(is_vim_shell) +${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" + else + PS1="${TITLEBAR} +${D_USER_COLOR}\u ${D_INTERMEDIATE_COLOR}\ +at ${D_MACHINE_COLOR}\h ${D_INTERMEDIATE_COLOR}\ +in ${D_DIR_COLOR}\w ${D_INTERMEDIATE_COLOR}\ +${LAST_COMMAND_FAILED}\ +$(demula_vcprompt)\ +$(is_vim_shell)\ +$(safe_battery_charge) +${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" + fi + + PS2="${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" +} + +# Runs prompt (this bypasses oh-my-bash $PROMPT setting) +safe_append_prompt_command prompt diff --git a/themes/dos/dos.theme.sh b/themes/dos/dos.theme.sh new file mode 100644 index 0000000..17f0cff --- /dev/null +++ b/themes/dos/dos.theme.sh @@ -0,0 +1 @@ +PROMPT="\w>>" diff --git a/themes/doubletime/doubletime.theme.sh b/themes/doubletime/doubletime.theme.sh new file mode 100644 index 0000000..3f68666 --- /dev/null +++ b/themes/doubletime/doubletime.theme.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY='' +SCM_THEME_PROMPT_CLEAN='' +SCM_GIT_CHAR="${bold_cyan}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" +if [ ! -z $RVM_THEME_PROMPT_COLOR ]; then + RVM_THEME_PROMPT_COLOR=$(eval echo $`echo ${RVM_THEME_PROMPT_COLOR}`); +else + RVM_THEME_PROMPT_COLOR="${red}" +fi +RVM_THEME_PROMPT_PREFIX="(${RVM_THEME_PROMPT_COLOR}rb${normal}: " +RVM_THEME_PROMPT_SUFFIX=") " +if [ ! -z $VIRTUALENV_THEME_PROMPT_COLOR ]; then + VIRTUALENV_THEME_PROMPT_COLOR=$(eval echo $`echo ${VIRTUALENV_THEME_PROMPT_COLOR}`); +else + VIRTUALENV_THEME_PROMPT_COLOR="${green}" +fi +VIRTUALENV_THEME_PROMPT_PREFIX="(${VIRTUALENV_THEME_PROMPT_COLOR}py${normal}: " +VIRTUALENV_THEME_PROMPT_SUFFIX=") " + +if [ ! -z $THEME_PROMPT_HOST_COLOR ]; then + THEME_PROMPT_HOST_COLOR=$(eval echo $`echo ${THEME_PROMPT_HOST_COLOR}`); +else + THEME_PROMPT_HOST_COLOR="$blue" +fi + +doubletime_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ]; then + return + elif [ $CHAR = $SCM_GIT_CHAR ]; then + echo "$(git_prompt_status)" + else + echo "[$(scm_prompt_info)]" + fi +} + +function prompt_setter() { + # Save history + history -a + history -c + history -r + PS1=" +$(clock_prompt) $(scm_char) [${THEME_PROMPT_HOST_COLOR}\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt)$(ruby_version_prompt)\w +$(doubletime_scm_prompt)$reset_color $ " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter + +git_prompt_status() { + local git_status_output + git_status_output=$(git status 2> /dev/null ) + if [ -n "$(echo $git_status_output | grep 'Changes not staged')" ]; then + git_status="${bold_red}$(scm_prompt_info) ✗" + elif [ -n "$(echo $git_status_output | grep 'Changes to be committed')" ]; then + git_status="${bold_yellow}$(scm_prompt_info) ^" + elif [ -n "$(echo $git_status_output | grep 'Untracked files')" ]; then + git_status="${bold_cyan}$(scm_prompt_info) +" + elif [ -n "$(echo $git_status_output | grep 'nothing to commit')" ]; then + git_status="${bold_green}$(scm_prompt_info) ${green}✓" + else + git_status="$(scm_prompt_info)" + fi + echo "[$git_status${normal}]" + +} diff --git a/themes/doubletime_multiline/doubletime_multiline.theme.sh b/themes/doubletime_multiline/doubletime_multiline.theme.sh new file mode 100644 index 0000000..68a0c0c --- /dev/null +++ b/themes/doubletime_multiline/doubletime_multiline.theme.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +source "$OSH/themes/doubletime/doubletime.theme.sh" + +function prompt_setter() { + # Save history + history -a + history -c + history -r + PS1=" +$(clock_prompt) $(scm_char) [$THEME_PROMPT_HOST_COLOR\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt)$(ruby_version_prompt) +\w +$(doubletime_scm_prompt)$reset_color $ " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter diff --git a/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.sh b/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.sh new file mode 100644 index 0000000..df379bd --- /dev/null +++ b/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +source "$OSH/themes/doubletime/doubletime.theme.sh" + +function prompt_setter() { + # Save history + history -a + history -c + history -r + PS1=" +$(clock_prompt) $(scm_char) [$THEME_PROMPT_HOST_COLOR\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt) +\w +$(doubletime_scm_prompt)$reset_color $ " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter diff --git a/themes/dulcie/dulcie.theme.sh b/themes/dulcie/dulcie.theme.sh new file mode 100644 index 0000000..a83b62f --- /dev/null +++ b/themes/dulcie/dulcie.theme.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +# Simplistic one-liner theme to display source control management info beside +# the ordinary Linux bash prompt. +# +# Demo: +# +# [ritola@localhost ~]$ cd .bash-it/themes/dulcie +# [ritola@localhost |master ✓| dulcie]$ # This is single line mode +# |bash-it|± master ✓| +# [ritola@localhost dulcie]$ # In multi line, the SCM info is in the separate line +# +# Configuration. Change these by adding them in your .bash_profile + +DULCIE_COLOR=${DULCIE_COLOR:=1} # 0 = monochrome, 1 = colorful +DULCIE_MULTILINE=${DULCIE_MULTILINE:=1} # 0 = Single line, 1 = SCM in separate line + +dulcie_color() { + echo -en "\[\e[38;5;${1}m\]" +} + +dulcie_background() { + echo -en "\[\e[48;5;${1}m\]" +} + +dulcie_prompt() { + color_user_root=$(dulcie_color 169) + color_user_nonroot="${green}" + color_host_local=$(dulcie_color 230) + color_host_remote=$(dulcie_color 214) + color_rootdir=$(dulcie_color 117) + color_workingdir=$(dulcie_color 117) + background_scm=$(dulcie_background 238) + + SCM_THEME_ROOT_SUFFIX="|$(scm_char) " + + # Set colors + if [ "${DULCIE_COLOR}" -eq "1" ]; then + if [[ $EUID -ne 0 ]]; then + color_user="${color_user_nonroot}" + else + color_user="${color_user_root}" + fi + + if [[ -n "${SSH_CLIENT}" ]]; then + color_host="${color_host_remote}" + else + color_host="${color_host_local}" + fi + + DULCIE_USER="${color_user}\u${reset_color}" + DULCIE_HOST="${color_host}\h${reset_color}" + DULCIE_WORKINGDIR="${color_workingdir}\W${reset_color}" + DULCIE_PROMPTCHAR="${color_user}"'\$'"${reset_color}" + + SCM_THEME_PROMPT_DIRTY=" ${red}✗${reset_color}" + SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" + DULCIE_SCM_BACKGROUND="${background_scm}" + DULCIE_SCM_DIR_COLOR="${color_rootdir}" + SCM_THEME_ROOT_SUFFIX="${reset_color}${SCM_THEME_ROOT_SUFFIX}" + SCM_THEME_PROMPT_DIRTY=" $(dulcie_color 1)✗${reset_color}" + SCM_THEME_PROMPT_CLEAN=" $(dulcie_color 10)✓${reset_color}" + else + DULCIE_USER='\u' + DULCIE_HOST='\h' + DULCIE_WORKINGDIR='\W' + DULCIE_PROMPTCHAR='\$' + + DULCIE_SCM_BACKGROUND="" + DULCIE_SCM_DIR_COLOR="" + SCM_THEME_DIR_COLOR="" + SCM_THEME_PROMPT_DIRTY=" ✗" + SCM_THEME_PROMPT_CLEAN=" ✓" + fi + + # Change terminal title + printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}" + + # Open the new terminal in the same directory + declare -f __vte_osc7 > /dev/null && __vte_osc7 + + PS1="${reset_color}[${DULCIE_USER}@${DULCIE_HOST}$(scm_prompt_info)${reset_color} ${DULCIE_WORKINGDIR}]" + if [[ "${DULCIE_MULTILINE}" -eq "1" ]]; then + PS1="${reset_color}[${DULCIE_USER}@${DULCIE_HOST}${reset_color} ${DULCIE_WORKINGDIR}]" + if [[ "$(scm_prompt_info)" ]]; then + SCM_THEME_PROMPT_PREFIX="${DULCIE_SCM_BACKGROUND}|${DULCIE_SCM_DIR_COLOR}" + SCM_THEME_PROMPT_SUFFIX="|${normal}" + PS1="$(scm_prompt_info)\n${PS1}" + fi + else + SCM_THEME_PROMPT_PREFIX=" ${DULCIE_SCM_BACKGROUND}|${DULCIE_SCM_DIR_COLOR}" + SCM_THEME_PROMPT_SUFFIX="|${normal}" + PS1="${reset_color}[${DULCIE_USER}@${DULCIE_HOST}$(scm_prompt_info)${reset_color} ${DULCIE_WORKINGDIR}]" + fi + PS1="${PS1}${DULCIE_PROMPTCHAR} " +} + +safe_append_prompt_command dulcie_prompt diff --git a/themes/duru/duru.theme.sh b/themes/duru/duru.theme.sh new file mode 100644 index 0000000..6928410 --- /dev/null +++ b/themes/duru/duru.theme.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_PREFIX="${cyan} on ${green}" +SCM_THEME_PROMPT_SUFFIX="" +SCM_THEME_PROMPT_DIRTY=" ${red}with changes" +SCM_THEME_PROMPT_CLEAN="" + +venv() { + if [ ! -z "$VIRTUAL_ENV" ] + then + local env=$VIRTUAL_ENV + echo "${gray} in ${orange}${env##*/} " + fi +} + +last_two_dirs() { + pwd|rev|awk -F / '{print $1,$2}'|rev|sed s_\ _/_|sed "s|$(sed 's,\/,,'<<<$HOME)|~|g" +} + +prompt() { + PS1="${yellow}# ${reset_color}$(last_two_dirs)$(scm_prompt_info)${reset_color}$(venv)${reset_color} ${cyan}\n> ${reset_color}" +} + +safe_append_prompt_command prompt diff --git a/themes/emperor/emperor.theme.sh b/themes/emperor/emperor.theme.sh new file mode 100644 index 0000000..e3f2df8 --- /dev/null +++ b/themes/emperor/emperor.theme.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="|" + +function get_hour_color { + hour_color=$red + min=$(date +%M) + if [ "$min" -lt "15" ]; then + hour_color=$white + elif [ "$min" -lt "30" ]; then + hour_color=$green + elif [ "$min" -lt "45" ]; then + hour_color=$yellow + else + hour_color=$red + fi + echo "$hour_color" +} + +__emperor_clock() { + THEME_CLOCK_COLOR=$(get_hour_color) + clock_prompt +} + +function prompt_command() { + PS1="\n$(__emperor_clock)${purple}\h ${reset_color}in ${prompt_color}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} " +} + +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H "} + +safe_append_prompt_command prompt_command diff --git a/themes/envy/envy.theme.sh b/themes/envy/envy.theme.sh new file mode 100644 index 0000000..277e375 --- /dev/null +++ b/themes/envy/envy.theme.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +function prompt_command() { + PS1="\n${yellow}$(ruby_version_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}→${reset_color} " +} + +safe_append_prompt_command prompt_command diff --git a/themes/font/font.theme.sh b/themes/font/font.theme.sh new file mode 100644 index 0000000..5443690 --- /dev/null +++ b/themes/font/font.theme.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# +# One line prompt showing the following configurable information +# for git: +# time (virtual_env) username@hostname pwd git_char|git_branch git_dirty_status|→ +# +# The → arrow shows the exit status of the last command: +# - bold green: 0 exit status +# - bold red: non-zero exit status +# +# Example outside git repo: +# 07:45:05 user@host ~ → +# +# Example inside clean git repo: +# 07:45:05 user@host .oh-my-bash ±|master|→ +# +# Example inside dirty git repo: +# 07:45:05 user@host .oh-my-bash ±|master ✗|→ +# +# Example with virtual environment: +# 07:45:05 (venv) user@host ~ → +# + +SCM_NONE_CHAR='' +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN="" +SCM_THEME_PROMPT_PREFIX="${green}|" +SCM_THEME_PROMPT_SUFFIX="${green}|" +SCM_GIT_SHOW_MINIMAL_INFO=true + +CLOCK_THEME_PROMPT_PREFIX='' +CLOCK_THEME_PROMPT_SUFFIX=' ' +THEME_SHOW_CLOCK=true +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$bold_blue"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%I:%M:%S"} + +VIRTUALENV_THEME_PROMPT_PREFIX='(' +VIRTUALENV_THEME_PROMPT_SUFFIX=') ' + +function prompt_command() { + # This needs to be first to save last command return code + local RC="$?" + + hostname="${bold_black}\u@\h" + virtualenv="${white}$(virtualenv_prompt)" + + # Set return status color + if [[ ${RC} == 0 ]]; then + ret_status="${bold_green}" + else + ret_status="${bold_red}" + fi + + # Append new history lines to history file + history -a + + PS1="$(clock_prompt)${virtualenv}${hostname} ${bold_cyan}\W $(scm_prompt_char_info)${ret_status}→ ${normal}" +} + +safe_append_prompt_command prompt_command diff --git a/themes/gallifrey/gallifrey.theme.sh b/themes/gallifrey/gallifrey.theme.sh new file mode 100644 index 0000000..ddb8977 --- /dev/null +++ b/themes/gallifrey/gallifrey.theme.sh @@ -0,0 +1,41 @@ +# scm theming +SCM_THEME_PROMPT_PREFIX="${yellow}(" +SCM_THEME_PROMPT_SUFFIX=")${normal}" + +SCM_THEME_PROMPT_DIRTY="*" +SCM_THEME_PROMPT_CLEAN="" +SCM_GIT_CHAR="g" +SCM_SVN_CHAR="s" +SCM_HG_CHAR="h" + +### TODO: openSUSE has already colors enabled, check if those differs from stock +# LS colors, made with http://geoff.greer.fm/lscolors/ +# export LSCOLORS="Gxfxcxdxbxegedabagacad" +# export LS_COLORS='no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:' + +scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "$(scm_prompt_info) " + fi +} + +pure_prompt() { + ps_host="${green}\h${normal}"; + ps_user_mark="${bold}\$${normal}"; + ps_root_mark="${normal}§" + ps_path="${normal}\w"; + + # make it work + case $(id -u) in + 0) PS1="$ps_host $ps_path $(scm_prompt)$ps_root_mark " + ;; + *) PS1="$ps_host $ps_path $(scm_prompt)$ps_user_mark " + ;; + esac +} + +safe_append_prompt_command pure_prompt diff --git a/themes/hawaii50/hawaii50.theme.sh b/themes/hawaii50/hawaii50.theme.sh new file mode 100644 index 0000000..eaa6b1e --- /dev/null +++ b/themes/hawaii50/hawaii50.theme.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# +# This theme was obviously inspired a lot by +# +# - Demula theme +# +# which in itself was inspired by : +# +# - Ronacher's dotfiles (mitsuhikos) - http://github.com/mitsuhiko/dotfiles/tree/master/bash/ +# - Glenbot - http://theglenbot.com/custom-bash-shell-for-development/ +# - My extravagant zsh - http://stevelosh.com/blog/2010/02/my-extravagant-zsh-prompt/ +# - Monokai colors - http://monokai.nl/blog/2006/07/15/textmate-color-theme/ +# - Bash_it modern theme +# +# Hawaii50 theme supports : +# +# - configurable directory length +# - hg, svn, git detection (I work in all of them) +# - virtualenv, rvm + gemsets +# +# Screenshot: http://i.imgur.com/4IAMJ.png +# +# by Ryan Kanno +# +# And yes, we code out in Hawaii. :D +# +# Note: I also am really new to this bash scripting game, so if you see things +# that are flat out wrong, or if you think of something neat, just send a pull +# request. This probably only works on a Mac - as some functions are OS +# specific like getting ip, etc. +# + +# IMPORTANT THINGS TO CHANGE ================================================== + +# Show IP in prompt +# One thing to be weary about if you have slow Internets +IP_ENABLED=1 + +# virtual prompts +VIRTUAL_PROMPT_ENABLED=1 + +# COLORS ====================================================================== +ORANGE='\[\e[0;33m\]' + +DEFAULT_COLOR="${white}" + +USER_COLOR="${purple}" +SUPERUSER_COLOR="${red}" +MACHINE_COLOR=$ORANGE +IP_COLOR=$ORANGE +DIRECTORY_COLOR="${green}" + +VE_COLOR="${cyan}" +RVM_COLOR="${cyan}" + +REF_COLOR="${purple}" + +# SCM prompts +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_THEME_PROMPT_PREFIX=' on ' +SCM_THEME_PROMPT_SUFFIX='' + +# rvm prompts +RVM_THEME_PROMPT_PREFIX='' +RVM_THEME_PROMPT_SUFFIX='' + +# virtualenv prompts +VIRTUALENV_THEME_PROMPT_PREFIX='' +VIRTUALENV_THEME_PROMPT_SUFFIX='' + +VIRTUAL_THEME_PROMPT_PREFIX=' using ' +VIRTUAL_THEME_PROMPT_SUFFIX='' + +# Max length of PWD to display +MAX_PWD_LENGTH=20 + +# Max length of Git Hex to display +MAX_GIT_HEX_LENGTH=5 + +# IP address +IP_SEPARATOR=', ' + +# FUNCS ======================================================================= + +function get_ip_info { + myip=$(curl -s checkip.dyndns.org | grep -Eo '[0-9\.]+') + echo -e "$(ips | sed -e :a -e '$!N;s/\n/${IP_SEPARATOR}/;ta' | sed -e 's/127\.0\.0\.1\${IP_SEPARATOR}//g'), ${myip}" +} + +# Displays ip prompt +function ip_prompt_info() { + if [[ $IP_ENABLED == 1 ]]; then + echo -e " ${DEFAULT_COLOR}(${IP_COLOR}$(get_ip_info)${DEFAULT_COLOR})" + fi +} + +# Displays virtual info prompt (virtualenv/rvm) +function virtual_prompt_info() { + local virtual_env_info=$(virtualenv_prompt) + local rvm_info=$(ruby_version_prompt) + local virtual_prompt="" + + local prefix=${VIRTUAL_THEME_PROMPT_PREFIX} + local suffix=${VIRTUAL_THEME_PROMPT_SUFFIX} + + # If no virtual info, just return + [[ -z "$virtual_env_info" && -z "$rvm_info" ]] && return + + # If virtual_env info present, append to prompt + [[ -n "$virtual_env_info" ]] && virtual_prompt="virtualenv: ${VE_COLOR}$virtual_env_info${DEFAULT_COLOR}" + + if [[ -n "$rvm_info" ]] + then + [[ -n "$virtual_env_info" ]] && virtual_prompt="$virtual_prompt, " + virtual_prompt="${virtual_prompt}rvm: ${RVM_COLOR}$rvm_info${DEFAULT_COLOR}" + fi + echo -e "$prefix$virtual_prompt$suffix" +} + +# Parse git info +function git_prompt_info() { + if [[ -n $(git status -s 2> /dev/null |grep -v ^# |grep -v "working directory clean") ]]; then + state=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + state=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + prefix=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + suffix=${GIT_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + ref=$(git symbolic-ref HEAD 2> /dev/null) || return + commit_id=$(git rev-parse HEAD 2>/dev/null) || return + + echo -e "$prefix${REF_COLOR}${ref#refs/heads/}${DEFAULT_COLOR}:${commit_id:0:$MAX_GIT_HEX_LENGTH}$state$suffix" +} + +# Parse hg info +function hg_prompt_info() { + if [[ -n $(hg status 2> /dev/null) ]]; then + state=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + state=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + prefix=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + suffix=${HG_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + branch=$(hg summary 2> /dev/null | grep branch | awk '{print $2}') + changeset=$(hg summary 2> /dev/null | grep parent | awk '{print $2}') + + echo -e "$prefix${REF_COLOR}${branch}${DEFAULT_COLOR}:${changeset#*:}$state$suffix" +} + +# Parse svn info +function svn_prompt_info() { + if [[ -n $(svn status --ignore-externals -q 2> /dev/null) ]]; then + state=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + state=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + prefix=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + suffix=${SVN_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + ref=$(svn info 2> /dev/null | awk -F/ '/^URL:/ { for (i=0; i<=NF; i++) { if ($i == "branches" || $i == "tags" ) { print $(i+1); break }; if ($i == "trunk") { print $i; break } } }') || return + [[ -z $ref ]] && return + + revision=$(svn info 2> /dev/null | sed -ne 's#^Revision: ##p' ) + + echo -e "$prefix${REF_COLOR}$ref${DEFAULT_COLOR}:$revision$state$suffix" +} + +# Displays last X characters of pwd +function limited_pwd() { + + # Replace $HOME with ~ if possible + RELATIVE_PWD=${PWD/#$HOME/\~} + + local offset=$((${#RELATIVE_PWD}-$MAX_PWD_LENGTH)) + + if [ $offset -gt "0" ] + then + local truncated_symbol="..." + TRUNCATED_PWD=${RELATIVE_PWD:$offset:$MAX_PWD_LENGTH} + echo -e "${truncated_symbol}/${TRUNCATED_PWD#*/}" + else + echo -e "${RELATIVE_PWD}" + fi +} + +# Displays the current prompt +function prompt() { + local UC=$USER_COLOR + [ $UID -eq "0" ] && UC=$SUPERUSER_COLOR + + if [[ $VIRTUAL_PROMPT_ENABLED == 1 ]]; then + PS1="$(scm_char) ${UC}\u ${DEFAULT_COLOR}at ${MACHINE_COLOR}\h$(ip_prompt_info) ${DEFAULT_COLOR}in ${DIRECTORY_COLOR}$(limited_pwd)${DEFAULT_COLOR}$(virtual_prompt_info)$(scm_prompt_info)${reset_color} \$ " + else + PS1="$(scm_char) ${UC}\u ${DEFAULT_COLOR}at ${MACHINE_COLOR}\h$(ip_prompt_info) ${DEFAULT_COLOR}in ${DIRECTORY_COLOR}$(limited_pwd)${DEFAULT_COLOR}$(scm_prompt_info)${reset_color} \$ " + fi + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt diff --git a/themes/iterate/iterate.theme.sh b/themes/iterate/iterate.theme.sh new file mode 100644 index 0000000..2031b7f --- /dev/null +++ b/themes/iterate/iterate.theme.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +SCM_GIT_CHAR="± " +SCM_HG_CHAR="☿ " +SCM_SVN_CHAR="⑆ " +SCM_NONE_CHAR="" +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX="|" +SCM_THEME_PROMPT_SUFFIX="${green}| " +SCM_GIT_AHEAD_CHAR="${green}+" +SCM_GIT_BEHIND_CHAR="${red}-" + +GIT_THEME_PROMPT_DIRTY=" ${bold_red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX="${cyan}|" +GIT_THEME_PROMPT_SUFFIX="${cyan}| " + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="| " + +VIRTUALENV_THEME_PROMPT_PREFIX="|" +VIRTUALENV_THEME_PROMPT_SUFFIX="| " + +RBENV_THEME_PROMPT_PREFIX="|" +RBENV_THEME_PROMPT_SUFFIX="| " + +RBFU_THEME_PROMPT_PREFIX="|" +RBFU_THEME_PROMPT_SUFFIX="| " + +function rvm_version_prompt { + if which rvm &> /dev/null; then + rvm_current=$(rvm tools identifier) || return + rvm_default=$(rvm strings default) || return + [ "$rvm_current" != "$rvm_default" ] && ( echo -e "$RVM_THEME_PROMPT_PREFIX$rvm_current$RVM_THEME_PROMPT_SUFFIX" ) + fi +} + +function git_prompt_info { + git_prompt_vars + echo -e "$SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_GIT_AHEAD$SCM_GIT_BEHIND$SCM_GIT_STASH$SCM_SUFFIX" +} + +LAST_PROMPT="" +function prompt_command() { + local new_PS1="${bold_cyan}$(scm_char)${yellow}$(ruby_version_prompt)${green}\w $(scm_prompt_info)" + local new_prompt=$(PS1="$new_PS1" "$BASH" --norc -i &1 | sed -n '${s/^\(.*\)exit$/\1/p;}') + + if [ "$LAST_PROMPT" = "$new_prompt" ]; then + new_PS1="" + else + LAST_PROMPT="$new_prompt" + fi + + local wrap_char="" + [[ ${#new_PS1} -gt $(($COLUMNS/1)) ]] && wrap_char="\n" + PS1="${new_PS1}${green}${wrap_char}→${reset_color} " +} + +safe_append_prompt_command prompt_command diff --git a/themes/kitsune/kitsune.theme.sh b/themes/kitsune/kitsune.theme.sh new file mode 100644 index 0000000..c339f54 --- /dev/null +++ b/themes/kitsune/kitsune.theme.sh @@ -0,0 +1,38 @@ +# This is combination of works from two different people which I combined for my requirement. +# Original PS1 was from reddit user /u/Allevil669 which I found in thread: https://www.reddit.com/r/linux/comments/1z33lj/linux_users_whats_your_favourite_bash_prompt/ +# I used that PS1 to the bash-it theme 'morris', and customized it to my liking. All credits to /u/Allevil669 and morris. +# +# prompt theming + +# added TITLEBAR for updating the tab and window titles with the pwd +case $TERM in + xterm*) + TITLEBAR=$(printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}") + ;; + screen) + TITLEBAR=$(printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}") + ;; + *) + TITLEBAR="" + ;; +esac +if [ "$?" == "0" ] +then + SC="${green}^_^"; +else + SC="${red}T_T"; +fi +BC=`battery_percentage` +function prompt_command() { + #PS1="${TITLEBAR}[\u@\h \W $(scm_prompt_info)]\$ " + PS1="\n${cyan}┌─${bold_white}[\u@\h]${cyan}─${bold_yellow}(\w)$(scm_prompt_info)\n${cyan}└─${bold_green}[\A]-${green}($BC%)${bold_cyan}-[${green}${bold_green}\$${bold_cyan}]${green} " +} + +# scm theming +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX="${bold_cyan}(" +SCM_THEME_PROMPT_SUFFIX="${bold_cyan})${reset_color}" + + +safe_append_prompt_command prompt_command diff --git a/themes/luan/luan.theme.sh b/themes/luan/luan.theme.sh new file mode 100644 index 0000000..8b7059e --- /dev/null +++ b/themes/luan/luan.theme.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX="(${yellow}" +SCM_THEME_PROMPT_SUFFIX="${normal})" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX="(${yellow}" +GIT_THEME_PROMPT_SUFFIX="${normal})" + +RVM_THEME_PROMPT_PREFIX="" +RVM_THEME_PROMPT_SUFFIX="" + +function prompt_command() { + dtime="$(clock_prompt)" + user_host="${green}\u@${cyan}\h${normal}" + current_dir="${bold_blue}\w${normal}" + rvm_ruby="${bold_red}$(ruby_version_prompt)${normal}" + git_branch="$(scm_prompt_info)${normal}" + prompt="${bold_green}\$${normal} " + arrow="${bold_white}▶${normal} " + prompt="${bold_green}\$${normal} " + + PS1="${dtime}${user_host}:${current_dir} ${rvm_ruby} ${git_branch} + $arrow $prompt" +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$yellow"} +THEME_CLOCK_FORMAT=${THEME_TIME_FORMAT:-"%I:%M:%S "} + +safe_append_prompt_command prompt_command diff --git a/themes/mairan/mairan.theme.sh b/themes/mairan/mairan.theme.sh new file mode 100644 index 0000000..5c5dfef --- /dev/null +++ b/themes/mairan/mairan.theme.sh @@ -0,0 +1,130 @@ +# Mairan Bash Prompt, inspired by "Zork" + +if tput setaf 1 &> /dev/null; then + if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then + MAGENTA=$(tput setaf 9) + ORANGE=$(tput setaf 172) + GREEN=$(tput setaf 190) + PURPLE=$(tput setaf 141) + WHITE=$(tput setaf 0) + else + MAGENTA=$(tput setaf 5) + ORANGE=$(tput setaf 4) + GREEN=$(tput setaf 2) + PURPLE=$(tput setaf 1) + WHITE=$(tput setaf 7) + fi + BOLD=$(tput bold) + RESET=$(tput sgr0) +else + MAGENTA="\033[1;31m" + ORANGE="\033[1;33m" + GREEN="\033[1;32m" + PURPLE="\033[1;35m" + WHITE="\033[1;37m" + BOLD="" + RESET="\033[m" +fi + +# prompt_symbol='λ' +# prompt_symbol='⚡' +prompt_symbol='' +BRACKET_COLOR=$ORANGE + +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +#Mysql Prompt +export MYSQL_PS1="(\u@\h) [\d]> " + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +__my_rvm_ruby_version() { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + local full="$version$gemset" + [ "$full" != "" ] && echo "[$full]" +} + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$GREEN$(scm_prompt_info)]" + fi +} + +# show chroot if exist +chroot(){ + if [ -n "$debian_chroot" ] + then + my_ps_chroot="${bold_cyan}$debian_chroot${normal}"; + echo "($my_ps_chroot)"; + fi + } + +# show virtualenvwrapper +my_ve(){ + if [ -n "$VIRTUAL_ENV" ] + then + my_ps_ve="${bold_purple}$ve${normal}"; + echo "($my_ps_ve)"; + fi + echo ""; + } + +prompt() { + + my_ps_host="$BOLD$ORANGE\h${normal}"; + # yes, these are the the same for now ... + my_ps_host_root="$ORANGE\h${normal}"; + + my_ps_user="$BOLD$GREEN\u${normal}" + my_ps_root="${bold_red}\u${normal}"; + + if [ -n "$VIRTUAL_ENV" ] + then + ve=`basename $VIRTUAL_ENV`; + fi + + # nice prompt + case "`id -u`" in + 0) PS1="\n${TITLEBAR}${BRACKET_COLOR}┌─${normal}$(my_ve)$(chroot)[$my_ps_root][$my_ps_host_root]$(modern_scm_prompt)$(__my_rvm_ruby_version)[${green}\w${normal}]$(is_vim_shell)${BRACKET_COLOR} +└─▪ ${prompt_symbol} ${normal}" + ;; + *) PS1="\n${TITLEBAR}${BRACKET_COLOR}┌─${normal}$(my_ve)$(chroot)[$my_ps_user][$my_ps_host]$(modern_scm_prompt)${normal}$(__my_rvm_ruby_version)[${green}\w${normal}]$(is_vim_shell)${BRACKET_COLOR} +└─▪ ${prompt_symbol} ${normal}" + ;; + esac +} + +PS2="└─▪ " + + + +safe_append_prompt_command prompt diff --git a/themes/mbriggs/mbriggs.theme.sh b/themes/mbriggs/mbriggs.theme.sh new file mode 100644 index 0000000..169f8d7 --- /dev/null +++ b/themes/mbriggs/mbriggs.theme.sh @@ -0,0 +1,34 @@ +# ------------------------------------------------------------------# +# FILE: mbriggs.zsh-theme # +# BY: Matt Briggs (matt@mattbriggs.net) # +# BASED ON: smt by Stephen Tudor (stephen@tudorstudio.com) # +# ------------------------------------------------------------------# + +SCM_THEME_PROMPT_DIRTY="${red}⚡${reset_color}" +SCM_THEME_PROMPT_AHEAD="${red}!${reset_color}" +SCM_THEME_PROMPT_CLEAN="${green}✓${reset_color}" +SCM_THEME_PROMPT_PREFIX=" " +SCM_THEME_PROMPT_SUFFIX="" +GIT_SHA_PREFIX=" ${yellow}" +GIT_SHA_SUFFIX="${reset_color}" + +function git_short_sha() { + SHA=$(git rev-parse --short HEAD 2> /dev/null) && echo "$GIT_SHA_PREFIX$SHA$GIT_SHA_SUFFIX" +} + +function prompt() { + local return_status="" + local ruby="${red}$(ruby_version_prompt)${reset_color}" + local user_host="${green}\h${reset_color}" + local current_path="\w" + local n_commands="\!" + local git_branch="$(git_short_sha)$(scm_prompt_info)" + local prompt_symbol='λ' + local open='(' + local close=')' + local prompt_char=' \$ ' + + PS1="\n${n_commands} ${user_host} ${prompt_symbol} ${ruby} ${open}${current_path}${git_branch}${close}${return_status}\n${prompt_char}" +} + +safe_append_prompt_command prompt \ No newline at end of file diff --git a/themes/minimal/minimal.theme.sh b/themes/minimal/minimal.theme.sh new file mode 100644 index 0000000..72fb220 --- /dev/null +++ b/themes/minimal/minimal.theme.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_PREFIX="${cyan}(${green}" +SCM_THEME_PROMPT_SUFFIX="${cyan})" +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${green}✓" + +prompt() { + PS1="$(scm_prompt_info)${reset_color} ${cyan}\W${reset_color} " +} + +safe_append_prompt_command prompt diff --git a/themes/modern-t/modern-t.theme.sh b/themes/modern-t/modern-t.theme.sh new file mode 100644 index 0000000..da5f944 --- /dev/null +++ b/themes/modern-t/modern-t.theme.sh @@ -0,0 +1,56 @@ +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$(scm_prompt_info)]" + fi +} + +prompt() { + if [ $? -ne 0 ] + then + # Yes, the indenting on these is weird, but it has to be like + # this otherwise it won't display properly. + + PS1="${TITLEBAR}${bold_red}┌─[${cyan}$(t | wc -l | sed -e's/ *//')${reset_color}]${reset_color}$(modern_scm_prompt)[${cyan}\W${normal}]$(is_vim_shell) +${bold_red}└─▪${normal} " + else + PS1="${TITLEBAR}┌─[${cyan}$(t | wc -l | sed -e's/ *//')${reset_color}]$(modern_scm_prompt)[${cyan}\W${normal}]$(is_vim_shell) +└─▪ " + fi +} + +PS2="└─▪ " + + + +safe_append_prompt_command prompt diff --git a/themes/modern/modern.theme.sh b/themes/modern/modern.theme.sh new file mode 100644 index 0000000..583764e --- /dev/null +++ b/themes/modern/modern.theme.sh @@ -0,0 +1,56 @@ +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$(scm_prompt_info)]" + fi +} + +prompt() { + if [ $? -ne 0 ] + then + # Yes, the indenting on these is weird, but it has to be like + # this otherwise it won't display properly. + + PS1="${TITLEBAR}${bold_red}┌─${reset_color}$(modern_scm_prompt)[${cyan}\W${normal}][$(battery_charge)]$(is_vim_shell) +${bold_red}└─▪${normal} " + else + PS1="${TITLEBAR}┌─$(modern_scm_prompt)[${cyan}\W${normal}][$(battery_charge)]$(is_vim_shell) +└─▪ " + fi +} + +PS2="└─▪ " + + + +safe_append_prompt_command prompt diff --git a/themes/morris/morris.theme.sh b/themes/morris/morris.theme.sh new file mode 100644 index 0000000..d6b0258 --- /dev/null +++ b/themes/morris/morris.theme.sh @@ -0,0 +1,28 @@ + +# prompt theming + +# added TITLEBAR for updating the tab and window titles with the pwd +case $TERM in + xterm*) + TITLEBAR=$(printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}") + ;; + screen) + TITLEBAR=$(printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}") + ;; + *) + TITLEBAR="" + ;; +esac + +function prompt_command() { + PS1="${TITLEBAR}[\u@\h \W $(scm_prompt_info)]\$ " +} + +# scm theming +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX="${green}(" +SCM_THEME_PROMPT_SUFFIX="${green})${reset_color}" + + +safe_append_prompt_command prompt_command diff --git a/themes/n0qorg/n0qorg.theme.sh b/themes/n0qorg/n0qorg.theme.sh new file mode 100644 index 0000000..291e451 --- /dev/null +++ b/themes/n0qorg/n0qorg.theme.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# n0qorg theme by Florian Baumann + +## look-a-like +# host directory (branch*)» +# for example: +# ananas ~/Code/bash-it/themes (master*)» +function prompt_command() { + PS1="${bold_blue}[$(hostname)]${normal} \w${normal} ${bold_white}[$(git_prompt_info)]${normal}» " +} + +safe_append_prompt_command prompt_command + +## git-theme +# feel free to change git chars. +GIT_THEME_PROMPT_DIRTY="${bold_blue}*${bold_white}" +GIT_THEME_PROMPT_CLEAN="" +GIT_THEME_PROMPT_PREFIX="${bold_blue}(${bold_white}" +GIT_THEME_PROMPT_SUFFIX="${bold_blue})" + +## alternate chars +# +SCM_THEME_PROMPT_DIRTY="*" +SCM_THEME_PROMPT_CLEAN="" +SCM_THEME_PROMPT_PREFIX="(" +SCM_THEME_PROMPT_SUFFIX=")" diff --git a/themes/nwinkler/nwinkler.theme.sh b/themes/nwinkler/nwinkler.theme.sh new file mode 100644 index 0000000..a032331 --- /dev/null +++ b/themes/nwinkler/nwinkler.theme.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Two line prompt showing the following information: +# (time) SCM [username@hostname] pwd (SCM branch SCM status) +# → +# +# Example: +# (14:00:26) ± [foo@bar] ~/.oh-my-bash (master ✓) +# → +# +# The arrow on the second line is showing the exit status of the last command: +# * Green: 0 exit status +# * Red: non-zero exit status +# +# The exit code functionality currently doesn't work if you are using the 'fasd' plugin, +# since 'fasd' is messing with the $PROMPT_COMMAND + + +PROMPT_END_CLEAN="${green}→${reset_color}" +PROMPT_END_DIRTY="${red}→${reset_color}" + +function prompt_end() { + echo -e "$PROMPT_END" +} + +prompt_setter() { + local exit_status=$? + if [[ $exit_status -eq 0 ]]; then PROMPT_END=$PROMPT_END_CLEAN + else PROMPT_END=$PROMPT_END_DIRTY + fi + # Save history + #history -a + #history -c + #history -r + PS1="($(clock_prompt)) $(scm_char) [${blue}\u${reset_color}@${green}\H${reset_color}] ${yellow}\w${reset_color}$(scm_prompt_info) ${reset_color}\n$(prompt_end) " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_THEME_PROMPT_PREFIX=" (" +SCM_THEME_PROMPT_SUFFIX=")" +RVM_THEME_PROMPT_PREFIX=" (" +RVM_THEME_PROMPT_SUFFIX=")" diff --git a/themes/nwinkler_random_colors/README.md b/themes/nwinkler_random_colors/README.md new file mode 100644 index 0000000..80620ef --- /dev/null +++ b/themes/nwinkler_random_colors/README.md @@ -0,0 +1,29 @@ +# Nwinkler Random Color Theme + +## Description + +The *Nwinkler Random Color* Theme is based on the [nwinkler theme](https://github.com/Bash-it/bash-it/wiki/Themes#nwinkler), but it randomizes the colors for: + +* time +* username +* hostname +* path + +The random colors are chosen the first time this theme is used and saved to the `~/.nwinkler_random_colors` file. So, the next time you connect to the same machine, you will get the same colors. + +To force new random colors to be selected, run the command: + +```sh +randomize_nwinkler +``` + +## Screenshot + +Here it is in action: + +![alt text](screenshot.png "Nwinkler Random Color Theme in Action!") + +## Usage Scenario + +This theme is especially useful when connecting to many different machines and switching between them often. Yes, the hostname *is* present in the prompt. But I argue that it's a lot faster to get a "feel" of what machine you are currently on because of the custom colors on that machine's prompt than by reading the hostname. + diff --git a/themes/nwinkler_random_colors/nwinkler_random_colors.theme.sh b/themes/nwinkler_random_colors/nwinkler_random_colors.theme.sh new file mode 100644 index 0000000..9e0d177 --- /dev/null +++ b/themes/nwinkler_random_colors/nwinkler_random_colors.theme.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Two line prompt showing the following information: +# (time) SCM [username@hostname] pwd (SCM branch SCM status) +# → +# +# Example: +# (14:00:26) ± [foo@bar] ~/.oh-my-bash (master ✓) +# → +# +# The arrow on the second line is showing the exit status of the last command: +# * Green: 0 exit status +# * Red: non-zero exit status +# +# The exit code functionality currently doesn't work if you are using the 'fasd' plugin, +# since 'fasd' is messing with the $PROMPT_COMMAND + +RANDOM_COLOR_FILE=$HOME/.nwinkler_random_colors + +function randomize_nwinkler { + declare -a AVAILABLE_COLORS + + AVAILABLE_COLORS=( + $black + $red + $green + $yellow + $blue + $purple + $cyan + $white + $orange + $bold_black + $bold_red + $bold_green + $bold_yellow + $bold_blue + $bold_purple + $bold_cyan + $bold_white + $bold_orange + ) + # Uncomment these to allow underlines: + #$underline_black + #$underline_red + #$underline_green + #$underline_yellow + #$underline_blue + #$underline_purple + #$underline_cyan + #$underline_white + #$underline_orange + #) + + USERNAME_COLOR=${AVAILABLE_COLORS[$RANDOM % ${#AVAILABLE_COLORS[@]} ]} + HOSTNAME_COLOR=${AVAILABLE_COLORS[$RANDOM % ${#AVAILABLE_COLORS[@]} ]} + TIME_COLOR=${AVAILABLE_COLORS[$RANDOM % ${#AVAILABLE_COLORS[@]} ]} + THEME_CLOCK_COLOR=$TIME_COLOR + PATH_COLOR=${AVAILABLE_COLORS[$RANDOM % ${#AVAILABLE_COLORS[@]} ]} + + echo "$USERNAME_COLOR,$HOSTNAME_COLOR,$TIME_COLOR,$PATH_COLOR," > $RANDOM_COLOR_FILE +} + +if [ -f $RANDOM_COLOR_FILE ]; +then + # read the colors already stored in the file + IFS=',' read -ra COLORS < $RANDOM_COLOR_FILE + USERNAME_COLOR=${COLORS[0]} + HOSTNAME_COLOR=${COLORS[1]} + TIME_COLOR=${COLORS[2]} + THEME_CLOCK_COLOR=$TIME_COLOR + PATH_COLOR=${COLORS[3]} +else + # No colors stored yet. Generate them! + randomize_nwinkler + + echo + echo "Looks like you are using the nwinkler_random_color bashit theme for the first time." + echo "Random colors have been generated to be used in your prompt." + echo "If you don't like them, run the command:" + echo " randomize_nwinkler" + echo "until you get a combination that you like." + echo +fi + +PROMPT_END_CLEAN="${green}→${reset_color}" +PROMPT_END_DIRTY="${red}→${reset_color}" + +function prompt_end() { + echo -e "$PROMPT_END" +} + +prompt_setter() { + local exit_status=$? + if [[ $exit_status -eq 0 ]]; then PROMPT_END=$PROMPT_END_CLEAN + else PROMPT_END=$PROMPT_END_DIRTY + fi + # Save history + history -a + history -c + history -r + PS1="($(clock_prompt)${reset_color}) $(scm_char) [${USERNAME_COLOR}\u${reset_color}@${HOSTNAME_COLOR}\H${reset_color}] ${PATH_COLOR}\w${reset_color}$(scm_prompt_info) ${reset_color}\n$(prompt_end) " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_THEME_PROMPT_PREFIX=" (" +SCM_THEME_PROMPT_SUFFIX=")" +RVM_THEME_PROMPT_PREFIX=" (" +RVM_THEME_PROMPT_SUFFIX=")" diff --git a/themes/nwinkler_random_colors/screenshot.png b/themes/nwinkler_random_colors/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e8cc75d8948f04a0466206de558c2a19930ed310 GIT binary patch literal 43510 zcmb@tbyyo+yDyx2DaEZtTfAr~P%J=^BBi){u|o0Unv~*FDDF_)3GR>rh2ZWKf)v-_ zkdU14Jny^rKJVV|b$#DC=MS!xnPJw;fRC|s1uJ?u7)qnxfY0D#|l^LGp8 zP-qSS6ot!6OK5l)?OppiQd?%gal|$~5wp0(?)S&-voy@_N|4U7sngEv7MV~yDZrQc zaURCc!=96vgsV=ndF%z~^md!PZdaAtbo`}6X!6M=vSd#4@$DzD#!3-j7hv?|aMo@6 zLH>GI*$GGM6h4vM7xEmBJ!Rt`#dwdu2*>c8{H7@mh5#( zp@9SI>ow)as9!}d$Ke;@4=uFxZ{7S`z&Z+wp5`mMC*j=3g>#7TS&jm;rC&ixCbx}| zHsC!NXcwlzW(Gdh2IsBIkzTJEkHNXYm;Daw>upEwnX#caod~v|woj;xBB?Vqn-K^( zU+0a3Yf+dFRl}9XSF&L^jXdfcdS=7Gz<@!>iqkI~2XgZ@1YTWTp-+@CC)LAZND9n~ zF^T|+0E?d1WAgQG{fzz-j5!l=0G;!84}ol+(`bJ}-sgV5*8u_BB(3+uJy%7b)tEft zFK-`3u~wuM6tpNn&&nWRT~5C7q}df4IEoxuZYhk+2l5hw%0UO0#+lciwU2);R-K0h zzf2dl>!-<1FVsq(L>3;Q=fOxY7_kzXl{Jj+1Yh`zU---3uhA*f%Jf`M7RMZmWBQ>h zL$rWMuFUIw%xd%Q7^L-R=K+K)3cT|(ej7mk;`>J1CA-GxxXWp(?OvwuhBu?VD4{H@ zz`^$$E~Sw2*KS_X)6)&mMxBY{@szu`$T{wJktM4v%^~|gkrcPWHgJtEI+W3Wl+g~D zeYo$%s4NC%e3h4p9!r#4@v(j56pTi1%8GkkofJLYzP(gJ~1d};g+dMpAyf`N|$xhpCiP}&q+1|G+Q0`hC9txS~s$ps=WFAsjThe2*d zOVly}WFNCW3LCdMT0&U)j>7wVg=Ld7k5rgmyG#3&ELB&{Y z?>-r^gr;IF;YjH}A6VKzu4fz2UmKLWJ%`_E-U}g49j<>rfb&So2{1roF1wZW^{@L9 z;g^H8u$uhm!mG87p`I!m1KCZ~FIc3b1;xnuIQR5sFzdtUMfWa~Fx2q&_>2-?S>;a@ zA9`uS3Ly&>^+onyQ6Cv^6Tlv?q7JD#HHi~ly!9`sitgNf#%ScAecdE`w=Z*X2S&2H zDs(o$i}CWj#GLd)QQ{b7jJn;7R-C}i#2j9KwTJUAF(}Brr2f;#P^|F@X=pc?5Ok+$)Wf1wVcX$eT2@cSr(y}4&Yy)LlK+D__P(6?^U1EC$=M3 zz6<8>Z;?tk6yS~?Z(uIPF$LntYB~&p4s#5>ICkDZ?;|#y4@xP}!I)$4IXh+(irj!+ zUI{>$^T%OVm<=Y`f{%d6*Qxa$nY7oXm~mrFurYYwU5u^dZ8vD&rg#)|W|`rQYCphb zQbC^|WFpt6Gu3Zf9k;?Sj}kN2oQzM zna6oF3|#0=QPa3-a1>SMe|0nrPOtA1lclVZlh_Cw-!8vr-29B-SOMPP7+L8I zeWozxg0EkIN{1VG`lX zf7M|p7)f*b<&^56gwfA#qk2!7>ii-vq!D?aGMyw_!{qhGgUN{jB=x5r`g`f@N+r$Y zKnflL^rR*t`==ZE==ncOU{vTiXa|NdO}+LMHv{jnV5TvOcJ~2Rewk=} z@pB8>UV2~070b3?LBf~N z$$+QJNQaxE<=$#c{VMvwPa^u4#iwTCm$BlP?9d~2%%4nDEclQB-Oi0U;>L`v^(SYF z(_9ycUyRcIMpr}8#uao(`7;SRZxn17<9j>WOMQ=Z3=CF8R*| zdlDaH_@Y`5d=jsBhaZJX;a#%Op?+kghD??pE2A4i?@R8FZU+s3R2(nI(h2Ar*4r+z z@iCJep7EJ_!V-#XrMsZTzVu5SEAMGzrN(-<=s{G3RXu^aR-TO4d>gJb+$^nxR86m57;RE|oE0%+~P4 zM*skU*Hi+>h8GPe;U#nRY}qgKi$DlZzW3huiw~K;N431gYv`k4j4!%X#AL&`3VJ{` zx#CUg;M6OMM)GPyXJa6%1yC`n79pC6`nIz+;X?4)EfP^PpGZFQ=#I1!>=0{@cp}#u z;g{vCKV`WO&rbn>2hl$&$1z7NphIsu)C>iv#a`l*xYywWj2%1^T?PRKUXL1AVNMcv z5tu|#&pxs1&PyoL=LGsRcK#LsUu3QOU=0BHxywVFVHPJd)-NSlx49HzXs-*1OsN@4LP8zvH^#2;0{s z>yrQ2+ZhliQWi%0H^if+e4jNQv-$V^{9JyckY>QeV%ZV?&%?~QzelrK82^3_LB1r( z0;bV__9IdK3y0h5-#yyD+{1szmj7;SaMXZXjj0N}pKC{6Ba-u!lA?o1oj=9rN3#!} zMDCr-jroW*V3KHV|Hik}g8)OY$k8)=r_1@S3(vDZ z@3u}5O^Hx%sJ1tC&Cv;S@BmCbBa@oJiK+H6J|_yjFT@|VQ!VOs(NgP`PS=8@7d!3~ z)E_*gv$C~yYAcNqkv@+){}2yl*=d!M=6+jiUMr-p68<5Py7oA9=fQ4}Q7cGEhM`vE zz)gpB_qoxUxD}LQJG1qNT~}vbao|?S@w@4s$8~**!@UD(b)sI~My<9U2Lf`R!#NeJ zebj9jrdQWO&+aeN`*(X*2xtbCy5=VzuAOs7Rl>XPsLagkx}A`(M}FhHD;5}|d%Q|S z{&cwi_kKR5Z4Ia;(&yx>>`&lG7G%Y9yr*luScGGI>y1|+(|X&KZ_Q3OI{gnD1AL@ z-c79NFN%H9i#&Jgh2wVC?S^T^sd95yIPCTf2z%h2uG z9q849p0dHLFM!vQ*1gc|Ar(- z4?l>@8s*|FLUokZcIYfs+h2-i;kkgSfgSm^JromS9OTY_wx;D1;S5{m3pzK<^Yn4ODwOum7fr?qqN%-8TUh3`8lU;` z6ivN0fx8YGJmO3F^ga<6C@@Sv*xNT<^~Y~UnxeO(v#pzh9L5Vxau*_?E!=f73#Mrm zKSp^Z*;bgXYYX-dBVMkB>Vt-_Q$%XUFR3%*Qt>h46X3Jf42}HIuw- z4&}=Q5q{miGuE{@v-(j`KWyG$NOm$MZS?fsxw|%9uQd1XNbQx+qRmUj=ymusT_Q?s zI!fWPi>b8VY}H*fF(HqvelLZHBB0KEbo-k4JGAyVAHr_J;w6~|h9ZYnDV>|e&cBi$ z;7-F!x{!r0MY? z_%ao23^q7M8i?;V(740OEkQrIEb}#y=u3T32Rt3lWSHl?zgN+n8ZTp)O|k9ugB68> zzJn3W1F**)6$Yiw&9&qu+-t+{)v6gdr47NdZ^n+8R0Il?)!c+9jY+FZ{Cr zZ!TgI-p|&<$whTkhr$GYxf@4k^LLjQbv{+17F~8xELGd+5e414>M>Ym7RfjU+=QQ{4_7iFMPdPXvxvc;e9FeK4_zC{!}g4>a=OQ z+jS-j&O~b18if-4Fx}af9^9#dkt|>G|@8PF8_8HeEWbr@;dBi z|3!R4x!!*Bw=}5J8nC+g8c7Q|@*I&eFSNAB6Uh14YE^*pTbmucq%hL*eGuebN+P!E zI5bliIeqVQ2#ZmK7MycjIZ@6iRA$Z%@eoyR>8}(oPHIw4w>ohw1Gk3UK7d#B+yQlY z>gm5sR*g7Z|>PL zW=DChppZOS$i~7_IJh$6ODoS<{LygBwPo#6K+EQpD4iibXq`Mu$2EnexWw;LpA%~7 z2^<0+UfKrqDdRzBq=~nEhWd;df8DpcHsS&nPZ6(f$RCCn^G3_DQYe?eY{oqdJ!iKx zE?ccmuTlV^)jjSm!QNI-MptIw%izY}Yee{foF6b>a+S0K;yL2dn&^?&^6Uo7PG z3$mX*51`!a#RrcbyOE@0Lg|U#EIJ_LLLj>fc69ZA=L? zeb&0k3jL3tXL!9=aB~wtf*Lk9ifYVh{B2ZJ$dbhCftzu zK$kLJm^&J&-vq?-QcR+m7m2?}fDgCX2(8`sN^kT_hYK6%l7cR`Oza{!4faTcTMLc zrrsBLgLS&6cIuYt;@lU@SI4PaP7)gT;@+mj#s^yT-l+`biU|z%{ie$iX$j(SpusnO ziT~_}IdfkGpLGVEURJ+Ju0X=D&MWOCH=xxFMCW0}YBbm0lR(@V$fsb3lInVEI0Mx6 zgVX5Dok6`>sv{D-wTiX&bdm>9Mr$Wu9IOvQUsoI*liAOE z%?gaS*15L-j$nvVu(O>z|MA&dPwjG0-IVK4w;p8;vySGzIMA`E|E8xUx|^gManHyn zL(1M_!t7Ohmsl3>Edb-G*L9R$0AGaE~NJUz6jr7$V;;*1VRl=Lvx!>6|5tU9Hn&gVsYjw$Nly#;orWXrlLa;=o}Uc zdK=eG@HHOjxWzL~S*)&_%TKU7yXS57nJ3YmHxCje4z#HgA1iy!BB~FLkY1*wy3%jU zs;7#5F{`eZhCb!W0>E8w!}_wZZC6&SwR3CSM7w4m+Ph^2;=pj%eCg-8QH^ECTVClG zOKxZ;MYp+PSj*lWK-1fvLUJfOm9^Yy9K9o*ASCnl1JbvDO3r~DBfUGtc=E}mZP zK_+}r!enYY;|*uY<|yY-r+vl%aEK)lr}&6Zj{($Bw<@BM)E-(|B)aSJvn@BPEBj-X zmM`N+{Tl31qp+u@8j_F9WQQ0bJ!3_zl!PhoCx=maxSrmLWRIuYpOfL1D ze|~G?02i?NDhr8FS?KJB6h25iF#x3%xi?6*AxPJsck4RWNQcnWSc_|btbxCDX9k;X z7dO-uXt_Khj5Myugaf_o@$Wgz#GM`1RpTP@iFGGIT4e>^N+oCdeemwnEej|W0i4q) zI128|~0U?mifKrmhoI z`P)ui&PJA$+`&;i`$lrvx$m&$2%;_m%RM(I4%i(VL5zKNpZ4wpMueBiqKXLuO9`KY z*3cP+<@aH$mbC=F*(sHojkwh(fN~#zK=tV4`{t-pJR>hjq3zaPeI5cMmcB_R|Ac;q zD`qwiG`a5@dD}+p_PF%x)R#GKD~>tEX=#MF_;)JoKPFH5{~T8mIa?r%l(^0zw3~C_ zhhi?%2IF0JWhjrT4qO+mR!pJkJ1z0>{_rCdRSEwmRyxDieFvWx+_r%p3&wU5(_qHv z!jzQG9Um`R2daj2Ft_k2@{vI~9pH`SruTK(^a}T{iI^@HIQ%5pwLi7P?!2)Pyy87X zKSEC2A*a^U!y~>0_(Guq{9(g)v0(wX08W3c=oz7E`3m@=PGt4bVFDOvJoBMm;~AGGzL9g(tI`em{! z9?ia^SXLah4Dsl5+ND7w#?&H*`CFJNGd;U#TMMU+p4m}u=I7n-7X0izsA}_Y^bl)b zJnXd3)?>+u4r=F=5X`0S2>yh-%sEB@#+UH?cc+F-&G9_ z8O-TsBrH*l`{^MoN(;^Jm1(k@H*u-{RI=z5c5Fdg@dmVpCR@`yN_G=!i)U_Zmbq$5mJ@T8jHkiPoWchHo+Z_h5}f-HPT23{cZNw)-c9$3hlf&-de%v*z-ap;T|-(ARdqKeupgwC@OOhs=+)-RLEJ z6%?wRU+cN5R0+!hi?3-I6su$>&ocEEWD0k4uggiE4oAxB6j{|+`fLsceJ-LliC7r3 zLlPsud&KT)5O~Y?!}D_SelYGXBR9};F ztV0Ok+Kpc!YQywgvTG0VB2T&YANPTP7yUT>2I=iN2U~ zAaiC}$bQ+6Y}#C8GGLa$hUuf=+(4%~i_A>9{b;LdSbTmUd^*vd7V`T?5wEH&gdNvj zX3%TdHJ$y}0r3nk4ge6zh7Oax{Ozfk)^pUjFi|j}BuyMz9A<^{sJf%9opanMyX5I< zk6{Mb-~H%M(dDMoVKqeU5fCHIZ?1t$;GT@2Rfl13>9kd-)Q2tr&^k5IY4!>yD* z$)AKz1_)s|!W8a1tMMiXkbGf6}bh^`rr&Cefz;iQ3#+*p*sUs@yn z5o~^D{o~gzHauYu{SPvj(A}_La2@wVBBJFx{Ca**;H!x2#gPYX6W?<|LD-F^Ms2XP zDijyD!6Fs)>n?Wt3qzJiE>KV~(@V^1?Ix&sW#Y5b(%K~}lsMqO#@9E`BN8TLsNUhn zyG5NoCuo{YG(7sZqQc3`s%|t&m-F(r+3*?Lw1?WA^0kf7NJZBeSx zP7k~cE6A|@{;1#l8pRU5)=3@t?HfXsV6tI+Vud*zh%a@>^W+<|Ky-ZLiv`;Jl$4KR zcN3pg_dO^l{r(iuZX8cLXua^PRAor|HJxET#yaE^WK-EhD`{z@X>OZp8@FQ}P(l?$1T$knW0g_KMAYB&9sW!@vIvRktuw}4xK-^!T8ifO+=GyYv#?ieAg3W zJFH4sGb4-ojo(f#1_E{n4Se1ds13c+$S~%bW$;LxNZKvKTX_5KE9ut+qOIIYW1fmy zQY8>yqH!drl4D}ncXMp?)jN%Tf6}oAWL08IF9_cX1z#G1D6m&r3K_ZArOu`oG50+NQ zW0ikpKfUK6N%VABO=vfE+aKFA_^+O=Dg;Cm$DLm>GvJ&C5hXsB5F}Hv`MxLwW?8kp zv}sEE`T-h-oBNA?G!{X!J9KKQ>6LZc5SVdzTj;hQ$R!(vy}LKVl>%WfMp25*RU#7# zvZ!U#-Z6gQVr-9|p?gEtl&KE0`8kTF1R0rq6D`b9VO4Ok7S!&q@X_sN3pOWuPbSJw z^IZ(A14nHFeyw4`nxLCkyfH)7#n2R2=-4mq%0B|j(ep?aHA4nqC+NcS-QNQ;+Pt^8 z9(NFB>`Nb&be_)N+YyYcO{2wWP7WsG5{%LflizMW9wvD+I|Lx5Qf}79&QklQp zdGxoc4B!O(@9Ob?D7Trd8o;AwPdo>~r=51og9ZET%GKwWSQIV%u6|Eo72FaGfFrXn zeU35E?)K<&Nr=l~?VdbOIOv!IGu5To47-k{IBSqJ=h49J;``FR~L95-oC|Rx5 zCpE|)qkHgsP;blj%e#OtZim`HRO9qnM!`mD@Q37b@j=Vn#g^U&=o;BlYaJ#l@wsOa zNvX%Tb)wd~X?KBDY1ZwmP=b7#$i)scp~)(jVbt`4d8Hn8lZ2kv2W~Cqb61+{W3T*m zX}x2ENOE7|cE(~AAbID@yl8T;yP2Zd=a#eih+)t@FN(cHI9W6tNNqnh_vRqZkvdUt zY4%R!07++)E`TJtYthfQWpAGp8z2Iv;a+?279@mv9OZEBTsc;fZ(pc6c$KlV)3U9V zF_Rf7QX;_ukCa`iz6QmqL!$%$5XeLH?!W@H8~M(KTt}PQNall zL8eez*jj>kNcZ)O;JE8-ml)paM;S4?Gr%n@jaGq7V+!BObqZ?WDdxJ(MOnu?SuY() zejfIsIy7X8sk$G96%Vc5FAo23{6l@b>_6^zE1!~MAt}{}bL%@;EP9*G(gn<$)`GAj zO`lyHbJtC}VB@AMAN_zQ$-ObzkIU{Yc@~!?Gi#c0PHcqqN3zOyQCPXG^K*mc%F!y@PWEvc>=FG2#6W1+oY9ZLfLFH}DmityR<8jfx;MfZ z5D5+eOka>$z$Kbt{ozF)MWaPPU9*=R=N@E+n* zQcD^vtwOXgdHF!}`xh+8uyN0e2Hd5d0XC~;_NB#U_a4iY4%_lv->s^nT2q{s^2Bx2 zxNnvlQ;eL(;Opj>?6eMnWvR29)-s}fb$aLy*ToMH*@-pNj!@pl~flPsW)X!fdv?zbvT zmrG%z4mnm1=#6EueopNG<;DC)SWbSuDNHiifsK=LY%)fIC|aPnC1OFpZ*jRGgs~ZV zF3y($L07W=PyT0keGVw?>P6S)EC%&2GI8&P&67mcsHCE1^&iF}3Dn zdnw?~GS=(3Z^jy9s@y-O*m>W{^8V8u@$0vZav?v}LsYa0?Pi|}X6(aX_>?{>V1;@Y zkn_xexINym_M3-Tb2xAKfZVe!<)w4}I;cXeXBh7*gar^JG?jI=&)gUZek=wFTU^ThL^P>v(aMDNeQE}2z9#n%kPZe9IHDk z@oGa`ZInfNqr=`oInss2+10xFlw$3|d%L0%5d7<0dEb>HeIX9;|4!MF97Gu&9^xkWWjLMyUP8RXff>1Pk$zzIM zBvf%h83+Rg~`IheM zF`chgIhfB8(LXTI>94$JI$s%wAEl~AhX7BWr4hhZ#6G`Zk+PxUNr2`_zQwD|4Nf%A zPWqb0F6O4gv8V*U_$d6ra?ue!I`G6S)*4G*C#bnhw`zv1iN!RcGe5Sm7#YQ!(e^A-) zK0OfmbJGElxU<3TKbGea4l?n9PqYbk=zmms`Z37O|Ngrg|i3SU94^&^63n zDlYmwu6^QO^@h{KpeafpUi44u8!H!w0L`9UW z9IdRZ;pJX?|EcrD*<-GefwedvTwg@p#bW~H#w1U#`UAHw!7#MJa+l6pIhuBOq~2^I z<;;>x&xYIhwRqlmfHtTk&1Z#fw{lm%p*472#uMbk0jsKlb7RWCoo2h2jA%U_ZPaN~ zcpDoRQ!QEALmI;oCp$O2Oq4Q^(SH@l@%3mtLPNFOt(bpIII8%Bef@aUIus)Umi4iF z0}5B}4!uv|F;KW%TgpspL|Ilb@V2dYGF^3kdc|U6xfb{WCmIS`mk=`$&*++Oft&=r zd}3aZWJov2%kI1?qQ!MH*M@K6Z^n=Rfm(DMAN9&;&)csPux*$47z%UPi#GkvI^aBb zbalyGEPB4P$Ej{}dhhi@JyL88J7RiS|D(`|GZ|IzGL@%OxYe&en9Q4$D9-yWSb|lI z*ZqTd!(;4uE}`E=6Z?;28`U<4N$Bp6X-7Z^-NOSO2kg~rybe-v|0=&tx3f{+4)3p1=co#bBt*71M z*sD9L_(fU5Rm{ALnXp>`7b4aSUwW+c^^o`HUxhfrZ>+kUV<|uJQvnE=be}wDqU|L5 z17l$8rAbtYi#FG*my!g=V{0TD-d6nyI-@kC?RdpFIAb%A6dMiYA+<>8+4ERX=nOVC z?oPzQbF4`Dyk_MoiNCu*)YaaXxl5D>zd(M4nDzT!-F!9P68`A*dvxm}#G*wBe3LK> zE-u@hp5YLx^=X)z~cQOLo=K=Bnm2 zRQ>V9x}2tx)DGps8SY^jC-DfmqL7dq`L;s#f-Qr|=83%!(JK9Ds>`ePcS0MR$@E`I z+WPx)iesdIE7CK zOThIePILjb0D+)bg`-FavTC=Rt=`b4=e&z+c%$WgY3I56B{F?qn_m5HaB^} z!s`;R7{b`G>fz}m{gfrm1jq#-8od!U&SJE#5av%(wH3rzAt5AD=Gt<--^W5SKe(4u zl#GRU8Uhss$-cAKPQEvL_D&*O_HKGhaNtJA+kF917BkbBw7u2mK>UblR%&@t)~3%zsu21o-b%V5!~-br zUiMsJwxTktqjZEHySku~S3uf0^`rJzGZOc8sV9-`Q<_{cA9(FB513qwh$rf0gC}w1Hbf z@Z~4?R4#($bb9+wx*JFr7Kk>P)oonEYhT3Q7k(2p$+D2Yb4mt~_4^(coN{36a{8_N z;2Q6bTH;P3x8RpEo7{)C)bo@WfTe9?euam3?7GFvOf0^=uYpFj<3bWe&lrET=o z*>R_7q#*A8G1OwMybw#(9Y=N4w%8M^ z*^RvrNe}L;DgGG6%ylZiu@sXVu3b+ZsSHvTt>9Yfi0mz(ovyq#_)$DCwSw|H{7T)| zkbd4tNik;Tu(U6Me|^n$aI8~T*uwf(_F~o^2e8{rLSVP+zvF& zY;-e9Ml+k3ii0{@$;**xZNRQbdsr~R=^i!C_J6_L@6;au8G8I`3Vapr6iw(?K$unj zY_5v;rIYLTvgtSuwUFoH{x(@k)r=jKPGiV~=WIgB!=L%MNsih4r1TpeY?QVy+~=UTr^hwPBO@s%Jpk*3ii&qBmHWmk&O6CgC}U@as8q#@ z&{I2NpxEwii!#{rLCSx{_v!zF@4eA~5bew9eYG;}ImO?Dto!jwB>(v5>)-iSXIQN| zu0q!KRH&CkfpfYcKE{MY0ZF=blDO{L6jT=zif^!|e*uNHYZVxbsC9NK8FxrdDeVt!q2vzl8OAI z>~^AA#b#^0NuO2$`cSpr@HlVxN9|QdwxOH|Uo!ellb{oQ^zL{|z>zw_{G-}OyeF6Z>`qBKok-7mls$4UY z(*Vte1RbkeG~7%ui61MWnO5a-zCt1~#m3YezsF3N2Rjwm*?o8L?Bo&Xrpe*;eJ`+W z=L;{72kE5qUh1a@(G4?|j)TgNeMP3A=xAA9a#13cenk6oX+wFtFWV8ent7b`t^=hP zHcm!0%*0g+$mk8fl)8i_pN2UhqBVXyFRs)d9pgL!B?Z$3@$Yn6Ot$?0^h{1DwaLG} zdh=*CM$>NoztfSTJ(gV3AKn|4Nzp1nDbGc68=kXP4=IPb2+2g0m>Z$uyP4D+dvHf= z(YZ=vPSTS31`vlP6?6Gq-{jzRSHwVbAQwYZ())JC=a;UAgGWyxzOx>aEO{25Qj?VF z(Z{h(^Wp@!$uODV?loCech->In~7LQhoJ8f3OT$n~zqiWLw3z>iK+$$d;zIx)% zD(2ZYGld6f=BsGC4e%iRul(q(dop)M-72jgu*Jna{Pa9iGd!&bmxA|N zIWkSYQPAVek0g89DoF1U$pR_y$MB~iCFxeVR}H0XzKcsEF>(&!1s3kJn|@E(^qy#h zQq#OzRX_BG@4MY!;i&_eokMMccSj)X!wsbDV?1WXcZnoSQh zG2Ja+2X+OXe*L1w#*Z_ z&47l?#l($KhYNTu`#jZ~52-|PlCfEbFp0J>l5~;&F+fyynj+k;x&_8>i7;~4m<4?t z*d&k`d{tZXF-MjF5huCj9-t9pL_N*o9US8t7^kSzLn@0@&WllHk@Sk8?m;<0bM<;6 z2OzD1#1LE_v$aHZmIEd(vZP3r&lDx!B20R9G{i3Om_|8F-g{AL6@f=X(#UQxtmWZE@85Vg@-Agc%sr?=(u=dX#*uv1k*Gd?1q` zm#883{ZhUyVW!!9quqzV1n{{ku<-#3Xt#NM>WK}gX)k`0Vc#3=McO(}T zxwB{Og|Arn!DWH3K07}um`~R^^Z8uBBbn6tH}mNZo*G(%uYW>pNr+OdfBVgBT*SZ8 zB*h=48B#QDJTYKyWZ=`c@_ReEv^2#Jvaz>R(BBHksk1G^P6EM)XNU$(iaRUw{)syq zg?mp8maZe!k3O6KTaHO^-uH4Uv(c)o7D~Mtri{K}$a-=@pS=kN?~T`%TUD>V+LJ#M zn9REK>7y2(@T)*d%07nv+)f5Q)$Aa?*!PUA;)8NzYt{vN3}wfK@1Uk)bY%$_&|~*s z^X*6aKChJc8h)C|;6W_-5r<<|ffigxiskzeb8Y0@A_R~%dHE33DKEj%@)d$(aosmh zAfWx3NZ0O_RfcXd6}-~vCc=Z7L!8CHSs(lt1M3(3T-tp|jl1m^6fPWdEx!6pzJU)$BEFP%KP7?Ql=!;ayLbv7m**Xrz zOhkAC8R3aJwwFjH?EE-?IP2Uv0Ogre&qTgA=4q4s%{c+{K5Mq#P`Vb`;GFgn)03`! zO35FyDfy1GzIUcgNCTg-RXfuqRkR2K*mRYATYCe|0cRPlk$=19)YkuQnTGR2QUVMb zUf%YES^SxY<6 z`bi+s6Yo0h#_m{3M^15N7u(`kVBe}W%=2Ex?7wHa$n#Fxq$AU&rj&J-UW|SNgiEgk4Z*(Xcov; z>j^w$kK>IVlug`%Qi{&9UvUs0VfzE6-h&1pTUZ z-1XV=n&sbBWk55=7~fAwXL;F`B6GOlCjE_KdQ9}PsEkK z$`;m0(`Oj~GuChd-gSHPZCF5`af_t0-AF(qHvfZ{h24)8Oz5yREZ*n)MS+BA!miuc zg;;-?>vh=rxmhZ@zt+wF1l|7sZLa@i0__w*nn#vh>NhHR%I`M`(iug7b}pWZ^iJrt z#wZluBb1)rVFyIseojWf51%chH8EfargVL2`3*=3TrYeQVfZm2R_JxJ5~IIgl3U90 z&T~~eWZ=&F$c|w)V=&Lbz!R-I4DtO%zrX0w$1oIKt@YbTS@VRLm#b-)Di-nG>eZR9 zCV!Z&b^O3)eu#ElO=yx8nI$8G(>oG)wT6oa{b~QSCyz^8CPHELht%|nB!_r1XYpF6 zzbgg*qU7TDit2~Wq3qsj#*!!-f+`?^YveNQM#ftYUVLE38i$0$$C_bDL_Rfk;M9N)B2 zAKT?;;zl9?8aEs>I63UGy_T4chJtLgx&4dIrabos#;uh}!-4JzPEyGZM-y0nm*TWQ zYsMqz>1dDI$(P{#Mn|=wdR60F0O|l0AeUEgWho(H)MN}^(Kmq!4t?_Qy?Y(ZTSeIQ zI`S??gF)HdGdTSHOcZweVu0dODQ0}T!g3FAtAhpBZK~b8<6z1*&NKOov^v%^A!8(- z`?}&pf2cU`Y%4C^z8bPd{iIR2LH)u*pOaRiso4GO;h5<74u>oMn|4P}7kO;02-S}5 zOv4Uv#%NL4O|xm|KX~xhi;5c_EZ!dW*E*m*d^-BRfRu=je^!Hsgr1{|Wl7r=5lgM! zKD#QegeJR&wZCYT#P~~|c&X#*Hd!7LN?%u{?Xt!{R_!f%uF_@pjQ-lxR)?wgVWR#= zcM)}XKJ$9YvL-7R#mrW{L$?1G7 zEw+0X^v%{GL|dmvPMiHt0#&lf>$KVL>;`*JGRWI->}<y4 z!_LJ^e`REvvP`%2<=Ztf%p_ht`a(;ugGh^LdPu8my#lf2Ni2H{Ce~s%tFvd0%M$XL zddzQP&Nw_%oYiEW!?8F1r<7fqjF|szGL_bWruWiN9c(jKYu$8xYoRTkjHfKTE=s_h zs3{&3ES4-apkI} zlD0^hX)h@;(`~go-?Gg&=PS{tDJOk)iJ4W)Xznmi|AI`4Mj9mB(=uxPmtC->#;fFX zRm7cYosQiZrbmuEooqSXfwhhic1 zx^&+D*%-g_Ez;QpP$aQ!oQ%)NJREgCt5H96RKwM#i-=qoP{*YzfahZRs3gPwq63_dt0$@{R$ zWzO|rzaz&6MS)>MqWAJgEdP@(hZHwfsF+DtF_;D9@qHX;;6cJwI_EgN%)@eSS=UJo z=(!E)6C744PU8vigEcBXX0zP>6~6ty*n7*UuJ?Ui8v{XFy1P?a;7@mVcXu}eigb5N zcXyY7ba%IOw;xg?m`&PA6*LF@ZPg6LK~dAGCDu^DO%=1aqRP z*)n(VKAT*<1VX0rYkb|GDjMG?mbGUJO)6@0w(@-VEXH#aEA#;;`ODLBB0qJ2hNsZ?B}5-|0fY%XXmb7C zS+q?CGNLpM!4LR1l`xIkkuj1#=FaJE2I*@R&E?)|gOp>|@5R9^qv$wnPwjNLU~VJA397g+o8A02QgeoyKiG{lLpJp^JLEWc#_&b#UNbw_RcEm z;0J17IHik!ZGoA#HjxyJ5`?DK-WemXP|`CCb!te&gKh8%F!o5JQSks+hLp^#AYrbU zh}DSd`LLa%ZbY+L9|~}?r0)aB`K4p3F;Me*!h^3RyQK)sWF1* zA>GaUAst>XYSL%?P3{g$ldGr$&W9}m>FcIBRoF`bljwbL17E2mEs;3W-aAfb;K*dv z7RJ>tMp}N}A3D_c@5Q|L>`kW~`7FZ+`%19xpfLW&?CWr=!@ULeuJAgRANu0M54rHx z7W7N8pI|jrWGbGIP3WK0%ZN17L%I1}Rr1?}dr+q;(1YL3h@rh4(qFTWp80gq=IgHz zyt{FlvG>C&)zsfp{8n(6-M(ujEU+zQ`0XVqFt8hv1YW%2`{@G&o;BTctz6``^ffn4 zw4RHKy0JI3lX1Ge5%plWf1R&z4~5&yJ3TvJC?m&Q77Vp2575GZI!EU)7k|v1t!^Io zd2@2mS$4gKNeG3nudv~i#f!UsmNyjz-8carMy)vcK^+8*oeiSY@u>sE&OS!aH07^^ z;$GF2o|tA$4y@)65^#H+yh* z|47zSum#(X#l(Fzhp7<}xE;1>T_C*KwXojzIWNuCX5c7qPRtaW7*FQ7UnM1Z}ba43pL`E^umvA3i)Q0a`i57;V!*STh&aEOdD9wG4%`` zh?V;ofRFz3Q<$I*eleqjNAkZW_WNlC)pwrP5y0QuFW#*HY)SL*sfuy!&)mi9Yxm-i zg#+`1mhqA|^y@@mD7o~PTG|Y^lne4_!fTDyIm_A1ib30#%i$$dYwg9eS%w82=nJ^Qp> zs*Nd)I=uMD0IyDIm*+`f*)Yv2weqFY(PXkN;d@@feBN3PC4On|?&TM0)EECA;c?w$ zRwjP4yBV+k&eP@3b9!?8v*xCqJMiw~YP)M4m%A$nUNZ^dVw&|aI(<9>!yC!S266X6 z*lc?@Jbnm2AuIinc?ZMeRsy^Tj}fOu`mx_Gh^%s78;fhGzMQM|3kZo7+TjTqES+I` zY2#q#3CfImCj=5+$S97BZKxhhmv9yQ5Yhn|!nshSu^|duAD2eP&N3y6yJ=gq!DEG~ zK{|6bfV1P+4$Lk9w2Sbu?^BCa+*(t+W5v_39Z;JR2Ipgjw`G3suY(>=WJgh|OLMuG zt&UigaYp*=>GFdw5*|ioMd>5vkl1nD#1xy#RkTM z7MzwNqVRpw4F%Xu59(|*p~<+D27cxj5@R|SK#DpsU=}DouIV*~z1OqHT^kcpzsIj^ zIs>&oSQun$kg;67(}h5BkiZ8qL2)}9>7a2kP_f<{vk=0+N%E)7l(|HoQE^MjGs)Jo zxifR*Vu&&7_MJc(0U^c(*jJ*L?QM6ZZIAGS4Uo!?fVdz2 zXQ+H;k>k&8(YCdB%$gFs<=S1~a(a%BSSy|XmTD2F zWBBpw8fmqoT+dWPzi%kU1fg;O60G0?7^>{Rm%QFpu|3OI6AwuvYbR1rBaD=x#T_|& z$w#umnRH&M9TA@*6^jS_F6=P>hbtfOaWJr1_`g=xmw)PRb)fD(2n~NcX@Ti*d#%6z zdTXJLq~uTd_yKH(U+d^E&%l56-XBpv{&u+h0Zqu7*F{GzCucNsr}xa|&0495?PD7= zn>d~?ech=GOWjNHvHBuLTY$=g;DED!`$DJAM*#@SLyvKu{;gbtdxNL02o0s*G`Xxq zY~-`ptv(*w9EMwQ&Cy-+FwXi>9pP>1uxy7+W=$EuW}wDZJ8DT&$+gteP@Ny= z49?x{C%@Oo;8g~oOos_)J-9p!(-`dnI#QZf}?aT>LVMK-je#XWV^ z-6lodieO#JtIH-T005n?0t)Z>GkXg)(q-Uh8^)Ljj)ghL0mzXu1K{70M#DtutXQ1d zs`FMAL8_|go1sZQswsrBmd4`9MsUSRtlf@$1f8txOSqGb8hMc#@w@|vq>OkujvI6M zsc~82MD_l1t6dyg(MA_Xv?_W>Xy1J3`f~lVf;?+CPL!?EtZmHwjF8$q;aX_2O?TIa z(5WQOZaA=XSUz%Gv=&AOU9Y7>^|oW|bzSnP`2vY$v`WJt56SA(jz-xjjmAGbEjDZI zLO{hORSy@ZJkF6_(J7Kn)JIVsPoXUQXkn^&5~K`YVxE$g6Wh8#FfXMtFvaTSo!N_NNr+&`#v~!TUBANBEC|?I1MN6p{#gVrgNs%raxcMk| zEQRrG!^04Z5*e^CSXt^F%nwMpcZ;-1(jiZ3aVjK$S48UnB^OkGKXKDuQlPY@kA2O z@`v(1zfH+(1SK{4HL=qN|Jd1c`Gars%5&8;&M)=yb(p_0fTcSE63IT3=+#qQAkE!x zhTe8Puv#m!7#7kM*cbXbq0#e4A}>(5FB0p1CO0g9qkj{%)+-Am0dr-o#AV}@|0XIg z18~a~BB04B%!9M77!9#FdWn5k06$Pt(i_JUV%XFx&dhvYch)nks^=^GI#FunjVU%t zSF)1;%F>}kOAMl9Na?xYi#JG@TX)1*So*-#pc09iv3n+t@Bl^pS;T=3TdK%}nIs9K zmXnAsvY?R_*_(9Y>^BVR>WaxBl7(-6v>aq_t9X9iELMy@2aWZFDYI!FR)>(t7w0BU z@??=Gx^Xc!JMwG!K7x*IH}gd?bqy(@Du!-3W#PH%H?wT=?%Alc+8#E+N}*e-Mg?R3 zlq?1}>K^p2&=Gv>Xjy_*{-gue{XqNl3{Cfgy$$bN-d!XX<@wU(BpZ#Mh`yykYS5i~ zP{9c!4n92hz+LQM7eeOtfob0AS~hAa7dpJc3G_~d+vN0;c>mAplzWq4SfTu}Z=MAyV&7@; zaGloawI-xWXtMK99AF6ccR%MK2E}m&jFbz6YSQI*y^ZJ?ovTSaq0SFQ$TA1n+XDWa6y}0E0vP8^B>~VT=0(bweFR*>>vPtQk z0mndR=bf8O@k;EctjD4f7H= zq03u`2^>xoQA;K2?X^zx8=P?-htvYhYg%+RzCy+_IQj@(WYW9W4P!ei6@jTAqai+C zK~C8>fcxohkE_?+PInP)q5beTG(*Q-PF>D~x(haoWUO|gXK9wlfSphjB>Dj_DAC6l z!NIt*zB>2*RsL%Sq3M9Cd#C20&L%?D9dcdB|9WCzASX7;CkM8=Kw*z0uj4G?%wa2J z*IfU;Wdeia#rk5@Jn+XEkjm~{hpwz?_sz^~Us65H0=QcR!$(*JlvsCZVU9!X9_)6n zoO*1yrN2_s<_WHYt&{vUe_r0UiC{oNuGnQ`?H?d(E zjP8{3bTD-DuxUSPCtAx{m(3f48qlcju!OZ)BfREt1iX{IVKADu@wr3v&eA(Zh6)Bs z(LuS6khCcIppF7c&0-b?KN5XetkRyTj{wt9y`71YuoTIUzsOO2UH)Do%-y%A3fCio z`wGQ5P|ag;xda*vQUO%r5J$EA(?v4{=*&QnxzFta=a zz25@kAZ>MG{~EEwwY<8rp-XW!_;ojBbG;L5-ordu#;t;*i#B@C1H5Z{{$ z7f~07&zZtsnqV9Fz^mBhlO;6EJt(`vp_A_)&koJaHEh^FoYLptn*K0+h8wF`1$#oZ zAn-L8(;5FN(X{0Aa=?*|72-h7HbWmy#vC6sbs;kZaBy&$cB-w8by7lEXO1dVu7?Ig z;CaN&Q%|X2Z6Wr3(|vh`B&mlc<Wpv9U2F2^6?c`u@zl*TfaZKp#C)#KqIMH9_3N>MFm0e2ZS?M+nRowrb7 z{CMZn(LsBu!SGuCiv8z*J~V^{Tc7s5ljZvwf~h@VC#UlmhPTUrvaYM{+tJ}WVs%5Mt#0RHjRP0FvhbAQFHOx%Ein%d!$y>Go+tDq(fy)1 zuUPRQSH7(uw(gcpehNW7E$s;_Wm^WYLgyLRY|&-9?qKDPu#6c9v|@)wU4`3q2v<24 zEW-OespYEzCV?Ikxo4H@_p>G>x&5ZuKgNFJ0egEdvOtYUT0DkpA;`<*uV0GmDQ3o<;ut63N z&w2NZS`+f;-4y2H?JleHHqsu1}{G%x-=S)N$lMzB`M-H77DgVcy(C)i8gaH#(cF`xvRznT$L1$kW8Y?qcBR9~0)JerN$ikyxn>9T2NZo7A}TL&9@vE52_-y|+8-f=c~3=LM~}AcI7WD>9=p@gA3jPT)3zN6xJbkbRu4(8q#q{hG@L9y$chi{a3oafGFc;hv8nivjrF~ z0E6zA{?k(zJqttkTZJ1p2;=DmcZOUh&i}pBgO9ne^w)Y3nDp#cKdb+;!xzY`b!(wG z==6u9-K6HLCFv$N0x^Q!=YQnE|N*(GLM}VzN;Ni=_*vK79L+5jP9)|x!~+=0|_C-Jy;@Ij88U{>C^Zv_776sb7wOS^x*BDC}<*qz_56O zY&K=TtMGykywL@;25$HA`TdT-uM0sI@GGU5a!lBJapAskl08MIjic7=+~5o>o^tfZ zGNbV`>T(F<>wNTMJZ=S)@p)2bx^48Y*^;xr#s3-Gvc0mQzIGbG28^5-LTXHbr9C<&{4CT}k-5m@#(Fi6Sd zt|raa@9N7kqoMaqeHkue8YsZm-~t*zf{YEhHW?o9#gHlw`1z6K$X1%6RIYGD6%1xz~$BIBHq*LKe6 z+_f6f*Vlk`u;pr&D4C*}&Q-wN0pnBx$e>c7Ud9IJqr^39t&-*JsP76vcki&p8_&dj z&s5Hr1;frLxka91FXV;~$3dElqrY?A;b^~eNh=%Gnc!>$Q{<(wXJ=@@L-XblC5Ycg z^PAK|=+h8nUJ9$_07&}%cy+6hXrfp*%6J8Ffqxy5ay-+FVsb=qy}={AS=CCzepL*S zSkCN!n!8;}`RCk8fy=c{YCkOvr%RB5#X$9H6%#2dY)jD&%&l0CQ>-9{l%WDyui1$* zk%jNZ@jahYrV@Ls*`f(*|G9PX^Z`9p#~1T5ezon0#W@i)A;Eplq;MJqi2}QHlV9|_ zCO)tUV}4I;TO!R49#5?4fE&9_wu>R;IS2X;(5IH`Z;aUwftPee1Birgv|VfHAA-Ip zO+@b7VmC_8D?gvGL5dknt60=@OXDeODh5>g7%_as3_D^b{$NB^O2rR01~?41CYt*T z*ZKeiT!&XEh!@q6BVouMmm@Fwn;Otdf8wcuqYdgpuDny@&_i6bRX~y>J+9~zGeExs z4PDGp530m&c9-EXFXzFljjs#Sj7?pPMq|0cO$LBf#Zq`4f|8gH-z-L>>EXc^4 z=`m9>#i8MX#L$_)huyc{2I)IbQh$iaCG3kDRhpb+LRN=q!O(zqM15Fwy7>z=z+9a> zPGaG;WArL2xM}_a9&k<{uvZ-%Rh)50p;J{Z(x4(c ztRyCX!MQoWk?v~GXJz6hXeh-dYJgk0ArikMVBhuRG{ZCx%cfQyphjxj#& zuV(-fJeOHq`jMfqHPf}^(eCL+C3pVtLT1!JOn8}bF)C6Gishf>i0?gvQZ#;0Cf9C; z>1aO=I0AIK>>1{%UG5^T$*1bG9hJJ=@f-UcT4D}!m1z7OaP&%j z*OC*5a^#e&C1!~l7wkl)F*e)daua;54-92JoHgAFvWGQ2Y>L9CrL19%5ygP;uc9;I z9v#~{)(@}-E^`FFr*fgjs7`XwtzvwbYevpzS$ff}u_{WR@ufNV%`bx!`!#C{ty7vR z+z$ZfU~w#q8tjQcvEPBx@dn*9G-%N=33vjvsac$HG6paKrWdD2F2n z00h48bd~wEmh8Suz{G!tyle2uw@3uWHR3IfsVeXg5%0qK{M zcD|~L%5rZMjSY$@Eh97HU(MZW8cW83xZX88UPnPmTN-oE>v_MCBk7A|ECA*a2)a~( zkH7$QYC(2`#kHpUS%O)`r>S=0^w-HV3^@%^zeQgjZV2a-PrA(hzGNJ$s zf@w>kCA-0PkYhc$U}PGzWd>=c&-f1+Ob zE;X!P&)KUgHPQr<6hsU{`BN&mS!BCS=D+ZcY>I=0Wae%3NQX+D_m@e%wxU0g2r;Y7 zb-J`@!zo(_%~iCJNpr&=Tb`8LyVc9l+6hZP%Q@sh)d}WM8_1{tJLHC#UpwS! zOd@;Q`UTN$V2M0`#PJQ7_G=z9QE1PP^b{iy z*Ksj0nxGu&>|zZe8U+>y(iN)V{*lrDmbX^|U3?Xet@Dh?NaAqc*vqdqi7d1+qsNvm zCWtI~iNbTOL3+XH_+qLjBej|RYeoGSMRy9_)dHtM80Q8O1k{&ueTtN-JpYDZ{|Ci+ zjvW=7Q_I|GS|b%h1>Yb{J<;HQ?w>8t$a=GpoJ6#CghHz!CAYe$I9W+6qd9k9&8>vk zwD9rQx?iO8UM1frC{R)cx+}_ZLB30W-h1CK40BURA{jQ`xCb>a0|0)zg!7ylly7k| z)@hZnFgl|u^4(9cBmnkdG&NXB$4MB@%jS4=x$}sg?Fa3R6 zSf0lYqiJA)`Gw%aH6r5Bw=KBq#J|rjZC6iIih=?p zv`E#?hw>SgyK#0G7=+6xbqbH+yXoB0ZTRFA{X``uFhG*|i08omPE36BLg-@8K3avA zGhXxvatKvT2R4Kn)=F~&W&C&iE|~(*aENv;+?hSTAFZze3|Po*P!vvPNkY$8E+01s zm>u*MR`Vk%YTUk#-1GcIy;IX@oi&sl9GG1Hhi1ndZb zD%=%yp+>qJ)%|A1%lXZ+LmzwP_6McP&O-QY8M&2K6nxJbmLTH9^4=O3D%R#v%`@QLw# zYjeNkB>`66{_!r_yTKhg5h?5U3GetB{<-p&GES$`+_!;c)|?DVrW78Y5EP3qY_2dd z>l+iDX$@f#%?7vZX})u8Y^B+uLy=o|1}yf4EmyVJV1`(v9+H$Lp0lWO;S z-m?4Vpmdxa?6dgE`JVwJQ72gkKfCbLw^9uxSI*ubh}0~cl$dg)yl z*l}bo*?zQ@y#w$wL!&Sdt_>eT$5L+>jc@y1rcRwqw`K8;=Z*_o5<){!$Fa`zL6@Nu ztgA<_LvI7d`0}|#v?8YGSpECGvak1|t*Xd?f8Sc9@_#q^%lsps-(&vrEx()mJ5|j# z0y*x(eVe8Sy@V&v$!aq+Rx2pgpH>p`B#aJ-1_&_jAb&*We3=aq{>P|rvQAEpO92n} zr6(K(qU6zy$8(INcDiVg%I}PMVltqi2LE1P$RH%c#sOc*XvQ4#`8#&zk)GT!^iyn0 z|4KEbM@1IHCdxfM6w%u&i!!@VGUin^&(xh+1v1x|o~f`G4W>4U8Uu9B=`-L@FMhcN z193_MrV9xqlm315M1Yy`3C;f*WT9TrC5h^a?bizo(6jm^4GgWs!d2#6Cq5gpMWzf+ z3SjaYooy(l{F~M8!k}yi9uHiTci-%G;}B5VO`W(Te2YDsu*qmiG+=Um4W!nB96?XtgK=9{b=6&FYm8YPB;-m#s4M1f)!2=-T#w>H1*Rc6*|AEwpHAMBJph4Tv+A->ydyK;}I+gB|DCJ~sGF^Fb0# z9^pXQ)+6BX za+w`8NK;b)^>4OjcolMpL^%lM>|burh^0C7vi@zc3g(Q89U}>*&jG`89?BLFH^nW# zIUl>y=RdY}$k;d$;+Wu`Dv*~V9^b$4J*!_-HZ! zb}rs-EuP2AoHYoaoKN?LZ}Rqk1QY#NHYO+pGg`<^$UHiNm)+h6{gdHY-*SJ%`9IXR>kEm*Km$t zO*0h$It3k46`mX5*$wB*>G|vK(xN${Kyi<8HUPxWJkJMlv$3#{ zwprlja|6XZ8(W8FZ^h{jeYdCI8ax}CRR7JB?D%~M4j2y>z~h&?`9nvkOsg77w#3X2 zN{h|O4YoE6%PB9I*$2%fIE7Fzs~C6g1|k^cwx;Ob^s!QzMV`=wPl66(Pw>lAG_`lt z8*nX_7!`GbRc<+OL;Y&jL z92q8Fcv`0Gujv{GW3`Hm&f?<3tg|{iFEz9DC}3(|eo2-3D7~%Wa1S6)?h-GJ#6(0d zmWvyrtf^F%4}neNqC$K9Mtkq0efttzLHXoua-nSe%NYOp*3Ay1cg$0~uY@S$>1H+! zgbNG;#H3)o3JahqJ&2~uqP}&eJ(Br+P+E+hZ`rL#rCvJwXp{!`IcS{%0;ti+BsImp zKui?|M_$rtR=rNjz6m(tU*-Fv#RnsPOTFXyiD917%<=v4f(`wiyw5{Ujh(LDaa}OX z8bcZRBm{ww4N6i*kRc4C@?1H+ibEx7ixHKk27d|I!aJc*xypTfVj4)Cwgu7xcqkYT zfKb0Y@(}hE3L0bA%y%&g9%K=oux-?HQhg$6qHnHA)tVtZg&8am`$7o6xLU6xcKsfn zs$x5Dwy&nF(p3Ej@~cdHd*N$f82x9cZo%b}_Haf^1aRfpL&Exg@tpnrH*DDRH z$}K1{(CSlF)2!ljpKSuwI`7K{0%Ft(o~S-b%jAB`9lm?LVms#?Ye9+q>n__!iAT?l zGHIAn7>$aa@3-OS6T2LQq4Ldb!$`+g1%|#&I7hqdWTWgb7>U8BZdESa({_X& zTCJ=3OBGoBaGa1hH~Jy4`^Ie%?ffi`Az7kNzd|&%0$X2SFNh^5oLXNovbBGfic*q* zHTyy|_Dc@@pPa42cp&eY!loO5-v8FBI7zwh4$P5_g1>ynwoDpvF3^m$vy+9Li_z57z_#Y*w7BT#(@>8Zx_U=J4X!ns))KLwFuBlMG!N*%35Ezjn|iP4pk3pJ!;CAel1u1qv451~ZzfA`16pch z_E673J^oNV{7M@$^CGgyo8tx^yP@T@94Xwkoyc8h;to9<3P$g~RPJ>!vp62iw^BH( zE$$Qca9W@?2Zl$cICLEH0D6(+lsYoK8<9d4*NjikyDr3%YJ??>hG{q&F&Sa8Bw0aZ5TQ7nqJ?nh$0$_bfIMjyFCU zZpd64v+Opznz}~R^0Kj(OdtdW1yPqE8uc?yHj71*@4lLhs2E#8FyOp`D+{F>k9A;7 zF0ZX3AB?gvlc-#UqR9xS4_J@R3$a`}k&_=o(hbJ~8x?tE?B9M?UESl`^QwBXdIiVl z(_3BCNt9R`__3a6@oLfSfF|McN0})HBf#wXEBws=Z+{F0*W$ z8Wd=P@ww)~eJ+D=7d8AjzGnzV`8yh7Bz6wHA=2i=$9J}M(a76X;NV-lc?UB3Qj|Us znZk|gOp{WPR&O^&Vk?mNSY_0u^hBtL{mE^ZJZ@*QNHvO3KV6BSyLl0zgj|4b-sx1^ zWrBb~ikea1CpKy%1($i5Z9L^Z9DzRQXQr>9<@gqfi1d|#J6>t!0Z)9udyJSMHTg(` zvF8Kvh}USo17g{KGhaXEo;C2}_p2-2XXUFS0yP0)G-C0!Q|?LqjExb$uLbHPA4xon zYN{s1$GAXFeTN|1ZNPzs%h9v$HOEPRpd#ikfaiQV+9sCYGeoLa5@T$3sOP6Bq?n&i z5LfLYN*YAb+pwLP~>!MRpYB*D?OSu(UX8)e>!V9@h*L~0wKe$9nKlif$;LIz1_=msUj3$k%X z6l_-sw6H^UrmJ*kiOT6CO(hB*ol+oaay*~Mw-8ln`xK?QQh920$DOtpE;kV|R+%!rZtLyRPSlV1%Vs^&QYlFcbXQ zo((0)l z&?<*v8KT~~7sZ&AEFFSoiA&Cb=@@$&fXp{HO$s&QfBGnTO2dUgCPs6TAlqrKDoL%? z7;9Vs+u8?MO=^KQdw9JD3Q(o}Jez`u1^R4Ut#ywaIw)^mr=V;7b@%?k&|{T`*;9}f zH%E%s5gsCJm{WKXty!03EYUV}<^;@Z91I%5h7G{g)R~Q98YKcfAGVu3x?4?`DD|Nr z!Zq^U*vMi@W=D?DPP;ArV?8E#LI^x zYTOq=x2kq^TDq-)BTdE_U)A-Jw+`++fM+|REqnT*tbzEBJa=_gIKP2Rl`%K&>N9SM zbR(=YdP{{qe$&25pnt z<8d^+dF-k8b*%>jLgAvhvJya|`&3>gZ zFoJ}Wyhj{o;nrA%Ph#pCF(NsQ^bgcSs)1n^jo4a4Km} zf8JM`ss9qB67a&fD6!&WS?O&o@c7I>NcBE+vg37AD6f zi$cJAJ%qCAEz8JPYy1%Lc5xYJcXoj!QDSE?Pw&Jv6Oiyi@eTwyjL(*#*Q-MPKS1Oo z0r}g9|G%pK|58;=$kl1JY%u)e?GVx?vPMSNTvTkLw0KOq$jIF8+OdObc1}0JvgUwl zy%k)`GKrWS`uT8(?h}9f?bRgWV~D1knfXg!os3mFLsvbYN@ic+W=LER7r=6Oz(x~m ze=3J({Ftx78n?dHH{%!tR&)nH=xnH^VMG0GV?8Nt&pJmnnO#Hz9mSzqo209+FX7J2 z7NgP^dV1%cq(Gz^A=JkZn?O}joZ)j9z({FaV(TD#ZHM?|LcU5s(Os>XAtQ~Sg zy6;{0XQ$q*^>MoDX8r7JU2ub3@6^(MR{rx}0(J+redr`HQt_?IP>-?86mDRlAm6J( zrw^Tt3!+sPpJ-Tvu*&Sz0y00@N27VXCn5tO&>o_KT%B4C|FW8REUG#!U~{>S|01GDF#DZ;nS ziq!Hy3)NFr{m+R0GrRud(XGG_{8mMek+yI6V>8$r1#V`6%2E7^r?h)&Dn;ZMXaqAt+G zmOH^Jh$-Aiq4c>$eDRS{pQolqJCv%=#F7q)Z%feJcFn8%x&@n!It)UO<=7perU2*Z z($;bIy@?&W3;SJEkHe~BS2EVG76Gifl~WZ1CCl!1Ie-qoA3i>@PiCp?bS zo_(V{oa}l0H~1MC{^S^WeEF(MhJ!BnG9qXsa~X;B^kbR=EX)pXqyjEN%72UB&ipc3 zCTO#9k_LYe4cw=J{#E@Jk=?6)W16JUw>Mgw|HXEx5Vb+qnjDefJYit z#N-n;@9i*~=L}g)9oPF}UE1)3eLFcWh*eBgr&gkjIATKg9`;N2a0D*|cxaRp6dg%w zo)!LK&narT4vYJuki0who#_fD4-bG*3JQT@)L;rgbW3c9a6i)Lv@W^RsB-%g&Co|% z-q(h3+SC6cfO}92c$)^RY%A9`%0+UI7Q5tAEK6;^O8_(ejC#8)NpjM)QBu4 zcDt*ntwNacdEfE{1+%QDLlF}|%P|%j*K%^718$R#5E*W?bsa8oOMUsJjAZI>#IyDD zh0Gn0s_xz$qkqFnT-R8`d4Z`g)=qr$yOusM<>312`l07)OM&ZeYU!?tX%-fKL1=Hv z$Si&%cPP)}g{5IIoT1xLROAE*oJ#u+M0&Ymk)9COL#em5#YSwze&2BTK3u|(u&_27 zS-V#)kvZlZMsJa|uYGsi;nF}kO8k-^y+~1$6C*D*f66b@p7gZX-uL=_Kfd~ zW-*i;-}(?_Brafoqa1*92&|9iEy!m^5smxOD1@K-zQd4Y+`f8X-i-8Lq48nLRLZGA zl7%09D3TQJKhTwHS_y~aDm9K=E;(vN&&h^Po1sEwThKACLn0ewJ(}ayc2yS1%8A$( ztgmMSIgt{UkRCVc!>PDiw79p*rpM|0$SX!BmPFlWbqbFe`r;%?0$D!7zN-f=xGNOx z%9$79U^KQ6hmlEN=mTUUc0mp^7N=W4ycA%{q!gtK+mH6(M>>2)k^DJ=B5XfZj3i6S z=Yp6m;%3uRv<4tW(uxx!Qte6pFGX-$b>tRTwZK$19-zc&9OIJn$Yy<_FhS$Uy0aM;?UaWO8$OXe ztQr=UQRCY_bO%BFJZLk|!bPT4fw{)$O2esV08W-#IbTxRZjFDm%_gHnDCjX`yYVS> z%A-BTXyE7ks@4REL%%;dxcXL8yr&4=gJ6xwf=@S!)>Wi_VZigA%#c6u3~^%5$7oO` z0X|09%|YXs9!J2Q2b_pz%)Ksw3wPXL$ivSBi4xs%`MITYtK(1&eL|hramdMp_KyO3wgfa` zji7pLMzegByevl3`_&$h15RbRo?e-x8nU?D0*BE9&wiy4V}h>7_SryL%b5e7MRdRU zr;h!*stVi2%Hf|m(9zA&VVC`AGYH<$?pb~_l}RoxrjN1whE&;E$Wl8vKE;3LESp&1 z;WiQC1_;im*5|F`>*+5Jfp-CJVNUxFFb?&4&Ry;g9H1IsC2Nb3b=jmI(Gw_=@<4pn7D=LpPOQQEzi`6!tk-}Bs7<#e8R~Mk+i~e> z*Ohoi9}_bhJ5U}k5gCkZGW_f|k@h%Z^e}ARb7`tR&kw&oaGuf{>=uIFg}tFqePq0C zu6=|&z6SKbJ9qxQ8ScLqm;c@3{HLe})YVoD*K4nzsx>$ez*Z-q3zzF+OFgFMkDXp+ z>#7Vwg1Ld{@XR2F$B%vS>iDPr`>B7k$^SD_23~goFxLR!KjFI%A0=yF)`+X0wzXjI zs{ee(|M4R%9aO0oi$ghy%NSfKaK^MHTTOiKM!UIBdt3vv5~~W9oN*qAoyP{xp#@+C z$PwgDWzJJVOIztzPUbeh!!)@@vmJLbNyo_B_@Ww%D;aUo$bKT^G|uyHn=p)w3n5r; zIY2Hg6RKJ&6%cEnAGYA7IS%sD*t8>IO^*xsCX(aX(8`jH>MgQGS-9&|y|if4;+ZjZ z1$xv@6N%OcRGS))m==5vj=z03v2WJ!Vw9PzXY&wWJOl&n-m9mEiw#)?ofp~wP+CszEe+r^VhvM`cb zq~0J=Y%o@3T87W_D@JUUlDxQ2TFPVlRwGaw%kDFyu}b#G&>&b1)O|KZ7v`Csk?G0OqlZSU*TEct(SX+1jEwE zB!f?icttngVan!-WNSov!6uHZRh&6Y<0Q*Br(ZeKJwEZ0iMmIw2*k~R(p$}(ayYsBNjG73l8fO#4j4CRB@ z63Ujc&^b^6ZW#I_cZ;(c*!B*uekzNK06gA9{rR)mW!9RvIiN!c&HM%7=5e$p={b*I zpsZ7bnYX}4A0zBcgU?VIMyj#&8(usFnlT3cM%`ZpoZrk%jtagb7-#HA+F*#O^q%gA zPPvk5if}SvI1Z=2o;VYzls-r7m+p#A6iqaJ!yiRxz4Z>R(-Wikx$LPxGUfGqPiz#pBSGLlUEmv1%ZB?P*qae!Q zOj@H#pThXyG8@=aznZ9~E>a?WPFtT0zZ}ozu9~Jqse9^|10O}CEDsFz2|7$rv)>l4 zqd!@wC&j%7xz?|CLvVIKrProK$bCG*8QAX2fMMo$+WAgpIDJDAN!tUdfBO*WDL&Cg z0Pf!mHnb(ZM@%D3Y|wvsOL{{nPIx!~Vk!$Z4&p*ga5!aM(IIXtEmGy$sG-ApD)g-L z=L=o2q65Z;4RBEzOxx#p%{pt<>r267vty!J?Qd+S)@p188>4nkd*+Av6p)TCpDUX* zKfG2pMNR`5TI~D9CqX^IXg+%li%=V?PGnh)-#=RjQb&emV3v$Y4xVi^>&vV*Nh!PZ zfGIN*L0aZ55T^yoN={FfrgB>L_`f?oo?ZUjzrEH1i|Zr>uiP(qw9}`pF43(Y68Ckl z)@6Ra+bG{eSLRoj*M98Lw1APGrP?<3>G^p&zmt>-p->RYZUTK-!|U$2DQf?(5zYKN zzbw=l6A2JrvS}5Rx$C*l5^_L(^ zOmH9Bt`D&^3}J*bqbT|U`>?V$>Gi+*v8sad#F*{-u3BXT<)K!%x)n>x0;+PT<0*#j zvr@8eqPJYMe7p0tLPD_UD|I;jfyYYg2;0@J991B_Cw<#Q=7%G``9V;f30=X+{hkrhBA7w_s!N9G`NWi%**4q)LoxGFWdtzhN(H93l@DQdyxu!S873Iy1Mhu;s z4-mTSeCIES(YRjTL!-@`Wq)_|z04yMU6DXH#@$~CwD)!umqMU}T%93zM`AQ>bGg5)F;Bnp%kesbHP=Jp&coDsQHc69&m0L?H+X*O3!NG+6CyG4}iOmzHvaPkf?b zP|FsV6rsGPMf;G8?#Zh+?||FWyUA;$u=5jE@D8K6>smI-qJEUZ#m8j2ug!HnH7K;h z-@tj@=gpSBlPoa8f@gxEH@a3Cc#>WYJ&~#dA=DZxiPIcPq!Dfxo^8~>_N!2ZE$-u| zx1`>?Hj;CWp*waHsrp@!rUbc=c}MKY>G1XX{@X&2V8EYXn6c7bVQ ztY4xd;zK(Up8h$B5})1yv>1%p-_f$`cc6k~DEoq|1C5wHT``XEO|RHfm2xy*TTWNF zyBu_?ikxGJSyogJClS-t|DQzu=O+<*eTlZ(uOC-ApkaZC5F9#Hq_>gWfDZAtsSdq- z-$SIkA8%)0jA)icLog(~0M$c$bmF_P8qGkv$XLKXH_JH2KMqP<0gLGjU@>)4Q-BSZ z#PG+CRfWE$JF#65AIn1eqn<=Ub9FA8l^#otreBcmZw%~KFm-B893dz`jcXq+aJRQ4 zUs(Hz`#sBX8|ZS&LS0H$*ybsj}XEklT_JefL z2#`uUJ0*%F`LMWCyShC^dDIeEwMYN>mD$%ujPfeGPTHQXa{5p{>4fy)@(E72 zcN|w(FgVTg_PM!Kdo<^14w8r$3OjnKG!$z+p!n^a+jYad@;5Hzl4kQ&L$7&ocV#m1 zT8H%{RUM-tu>FCxeLhLavF^8`yk|lCpR1lQet(e}AFD0Q=xxG)_ALwh!V+>Cky3({O z=t;640R17yR38+Mel^9`kMl~~w(OfHM%I|yFHO?Ytmc`#%N@Q%^S_&FS0=e(g?bE=n=UL z2R=w+5$?#R@PO8+%nS1(z%(6sS7)O+0uwnX513<{xY^rEWuS%#8{HxHy7u#x0zfQfw#WGw4FS z*l62$vVUJDg(~JmV>u)s+&tDi{X8=WzB7vrFGn{tkpz4dodex=csJ(WJGO3q#7vci z`xa%v+=ihS{jG}oO~AnaYF^M}bUiRNPAg6voP9BvSAf7hb$CaAew}`33w5x|djm5) z`6Gb_clx=fu6g+?KT5~tZa)@v5@D<%vx7h4#0wq9yxHspaavP^_4Cr?6YDfSo2;JG z5sq2x1;AF;mt5Kt2+KLH=-;PF99+$D44KnRF0&gSr|t$d z#DVOU@wD%Db_6@;cz+=-9Iqv_rE!#K8Lwk%#-(yeC-j%jm<7;d#3JVUl9 zogIHEuj^Khs!FvgV0$re4i%?KrqzwG(TA$X^NPiGZ6<8}mN2uyTnF`96^qE0Cw7Fh zkIC@bI=dhI{sp3X(LzZMm;b|)#RmXd7(N21e* zfn8U&-lwN(CfS<_$BcNgLyW5Qa@xv8$e%$C^mkx|$Qz6De`b9jrgoR_>)Za<_nzBS zWs=MPtJH^gN7P`Bt+%;achBj6d5``D+FSS(gLLsML#C0{4ms%<%TG zp~Vq9Rzr^V41v-f)^n~nd=J}Mq8xmiDW>374STK2V*TQc7lhpyt8akJ z)ud{$ohk<&=fTluTs=?jF8C^(1)BzryD6?6vvEJy+tzQX`@Kr7*RG9)=kv8iTmj(k zzxH3nyK~-7qmWV-a%TRU459d7lx8gnk|DVMkRgccnSSoT`gazg8fpflQ!jnsMPgYZ zYi9Mij&G_$+Gos9A&iIIE7D3=JcyxB z#*o|j1*e^KtI=kuZ|Z|jgX$~gjN@E9BJ4?rOHie6_Za(5lbO!%s7Hop4W9h(lOlKm z>(a=>_2^nOKfota{T<^blqaP!E16Bt3~!U^5)L$4??{LyX4`cTakvt6m2O@=ZyH0= zwzbc^pZqvjo{-4zNLug1VO3a+N=M>{PZ}GF$qKJh{2a`v`pFS2{McEy=Py-)Obw8M zZO-PxW}j3Yji$A$^)`iBNpdqgCAe)cA;{3-a2JRU%Bjl1=C<(bLM*r>WjW@1BNm?! zg(2uFkbpp26m7_5O(pO3nJEW3d9iS(DkYJN-Lac7vbWa6Ou;@h-a$0#3utHC|dX#|+jq>}54Gg1TruSv8dg z8YaxKsWKDWiCerRp9R<{ssWjR)NqUd?Wt8)s^A~vV`SWWdr}6CeBMu4D%Fj5Q*+R$ z^=f_^$|k_PFoz?|?cBTKQ3LdZZgO|#!oi>>W>3{q;)$H~H9jQ;>gXj|P8khpmF`)T zHiB-cvqYXQdiS^wi~TMz8&}#NMFv;_#8%(LP|IYi{5Q@OdapaPuYW6ZK^q<<6H*AF z;~C82BdrKM%D;?TR@SXIAMn1vNnfv9{c~d$hQmWymFrT?=%Q+Z;{@LD#-8i*xWjvu6>__!7++|e^24dXOk?y zFh#F^t9Wrpoe;;V6A5G^(Rm3D;ZD@6j~Qxbk2sn^N#65+BzYfwakm^=CC{C4Pa78P z9=upp!wy8tADP+P^^mxN% zr%|fSM^pSiDwD@VRzjB_e3`&f&uTQEv}yU21NV;3`psc2@A}_Lv?T2uzMU+z$h(kc ztTWUupH_v`dkx?`37>s+^r+39i&9;Tx`u&65@ z$__OHN1ZKf9B+I$`y{RgnP2ABtfN<@50!iz--S;WpVqyE$(HlhKHqIW+`dn^bV(vn z&ez|SyD&>w%HXnDbpYk21G(O}X1!e2v4SB+LgcKc6h9DRx5>cGa%Z}13fJ_t-wC7*%j{g zeSGC*WmBA>5v72$^gj>r_NCjnYV?OnTA85BZa(^_30{)ebF1N%2+u+~75^tvSmE#W zHc^LlTFa7KJ*WbmvWj6zRxm5z-9+T)9zuEE%3uZylT*YCwDxi1KY>=GS@6bOB#fXv z>pQ=Ph~?+8{Kt~>mupq+7%D>OJ1Q1!kVZoGgBi17e_OB0i11&~grnp^In@um6K*xT zeTu^i7B8;wU8=Z%yH`ople}W&l9>BUPRPljC9EYH!zD&9$sIj zUnUBFA1a0h&1 | grep -q "load"; then + color=${USER_INFO_THEME_PROMPT_COLOR_SUDO} + fi + fi + case "${POWERLINE_PROMPT_USER_INFO_MODE}" in + "sudo") + if [[ "${color}" == "${USER_INFO_THEME_PROMPT_COLOR_SUDO}" ]]; then + user_info="!" + fi + ;; + *) + if [[ -n "${SSH_CLIENT}" ]]; then + user_info="${USER_INFO_SSH_CHAR}${USER}@${HOSTNAME}" + else + user_info="${USER}" + fi + ;; + esac + [[ -n "${user_info}" ]] && echo "${user_info}|${color}" +} + +function __powerline_ruby_prompt { + local ruby_version="" + + if type_exists 'rvm'; then + ruby_version="$(rvm_version_prompt)" + elif type_exists 'rbenv'; then + ruby_version=$(rbenv_version_prompt) + fi + + [[ -n "${ruby_version}" ]] && echo "${RUBY_CHAR}${ruby_version}|${RUBY_THEME_PROMPT_COLOR}" +} + +function __powerline_python_venv_prompt { + local python_venv="" + + if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then + python_venv="${CONDA_DEFAULT_ENV}" + PYTHON_VENV_CHAR=${CONDA_PYTHON_VENV_CHAR} + elif [[ -n "${VIRTUAL_ENV}" ]]; then + python_venv=$(basename "${VIRTUAL_ENV}") + fi + + [[ -n "${python_venv}" ]] && echo "${PYTHON_VENV_CHAR}${python_venv}|${PYTHON_VENV_THEME_PROMPT_COLOR}" +} + +function __powerline_scm_prompt { + local color="" + local scm_prompt="" + + scm_prompt_vars + + if [[ "${SCM_NONE_CHAR}" != "${SCM_CHAR}" ]]; then + if [[ "${SCM_DIRTY}" -eq 3 ]]; then + color=${SCM_THEME_PROMPT_STAGED_COLOR} + elif [[ "${SCM_DIRTY}" -eq 2 ]]; then + color=${SCM_THEME_PROMPT_UNSTAGED_COLOR} + elif [[ "${SCM_DIRTY}" -eq 1 ]]; then + color=${SCM_THEME_PROMPT_DIRTY_COLOR} + else + color=${SCM_THEME_PROMPT_CLEAN_COLOR} + fi + if [[ "${SCM_GIT_CHAR}" == "${SCM_CHAR}" ]]; then + scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}" + fi + echo "${scm_prompt}${scm}|${color}" + fi +} + +function __powerline_cwd_prompt { + echo "$(pwd | sed "s|^${HOME}|~|")|${CWD_THEME_PROMPT_COLOR}" +} + +function __powerline_clock_prompt { + echo "$(date +"${THEME_CLOCK_FORMAT}")|${CLOCK_THEME_PROMPT_COLOR}" +} + +function __powerline_battery_prompt { + local color="" + local battery_status="$(battery_percentage 2> /dev/null)" + + if [[ -z "${battery_status}" ]] || [[ "${battery_status}" = "-1" ]] || [[ "${battery_status}" = "no" ]]; then + true + else + if [[ "$((10#${battery_status}))" -le 5 ]]; then + color="${BATTERY_STATUS_THEME_PROMPT_CRITICAL_COLOR}" + elif [[ "$((10#${battery_status}))" -le 25 ]]; then + color="${BATTERY_STATUS_THEME_PROMPT_LOW_COLOR}" + else + color="${BATTERY_STATUS_THEME_PROMPT_GOOD_COLOR}" + fi + ac_adapter_connected && battery_status="${BATTERY_AC_CHAR}${battery_status}" + echo "${battery_status}%|${color}" + fi +} + +function __powerline_in_vim_prompt { + if [ -n "$VIMRUNTIME" ]; then + echo "${IN_VIM_THEME_PROMPT_TEXT}|${IN_VIM_THEME_PROMPT_COLOR}" + fi +} + +function __powerline_left_segment { + local OLD_IFS="${IFS}"; IFS="|" + local params=( $1 ) + IFS="${OLD_IFS}" + local separator_char="${POWERLINE_LEFT_SEPARATOR}" + local separator="" + + if [[ "${SEGMENTS_AT_LEFT}" -gt 0 ]]; then + separator="$(set_color ${LAST_SEGMENT_COLOR} ${params[1]})${separator_char}${normal}" + fi + LEFT_PROMPT+="${separator}$(set_color - ${params[1]}) ${params[0]} ${normal}" + LAST_SEGMENT_COLOR=${params[1]} + (( SEGMENTS_AT_LEFT += 1 )) +} + +function __powerline_last_status_prompt { + [[ "$1" -ne 0 ]] && echo "${1}|${LAST_STATUS_THEME_PROMPT_COLOR}" +} + +function __powerline_prompt_command { + local last_status="$?" ## always the first + local separator_char="${POWERLINE_PROMPT_CHAR}" + + LEFT_PROMPT="" + SEGMENTS_AT_LEFT=0 + LAST_SEGMENT_COLOR="" + + ## left prompt ## + for segment in $POWERLINE_PROMPT; do + local info="$(__powerline_${segment}_prompt)" + [[ -n "${info}" ]] && __powerline_left_segment "${info}" + done + [[ "${last_status}" -ne 0 ]] && __powerline_left_segment $(__powerline_last_status_prompt ${last_status}) + [[ -n "${LEFT_PROMPT}" ]] && LEFT_PROMPT+="$(set_color ${LAST_SEGMENT_COLOR} -)${separator_char}${normal}" + + PS1="${LEFT_PROMPT} " + + ## cleanup ## + unset LAST_SEGMENT_COLOR \ + LEFT_PROMPT \ + SEGMENTS_AT_LEFT +} diff --git a/themes/powerline/powerline.theme.sh b/themes/powerline/powerline.theme.sh new file mode 100644 index 0000000..d396c04 --- /dev/null +++ b/themes/powerline/powerline.theme.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +source "$OSH/themes/powerline/powerline.base.sh" + +PROMPT_CHAR=${POWERLINE_PROMPT_CHAR:=""} +POWERLINE_LEFT_SEPARATOR=${POWERLINE_LEFT_SEPARATOR:=""} + +USER_INFO_SSH_CHAR=${POWERLINE_USER_INFO_SSH_CHAR:=" "} +USER_INFO_THEME_PROMPT_COLOR=32 +USER_INFO_THEME_PROMPT_COLOR_SUDO=202 + +PYTHON_VENV_CHAR=${POWERLINE_PYTHON_VENV_CHAR:="❲p❳ "} +CONDA_PYTHON_VENV_CHAR=${POWERLINE_CONDA_PYTHON_VENV_CHAR:="❲c❳ "} +PYTHON_VENV_THEME_PROMPT_COLOR=35 + +SCM_NONE_CHAR="" +SCM_GIT_CHAR=${POWERLINE_SCM_GIT_CHAR:=" "} +SCM_THEME_PROMPT_CLEAN="" +SCM_THEME_PROMPT_DIRTY="" +SCM_THEME_PROMPT_CLEAN_COLOR=25 +SCM_THEME_PROMPT_DIRTY_COLOR=88 +SCM_THEME_PROMPT_STAGED_COLOR=30 +SCM_THEME_PROMPT_UNSTAGED_COLOR=92 +SCM_THEME_PROMPT_COLOR=${SCM_THEME_PROMPT_CLEAN_COLOR} + +RVM_THEME_PROMPT_PREFIX="" +RVM_THEME_PROMPT_SUFFIX="" +RBENV_THEME_PROMPT_PREFIX="" +RBENV_THEME_PROMPT_SUFFIX="" +RUBY_THEME_PROMPT_COLOR=161 +RUBY_CHAR=${POWERLINE_RUBY_CHAR:="❲r❳ "} + +CWD_THEME_PROMPT_COLOR=240 + +LAST_STATUS_THEME_PROMPT_COLOR=52 + +CLOCK_THEME_PROMPT_COLOR=240 + +BATTERY_AC_CHAR=${BATTERY_AC_CHAR:="⚡"} +BATTERY_STATUS_THEME_PROMPT_GOOD_COLOR=70 +BATTERY_STATUS_THEME_PROMPT_LOW_COLOR=208 +BATTERY_STATUS_THEME_PROMPT_CRITICAL_COLOR=160 + +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:="%H:%M:%S"} + +IN_VIM_THEME_PROMPT_COLOR=245 +IN_VIM_THEME_PROMPT_TEXT="vim" + +POWERLINE_PROMPT=${POWERLINE_PROMPT:="user_info scm python_venv ruby cwd"} + +safe_append_prompt_command __powerline_prompt_command diff --git a/themes/primer/primer.theme.sh b/themes/primer/primer.theme.sh new file mode 100644 index 0000000..c9cdb35 --- /dev/null +++ b/themes/primer/primer.theme.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# based of the candy theme, but minimized by odbol +function prompt_command() { + PS1="$(clock_prompt) ${reset_color}${white}\w${reset_color}$(scm_prompt_info)${blue} →${bold_blue} ${reset_color} "; +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$blue"} +THEME_CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%I:%M:%S"} + +safe_append_prompt_command prompt_command diff --git a/themes/pro/pro.theme.sh b/themes/pro/pro.theme.sh new file mode 100644 index 0000000..1c7de29 --- /dev/null +++ b/themes/pro/pro.theme.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${green}✓" +SCM_THEME_PROMPT_PREFIX=" ${blue}scm:( " +SCM_THEME_PROMPT_SUFFIX="${blue} )" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${green}✓" +GIT_THEME_PROMPT_PREFIX="${green}git:( " +GIT_THEME_PROMPT_SUFFIX="${green} )" + +function git_prompt_info { + git_prompt_vars + echo -e "$SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_SUFFIX" +} + +function prompt() { + PS1="\h: \W $(scm_prompt_info)${reset_color} $ " +} + +safe_append_prompt_command prompt diff --git a/themes/pure/pure.theme.sh b/themes/pure/pure.theme.sh new file mode 100644 index 0000000..b75d3f8 --- /dev/null +++ b/themes/pure/pure.theme.sh @@ -0,0 +1,43 @@ +# scm theming +SCM_THEME_PROMPT_PREFIX="|" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${green}✓${normal}" +SCM_GIT_CHAR="${green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +### TODO: openSUSE has already colors enabled, check if those differs from stock +# LS colors, made with http://geoff.greer.fm/lscolors/ +# export LSCOLORS="Gxfxcxdxbxegedabagacad" +# export LS_COLORS='no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:' + +scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)$(scm_prompt_info)]" + fi +} + +pure_prompt() { + ps_host="${bold_blue}\h${normal}"; + ps_user="${green}\u${normal}"; + ps_user_mark="${green} $ ${normal}"; + ps_root="${red}\u${red}"; + ps_root_mark="${red} # ${normal}" + ps_path="${yellow}\w${normal}"; + + # make it work + case $(id -u) in + 0) PS1="$ps_root@$ps_host$(scm_prompt):$ps_path$ps_root_mark" + ;; + *) PS1="$ps_user@$ps_host$(scm_prompt):$ps_path$ps_user_mark" + ;; + esac +} + +safe_append_prompt_command pure_prompt diff --git a/themes/purity/purity.theme.sh b/themes/purity/purity.theme.sh new file mode 100644 index 0000000..fd8b60e --- /dev/null +++ b/themes/purity/purity.theme.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}⊘${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_THEME_PROMPT_PREFIX="${reset_color}( " +SCM_THEME_PROMPT_SUFFIX=" ${reset_color})" + +GIT_THEME_PROMPT_DIRTY=" ${bold_red}⊘${normal}" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +GIT_THEME_PROMPT_PREFIX="${reset_color}( " +GIT_THEME_PROMPT_SUFFIX=" ${reset_color})" + +STATUS_THEME_PROMPT_BAD="${bold_red}❯${reset_color}${normal} " +STATUS_THEME_PROMPT_OK="${bold_green}❯${reset_color}${normal} " + +function prompt_command() { + local ret_status="$( [ $? -eq 0 ] && echo -e "$STATUS_THEME_PROMPT_OK" || echo -e "$STATUS_THEME_PROMPT_BAD")" + PS1="\n${blue}\w $(scm_prompt_info)\n${ret_status} " +} + +safe_append_prompt_command prompt_command diff --git a/themes/rainbowbrite/rainbowbrite.theme.sh b/themes/rainbowbrite/rainbowbrite.theme.sh new file mode 100644 index 0000000..63c64b7 --- /dev/null +++ b/themes/rainbowbrite/rainbowbrite.theme.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# based off of n0qorg +# looks like, if you're in a git repo: +# ± ~/path/to (branch ✓) $ +# in glorious red / blue / yellow color scheme + +prompt_setter() { + # Save history + history -a + history -c + history -r + # displays user@server in purple + # PS1="$red$(scm_char) $purple\u@\h$reset_color:$blue\w$yellow$(scm_prompt_info)$(ruby_version_prompt) $black\$$reset_color " + # no user@server + PS1="$red$(scm_char) $blue\w$yellow$(scm_prompt_info)$(ruby_version_prompt) $black\$$reset_color " + PS2='> ' + PS4='+ ' +} + +safe_append_prompt_command prompt_setter + +SCM_NONE_CHAR='·' +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${green}✓" +SCM_THEME_PROMPT_PREFIX=" (" +SCM_THEME_PROMPT_SUFFIX="${yellow})" +RVM_THEME_PROMPT_PREFIX=" (" +RVM_THEME_PROMPT_SUFFIX=")" diff --git a/themes/rana/rana.theme.sh b/themes/rana/rana.theme.sh new file mode 100644 index 0000000..79fadfb --- /dev/null +++ b/themes/rana/rana.theme.sh @@ -0,0 +1,214 @@ +#!/usr/bin/env bash + +# Theme inspired on: +# - Ronacher's dotfiles (mitsuhikos) - http://github.com/mitsuhiko/dotfiles/tree/master/bash/ +# - Glenbot - http://theglenbot.com/custom-bash-shell-for-development/ +# - My extravagant zsh - http://stevelosh.com/blog/2010/02/my-extravagant-zsh-prompt/ +# - Monokai colors - http://monokai.nl/blog/2006/07/15/textmate-color-theme/ +# - Bash_it modern theme +# +# by Rana Amrit Parth + +# For the real Monokai colors you should add these to your .XDefaults or +# terminal configuration: +#! ----------------------------------------------------------- TERMINAL COLORS +#! monokai - http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/ +#*background: #272822 +#*foreground: #E2DA6E +#*color0: black +#! mild red +#*color1: #CD0000 +#! light green +#*color2: #A5E02D +#! orange (yellow) +#*color3: #FB951F +#! "dark" blue +#*color4: #076BCC +#! hot pink +#*color5: #F6266C +#! cyan +#*color6: #64D9ED +#! gray +#*color7: #E5E5E5 + +# ----------------------------------------------------------------- DEF COLOR +RCol='\e[0m' # Text Reset + +# Regular +Bla='\e[0;30m'; +Red='\e[0;31m'; +Gre='\e[0;32m'; +Yel='\e[0;33m'; +Blu='\e[0;34m'; +Pur='\e[0;35m'; +Cya='\e[0;36m'; +Whi='\e[0;37m'; + +# Bold +BBla='\e[1;30m'; +BRed='\e[1;31m'; +BYel='\e[1;33m'; +BGre='\e[1;32m'; +BBlu='\e[1;34m'; +BPur='\e[1;35m'; +BCya='\e[1;36m'; +BWhi='\e[1;37m'; + +# High Intensity +IBla='\e[0;90m'; +IRed='\e[0;91m'; +IGre='\e[0;92m'; +IYel='\e[0;93m'; +IBlu='\e[0;94m'; +IPur='\e[0;95m'; +ICya='\e[0;96m'; +IWhi='\e[0;97m'; + +# ----------------------------------------------------------------- COLOR CONF +D_DEFAULT_COLOR="${Whi}" +D_INTERMEDIATE_COLOR="${BWhi}" +D_USER_COLOR="${Yel}" +D_SUPERUSER_COLOR="${Red}" +D_MACHINE_COLOR="${IYel}" +D_DIR_COLOR="${Gre}" +D_GIT_COLOR="${BBlu}" +D_SCM_COLOR="${BYel}" +D_BRANCH_COLOR="${BYel}" +D_CHANGES_COLOR="${Whi}" +D_CMDFAIL_COLOR="${Red}" +D_VIMSHELL_COLOR="${Cya}" + +# ------------------------------------------------------------------ FUNCTIONS +case $TERM in + xterm*) + TITLEBAR="\033]0;\w\007" + ;; + *) + TITLEBAR="" + ;; +esac + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ]; + then + echo "${D_INTERMEDIATE_COLOR}on ${D_VIMSHELL_COLOR}\ +vim shell${D_DEFAULT_COLOR} " + fi +} + +mitsuhikos_lastcommandfailed() { + code=$? + if [ $code != 0 ]; + then + echo "${D_INTERMEDIATE_COLOR}exited ${D_CMDFAIL_COLOR}\ +$code ${D_DEFAULT_COLOR}" + fi +} + +# vcprompt for scm instead of oh-my-bash default +demula_vcprompt() { + if [ ! -z "$VCPROMPT_EXECUTABLE" ]; + then + local D_VCPROMPT_FORMAT="on ${D_SCM_COLOR}%s${D_INTERMEDIATE_COLOR}:\ +${D_BRANCH_COLOR}%b %r ${D_CHANGES_COLOR}%m%u ${D_DEFAULT_COLOR}" + $VCPROMPT_EXECUTABLE -f "$D_VCPROMPT_FORMAT" + fi +} + +# checks if the plugin is installed before calling battery_charge +safe_battery_charge() { + if [ -e "${OSH}/plugins/battery/battery.plugin.sh" ]; + then + battery_charge + fi +} + +prompt_git() { + local s=''; + local branchName=''; + + # Check if the current directory is in a Git repository. + if [ $(git rev-parse --is-inside-work-tree &>/dev/null; echo "${?}") == '0' ]; then + + # check if the current directory is in .git before running git checks + if [ "$(git rev-parse --is-inside-git-dir 2> /dev/null)" == 'false' ]; then + + # Ensure the index is up to date. + git update-index --really-refresh -q &>/dev/null; + + # Check for uncommitted changes in the index. + if ! $(git diff --quiet --ignore-submodules --cached); then + s+='+'; + fi; + + # Check for unstaged changes. + if ! $(git diff-files --quiet --ignore-submodules --); then + s+='!'; + fi; + + # Check for untracked files. + if [ -n "$(git ls-files --others --exclude-standard)" ]; then + s+='?'; + fi; + + # Check for stashed files. + if $(git rev-parse --verify refs/stash &>/dev/null); then + s+='$'; + fi; + + fi; + + # Get the short symbolic ref. + # If HEAD isn’t a symbolic ref, get the short SHA for the latest commit + # Otherwise, just give up. + branchName="$(git symbolic-ref --quiet --short HEAD 2> /dev/null || \ + git rev-parse --short HEAD 2> /dev/null || \ + echo '(unknown)')"; + + [ -n "${s}" ] && s=" [${s}]"; + + echo -e "${1}${branchName}${Cya}${s}"; + else + return; + fi; +} + +# -------------------------------------------------------------- PROMPT OUTPUT +prompt() { + local LAST_COMMAND_FAILED=$(mitsuhikos_lastcommandfailed) + local SAVE_CURSOR='\033[s' + local RESTORE_CURSOR='\033[u' + local MOVE_CURSOR_RIGHTMOST='\033[500C' + local MOVE_CURSOR_5_LEFT='\033[5D' + + if [ $(uname) = "Linux" ]; + then + PS1="${TITLEBAR} +${SAVE_CURSOR}${MOVE_CURSOR_RIGHTMOST}${MOVE_CURSOR_5_LEFT}\ +$(safe_battery_charge)${RESTORE_CURSOR}\ +${D_USER_COLOR}\u ${D_INTERMEDIATE_COLOR}\ +at ${D_MACHINE_COLOR}\h ${D_INTERMEDIATE_COLOR}\ +in ${D_DIR_COLOR}\w ${D_INTERMEDIATE_COLOR}\ +$(prompt_git "$D_INTERMEDIATE_COLOR on $D_GIT_COLOR")\ +${LAST_COMMAND_FAILED}\ +$(demula_vcprompt)\ +$(is_vim_shell) +${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" + else + PS1="${TITLEBAR} +${D_USER_COLOR}\u ${D_INTERMEDIATE_COLOR}\ +at ${D_MACHINE_COLOR}\h ${D_INTERMEDIATE_COLOR}\ +in ${D_DIR_COLOR}\w ${D_INTERMEDIATE_COLOR}\ +$(prompt_git "$D_INTERMEDIATE_COLOR on $D_GIT_COLOR")\ +${LAST_COMMAND_FAILED}\ +$(demula_vcprompt)\ +$(is_vim_shell)\ +$(safe_battery_charge) +${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" + fi + + PS2="${D_INTERMEDIATE_COLOR}$ ${D_DEFAULT_COLOR}" +} + +# Runs prompt (this bypasses oh-my-bash $PROMPT setting) +safe_append_prompt_command prompt diff --git a/themes/rjorgenson/rjorgenson.theme.sh b/themes/rjorgenson/rjorgenson.theme.sh new file mode 100644 index 0000000..e866f0e --- /dev/null +++ b/themes/rjorgenson/rjorgenson.theme.sh @@ -0,0 +1,100 @@ +# port of zork theme + +# set colors for use throughout the prompt +# i like things consistent +BRACKET_COLOR=${blue} +STRING_COLOR=${green} + +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${STRING_COLOR}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +#Mysql Prompt +export MYSQL_PS1="(\u@\h) [\d]> " + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +__my_rvm_ruby_version() { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + local full="$version$gemset" + [ "$full" != "" ] && echo "${BRACKET_COLOR}[${STRING_COLOR}$full${BRACKET_COLOR}]${normal}" +} + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "${BRACKET_COLOR}[${STRING_COLOR}vim shell${BRACKET_COLOR}]${normal}" + fi +} + +function is_integer() { # helper function for todo-txt-count + [ "$1" -eq "$1" ] > /dev/null 2>&1 + return $? +} + +todo_txt_count() { + if `hash todo.sh 2>&-`; then # is todo.sh installed + count=`todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+) tasks shown" | awk '{ print $4 }'` + if is_integer $count; then # did we get a sane answer back + echo "${BRACKET_COLOR}[${STRING_COLOR}T:$count${BRACKET_COLOR}]$normal" + fi + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "${BRACKET_COLOR}[${CHAR}${BRACKET_COLOR}][${STRING_COLOR}$(scm_prompt_info)${BRACKET_COLOR}]$normal" + fi +} + +my_prompt_char() { + if [[ $OSTYPE =~ "darwin" ]]; then + echo "${BRACKET_COLOR}➞ ${normal}" + else + echo "${BRACKET_COLOR}➞ ${normal}" + fi +} + +prompt() { + + my_ps_host="${STRING_COLOR}\h${normal}"; + my_ps_user="${STRING_COLOR}\u${normal}"; + my_ps_root="${bold_red}\u${normal}"; + my_ps_path="${STRING_COLOR}\w${normal}"; + + # nice prompt + case "`id -u`" in + 0) PS1="${TITLEBAR}${BRACKET_COLOR}┌─[$my_ps_root${BRACKET_COLOR}][$my_ps_host${BRACKET_COLOR}]$(modern_scm_prompt)$(__my_rvm_ruby_version)${BRACKET_COLOR}[${STRING_COLOR}\w${BRACKET_COLOR}]$(is_vim_shell) +${BRACKET_COLOR}└─$(my_prompt_char)${normal}" + ;; + *) PS1="${TITLEBAR}${BRACKET_COLOR}┌─[$my_ps_user${BRACKET_COLOR}][$my_ps_host${BRACKET_COLOR}]$(modern_scm_prompt)$(__my_rvm_ruby_version)${BRACKET_COLOR}[${STRING_COLOR}\w${BRACKET_COLOR}]$(is_vim_shell) +${BRACKET_COLOR}└─$(todo_txt_count)$(my_prompt_char)" + ;; + esac +} + +PS2="└─$(my_prompt_char)" + + + +safe_append_prompt_command prompt diff --git a/themes/roderik/roderik.theme.sh b/themes/roderik/roderik.theme.sh new file mode 100644 index 0000000..8a1c104 --- /dev/null +++ b/themes/roderik/roderik.theme.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +export GIT_PS1_SHOWDIRTYSTATE=true +export GIT_PS1_SHOWUNTRACKEDFILES=true +export GIT_PS1_SHOWSTASHSTATE=true + +export PROMPT_DIRTRIM=3 + +function prompt_command() { + if [[ ${EUID} == 0 ]] ; then + PS1="[$(clock_prompt)]${yellow}[${red}\u@\h ${green}\w${yellow}]${red}$(__git_ps1 "(%s)")${normal}\\$ " + else + PS1="[$(clock_prompt)]${yellow}[${cyan}\u@\h ${green}\w${yellow}]${red}$(__git_ps1 "(%s)")${normal}\\$ " + fi +} + +safe_append_prompt_command prompt_command diff --git a/themes/sexy/sexy.theme.sh b/themes/sexy/sexy.theme.sh new file mode 100644 index 0000000..60e00ec --- /dev/null +++ b/themes/sexy/sexy.theme.sh @@ -0,0 +1,46 @@ +# Sexy Bash Prompt, inspired by "Extravagant Zsh Prompt" +# Screenshot: http://cloud.gf3.ca/M5rG +# A big thanks to \amethyst on Freenode + +if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then export TERM=gnome-256color +elif [[ $TERM != dumb ]] && infocmp xterm-256color >/dev/null 2>&1; then export TERM=xterm-256color +fi + +if tput setaf 1 &> /dev/null; then + if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then + MAGENTA=$(tput setaf 9) + ORANGE=$(tput setaf 172) + GREEN=$(tput setaf 190) + PURPLE=$(tput setaf 141) + WHITE=$(tput setaf 0) + else + MAGENTA=$(tput setaf 5) + ORANGE=$(tput setaf 4) + GREEN=$(tput setaf 2) + PURPLE=$(tput setaf 1) + WHITE=$(tput setaf 7) + fi + BOLD=$(tput bold) + RESET=$(tput sgr0) +else + MAGENTA="\033[1;31m" + ORANGE="\033[1;33m" + GREEN="\033[1;32m" + PURPLE="\033[1;35m" + WHITE="\033[1;37m" + BOLD="" + RESET="\033[m" +fi + +parse_git_dirty () { + [[ $(git status 2> /dev/null | tail -n1 | cut -c 1-17) != "nothing to commit" ]] && echo "*" +} +parse_git_branch () { + git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e "s/* \(.*\)/\1$(parse_git_dirty)/" +} + +function prompt_command() { + PS1="\[${BOLD}${MAGENTA}\]\u \[$WHITE\]at \[$ORANGE\]\h \[$WHITE\]in \[$GREEN\]\w\[$WHITE\]\$([[ -n \$(git branch 2> /dev/null) ]] && echo \" on \")\[$PURPLE\]\$(parse_git_branch)\[$WHITE\]\n\$ \[$RESET\]" +} + +safe_append_prompt_command prompt_command diff --git a/themes/simple/simple.theme.sh b/themes/simple/simple.theme.sh new file mode 100644 index 0000000..999cfe6 --- /dev/null +++ b/themes/simple/simple.theme.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# prompt themeing + +#added TITLEBAR for updating the tab and window titles with the pwd +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +function prompt_command() { + PS1="${TITLEBAR}${orange}${reset_color}${green}\w${bold_blue}\[\$(scm_prompt_info)\]${normal} " +} + +# scm themeing +SCM_THEME_PROMPT_DIRTY=" ✗" +SCM_THEME_PROMPT_CLEAN=" ✓" +SCM_THEME_PROMPT_PREFIX="(" +SCM_THEME_PROMPT_SUFFIX=")" + +safe_append_prompt_command prompt_command diff --git a/themes/sirup/sirup.theme.sh b/themes/sirup/sirup.theme.sh new file mode 100644 index 0000000..38fcab4 --- /dev/null +++ b/themes/sirup/sirup.theme.sh @@ -0,0 +1,22 @@ +# For unstaged(*) and staged(+) values next to branch name in __git_ps1 +GIT_PS1_SHOWDIRTYSTATE="enabled" + +function rvm_version_prompt { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + + [ "$version" == "1.9.2" ] && version="" + + local full="$version$gemset" + + [ "$full" != "" ] && echo "$full" +} + +function prompt_command() { + # Check http://github.com/Sirupsen/dotfiles for screenshot + PS1="$blue\W/$bold_blue$(rvm_version_prompt)$bold_green$(__git_ps1 " (%s)") ${normal}$ " +} + +safe_append_prompt_command prompt_command diff --git a/themes/slick/slick.theme.sh b/themes/slick/slick.theme.sh new file mode 100644 index 0000000..aafdc25 --- /dev/null +++ b/themes/slick/slick.theme.sh @@ -0,0 +1,86 @@ +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_cyan}±${normal}" +SCM_SVN_CHAR="${bold_green}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +#Mysql Prompt +export MYSQL_PS1="(\u@\h) [\d]> " + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +__my_rvm_ruby_version() { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + local full="$version$gemset" + [ "$full" != "" ] && echo "[$full]" +} + +__my_venv_prompt() { + if [ ! -z "$VIRTUAL_ENV" ] + then + echo "[${blue}@${normal}${VIRTUAL_ENV##*/}]" + fi +} + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$(scm_prompt_info)]" + fi +} + +prompt() { + + case $HOSTNAME in + "clappy"* ) my_ps_host="${green}\h${normal}"; + ;; + "icekernel") my_ps_host="${red}\h${normal}"; + ;; + * ) my_ps_host="${green}\h${normal}"; + ;; + esac + + my_ps_user="\[\033[01;32m\]\u\[\033[00m\]"; + my_ps_root="\[\033[01;31m\]\u\[\033[00m\]"; + my_ps_path="\[\033[01;36m\]\w\[\033[00m\]"; + + # nice prompt + case "`id -u`" in + 0) PS1="${TITLEBAR}[$my_ps_root][$my_ps_host]$(modern_scm_prompt)$(__my_rvm_ruby_version)[${cyan}\w${normal}]$(is_vim_shell) +$ " + ;; + *) PS1="${TITLEBAR}[$my_ps_user][$my_ps_host]$(modern_scm_prompt)$(__my_rvm_ruby_version)$(__my_venv_prompt)[${cyan}\w${normal}]$(is_vim_shell) +$ " + ;; + esac +} + +PS2="> " + + + +safe_append_prompt_command prompt diff --git a/themes/standard/standard.theme.sh b/themes/standard/standard.theme.sh new file mode 100644 index 0000000..561a97c --- /dev/null +++ b/themes/standard/standard.theme.sh @@ -0,0 +1,24 @@ +# scm themeing +SCM_THEME_PROMPT_DIRTY="×" +SCM_THEME_PROMPT_CLEAN="✓" +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +# TODO: need a check for OS before adding this to the prompt +# ${debian_chroot:+($debian_chroot)} + +#added TITLEBAR for updating the tab and window titles with the pwd +case $TERM in + xterm*) + TITLEBAR='\[\033]0;\w\007\]' + ;; + *) + TITLEBAR="" + ;; +esac + +function prompt_command() { + PROMPT='${green}\u${normal}@${green}\h${normal}:${blue}\w${normal}${red}$(prompt_char)$(git_prompt_info)${normal}\$ ' +} + +safe_append_prompt_command prompt_command diff --git a/themes/tonka/tonka.theme.sh b/themes/tonka/tonka.theme.sh new file mode 100644 index 0000000..e97a571 --- /dev/null +++ b/themes/tonka/tonka.theme.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +__tonka_time() { + THEME_CLOCK_FORMAT="%H%M" + clock_prompt +} + +__tonka_date() { + THEME_CLOCK_FORMAT="%a,%d %b %y" + clock_prompt +} + +__tonka_clock() { + local LIGHT_BLUE="\[\033[1;34m\]" + if [[ "${THEME_SHOW_CLOCK}" = "true" ]]; then + echo "$(__tonka_time)${LIGHT_BLUE}:$(__tonka_date)${LIGHT_BLUE}:" + fi +} + +prompt_setter() { + +# Named "Tonka" because of the colour scheme +local WHITE="\[\033[1;37m\]" +local LIGHT_BLUE="\[\033[1;34m\]" +local YELLOW="\[\033[1;33m\]" +local NO_COLOUR="\[\033[0m\]" + +case $TERM in + xterm*|rxvt*) + TITLEBAR='\[\033]0;\u@\h:\w\007\]' + ;; + *) + TITLEBAR="" + ;; +esac + +PS1="$TITLEBAR\ +$YELLOW-$LIGHT_BLUE-(\ +$YELLOW\u$LIGHT_BLUE@$YELLOW\h\ +$LIGHT_BLUE)-(\ +$YELLOW\$PWD\ +$LIGHT_BLUE)-$YELLOW-\ +\n\ +$YELLOW-$LIGHT_BLUE-(\ +$(__tonka_clock)\ +$WHITE\$ $LIGHT_BLUE)-$YELLOW-$NO_COLOUR " + +PS2="$LIGHT_BLUE-$YELLOW-$YELLOW-$NO_COLOUR " + +} + +safe_append_prompt_command prompt_setter + +THEME_SHOW_CLOCK=${THEME_SHOW_CLOCK:-"true"} +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"\[\033[1;33m\]"} + +export PS3=">> " + +LS_COLORS='no=00:fi=00:di=00;33:ln=01;36:pi=40;34:so=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.deb=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.mpg=01;37:*.avi=01;37:*.gl=01;37:*.dl=01;37:'; + +export LS_COLORS diff --git a/themes/tonotdo/tonotdo.theme.sh b/themes/tonotdo/tonotdo.theme.sh new file mode 100644 index 0000000..347e586 --- /dev/null +++ b/themes/tonotdo/tonotdo.theme.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +SCM_THEME_PROMPT_PREFIX=" ${purple}" +SCM_THEME_PROMPT_SUFFIX=" ${normal}" +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${green}✓" +SCM_GIT_SHOW_DETAILS="false" + +function prompt_command() { + PS1="${yellow}\u${normal}${cyan}@\h${normal}${purple} ${normal}${green}\w${normal}$(scm_prompt_info)> " +} + +safe_append_prompt_command prompt_command diff --git a/themes/tylenol/tylenol.theme.sh b/themes/tylenol/tylenol.theme.sh new file mode 100644 index 0000000..a48dceb --- /dev/null +++ b/themes/tylenol/tylenol.theme.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# +# Based on 'bobby' theme with the addition of virtualenv_prompt +# + +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${green}✓" +SCM_THEME_PROMPT_PREFIX=" ${yellow}|${reset_color}" +SCM_THEME_PROMPT_SUFFIX="${yellow}|" + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="|" +VIRTUALENV_THEME_PROMPT_PREFIX='|' +VIRTUALENV_THEME_PROMPT_SUFFIX='|' + +function prompt_command() { + PS1="\n${green}$(virtualenv_prompt)${red}$(ruby_version_prompt) ${reset_color}\h ${orange}in ${reset_color}\w\n${yellow}$(scm_char)$(scm_prompt_info) ${yellow}→${white} " +} + +safe_append_prompt_command prompt_command diff --git a/themes/wanelo/wanelo.theme.sh b/themes/wanelo/wanelo.theme.sh new file mode 100644 index 0000000..437fd32 --- /dev/null +++ b/themes/wanelo/wanelo.theme.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +SCM_THEME_PROMPT_DIRTY=" ${red}✗" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" +SCM_THEME_PROMPT_PREFIX=" |" +SCM_THEME_PROMPT_SUFFIX="${green}|" + +GIT_THEME_PROMPT_DIRTY=" ${red}✗" +GIT_THEME_PROMPT_CLEAN=" ${bold_green}✓" +GIT_THEME_PROMPT_PREFIX=" ${green}|" +GIT_THEME_PROMPT_SUFFIX="${green}|" + +RVM_THEME_PROMPT_PREFIX="|" +RVM_THEME_PROMPT_SUFFIX="|" + +function prompt_command() { + if [ $? -eq 0 ]; then + status=❤️ + else + status=💔 + fi + PS1="\n${yellow}$(ruby_version_prompt) ${purple}\h ${reset_color}in ${green}\w $status \n${bold_cyan} ${blue}|$(clock_prompt)|${green}$(scm_prompt_info) ${green}→${reset_color} " +} + +THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$blue"} + +PROMPT_COMMAND=prompt_command; diff --git a/themes/zitron/zitron.theme.sh b/themes/zitron/zitron.theme.sh new file mode 100644 index 0000000..56b7bfa --- /dev/null +++ b/themes/zitron/zitron.theme.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# zitron theme by Florian Baumann + +## git-theme +# feel free to change git chars. +GIT_THEME_PROMPT_DIRTY="${bold_yellow}*${normal}" +GIT_THEME_PROMPT_CLEAN="" +GIT_THEME_PROMPT_PREFIX="" +GIT_THEME_PROMPT_SUFFIX="" + +## ls colors +# thanks a lot to http://geoff.greer.fm/lscolors/ +export LSCOLORS="Gxfxcxdxbxegedabagacad" +export LS_COLORS="no=00:fi=00:di=01;33:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;34:*.svg=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:" + +function prompt_command() { + ## look-a-like + # user:host:pwd git-branch(*)$ + # for example: + # noqqe:deathstar:themes master*$ + PS1="${no_color}\u:$(hostname)${normal}:${bold_yellow}\W/${normal} $(git_prompt_info)${reset_color}$ " +} + +safe_append_prompt_command prompt_command diff --git a/themes/zork/zork.theme.sh b/themes/zork/zork.theme.sh new file mode 100644 index 0000000..75bc17d --- /dev/null +++ b/themes/zork/zork.theme.sh @@ -0,0 +1,97 @@ +SCM_THEME_PROMPT_PREFIX="" +SCM_THEME_PROMPT_SUFFIX="" + +SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" +SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓${normal}" +SCM_GIT_CHAR="${bold_green}±${normal}" +SCM_SVN_CHAR="${bold_cyan}⑆${normal}" +SCM_HG_CHAR="${bold_red}☿${normal}" + +#Mysql Prompt +export MYSQL_PS1="(\u@\h) [\d]> " + +case $TERM in + xterm*) + TITLEBAR="\[\033]0;\w\007\]" + ;; + *) + TITLEBAR="" + ;; +esac + +PS3=">> " + +__my_rvm_ruby_version() { + local gemset=$(echo $GEM_HOME | awk -F'@' '{print $2}') + [ "$gemset" != "" ] && gemset="@$gemset" + local version=$(echo $MY_RUBY_HOME | awk -F'-' '{print $2}') + local full="$version$gemset" + [ "$full" != "" ] && echo "[$full]" +} + +is_vim_shell() { + if [ ! -z "$VIMRUNTIME" ] + then + echo "[${cyan}vim shell${normal}]" + fi +} + +modern_scm_prompt() { + CHAR=$(scm_char) + if [ $CHAR = $SCM_NONE_CHAR ] + then + return + else + echo "[$(scm_char)][$(scm_prompt_info)]" + fi +} + +# show chroot if exist +chroot(){ + if [ -n "$debian_chroot" ] + then + my_ps_chroot="${bold_cyan}$debian_chroot${normal}"; + echo "($my_ps_chroot)"; + fi + } + +# show virtualenvwrapper +my_ve(){ + if [ -n "$VIRTUAL_ENV" ] + then + my_ps_ve="${bold_purple}$ve${normal}"; + echo "($my_ps_ve)"; + fi + echo ""; + } + +prompt() { + + my_ps_host="${green}\h${normal}"; + # yes, these are the the same for now ... + my_ps_host_root="${green}\h${normal}"; + + my_ps_user="${bold_green}\u${normal}" + my_ps_root="${bold_red}\u${normal}"; + + if [ -n "$VIRTUAL_ENV" ] + then + ve=`basename $VIRTUAL_ENV`; + fi + + # nice prompt + case "`id -u`" in + 0) PS1="${TITLEBAR}┌─$(my_ve)$(chroot)[$my_ps_root][$my_ps_host_root]$(modern_scm_prompt)$(__my_rvm_ruby_version)[${cyan}\w${normal}]$(is_vim_shell) +└─▪ " + ;; + *) PS1="${TITLEBAR}┌─$(my_ve)$(chroot)[$my_ps_user][$my_ps_host]$(modern_scm_prompt)$(__my_rvm_ruby_version)[${cyan}\w${normal}]$(is_vim_shell) +└─▪ " + ;; + esac +} + +PS2="└─▪ " + + + +safe_append_prompt_command prompt diff --git a/tools/git-prompt.sh b/tools/git-prompt.sh new file mode 100644 index 0000000..c6cbef3 --- /dev/null +++ b/tools/git-prompt.sh @@ -0,0 +1,534 @@ +# bash/zsh git prompt support +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Distributed under the GNU General Public License, version 2.0. +# +# This script allows you to see repository status in your prompt. +# +# To enable: +# +# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-prompt.sh +# 3a) Change your PS1 to call __git_ps1 as +# command-substitution: +# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' +# ZSH: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' +# the optional argument will be used as format string. +# 3b) Alternatively, for a slightly faster prompt, __git_ps1 can +# be used for PROMPT_COMMAND in Bash or for precmd() in Zsh +# with two parameters,
 and , which are strings
+#        you would put in $PS1 before and after the status string
+#        generated by the git-prompt machinery.  e.g.
+#        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#          will show username, at-sign, host, colon, cwd, then
+#          various status string, followed by dollar and SP, as
+#          your prompt.
+#        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
+#          will show username, pipe, then various status string,
+#          followed by colon, cwd, dollar and SP, as your prompt.
+#        Optionally, you can supply a third argument with a printf
+#        format string to finetune the output of the branch status
+#
+# The repository status will be displayed only if you are currently in a
+# git repository. The %s token is the placeholder for the shown status.
+#
+# The prompt status always includes the current branch name.
+#
+# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
+# unstaged (*) and staged (+) changes will be shown next to the branch
+# name.  You can configure this per-repository with the
+# bash.showDirtyState variable, which defaults to true once
+# GIT_PS1_SHOWDIRTYSTATE is enabled.
+#
+# You can also see if currently something is stashed, by setting
+# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+# then a '$' will be shown next to the branch name.
+#
+# If you would like to see if there're untracked files, then you can set
+# GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
+# files, then a '%' will be shown next to the branch name.  You can
+# configure this per-repository with the bash.showUntrackedFiles
+# variable, which defaults to true once GIT_PS1_SHOWUNTRACKEDFILES is
+# enabled.
+#
+# If you would like to see the difference between HEAD and its upstream,
+# set GIT_PS1_SHOWUPSTREAM="auto".  A "<" indicates you are behind, ">"
+# indicates you are ahead, "<>" indicates you have diverged and "="
+# indicates that there is no difference. You can further control
+# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
+# of values:
+#
+#     verbose       show number of commits ahead/behind (+/-) upstream
+#     name          if verbose, then also show the upstream abbrev name
+#     legacy        don't use the '--count' option available in recent
+#                   versions of git-rev-list
+#     git           always compare HEAD to @{upstream}
+#     svn           always compare HEAD to your SVN upstream
+#
+# You can change the separator between the branch name and the above
+# state symbols by setting GIT_PS1_STATESEPARATOR. The default separator
+# is SP.
+#
+# By default, __git_ps1 will compare HEAD to your SVN upstream if it can
+# find one, or @{upstream} otherwise.  Once you have set
+# GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
+# setting the bash.showUpstream config variable.
+#
+# If you would like to see more information about the identity of
+# commits checked out as a detached HEAD, set GIT_PS1_DESCRIBE_STYLE
+# to one of these values:
+#
+#     contains      relative to newer annotated tag (v1.6.3.2~35)
+#     branch        relative to newer tag or branch (master~4)
+#     describe      relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
+#     tag           relative to any older tag (v1.6.3.1-13-gdd42c2f)
+#     default       exactly matching tag
+#
+# If you would like a colored hint about the current dirty state, set
+# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
+# the colored output of "git status -sb" and are available only when
+# using __git_ps1 for PROMPT_COMMAND or precmd.
+#
+# If you would like __git_ps1 to do nothing in the case when the current
+# directory is set up to be ignored by git, then set
+# GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the
+# repository level by setting bash.hideIfPwdIgnored to "false".
+
+# check whether printf supports -v
+__git_printf_supports_v=
+printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1
+
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+	local key value
+	local svn_remote svn_url_pattern count n
+	local upstream=git legacy="" verbose="" name=""
+
+	svn_remote=()
+	# get some config options from git-config
+	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+	while read -r key value; do
+		case "$key" in
+		bash.showupstream)
+			GIT_PS1_SHOWUPSTREAM="$value"
+			if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+				p=""
+				return
+			fi
+			;;
+		svn-remote.*.url)
+			svn_remote[$((${#svn_remote[@]} + 1))]="$value"
+			svn_url_pattern="$svn_url_pattern\\|$value"
+			upstream=svn+git # default upstream is SVN if available, else git
+			;;
+		esac
+	done <<< "$output"
+
+	# parse configuration values
+	for option in ${GIT_PS1_SHOWUPSTREAM}; do
+		case "$option" in
+		git|svn) upstream="$option" ;;
+		verbose) verbose=1 ;;
+		legacy)  legacy=1  ;;
+		name)    name=1 ;;
+		esac
+	done
+
+	# Find our upstream
+	case "$upstream" in
+	git)    upstream="@{upstream}" ;;
+	svn*)
+		# get the upstream from the "git-svn-id: ..." in a commit message
+		# (git-svn uses essentially the same procedure internally)
+		local -a svn_upstream
+		svn_upstream=($(git log --first-parent -1 \
+					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
+		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+			svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}
+			svn_upstream=${svn_upstream%@*}
+			local n_stop="${#svn_remote[@]}"
+			for ((n=1; n <= n_stop; n++)); do
+				svn_upstream=${svn_upstream#${svn_remote[$n]}}
+			done
+
+			if [[ -z "$svn_upstream" ]]; then
+				# default branch name for checkouts with no layout:
+				upstream=${GIT_SVN_ID:-git-svn}
+			else
+				upstream=${svn_upstream#/}
+			fi
+		elif [[ "svn+git" = "$upstream" ]]; then
+			upstream="@{upstream}"
+		fi
+		;;
+	esac
+
+	# Find how many commits we are ahead/behind our upstream
+	if [[ -z "$legacy" ]]; then
+		count="$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)"
+	else
+		# produce equivalent output to --count for older versions of git
+		local commits
+		if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+		then
+			local commit behind=0 ahead=0
+			for commit in $commits
+			do
+				case "$commit" in
+				"<"*) ((behind++)) ;;
+				*)    ((ahead++))  ;;
+				esac
+			done
+			count="$behind	$ahead"
+		else
+			count=""
+		fi
+	fi
+
+	# calculate the result
+	if [[ -z "$verbose" ]]; then
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p="=" ;;
+		"0	"*) # ahead of upstream
+			p=">" ;;
+		*"	0") # behind upstream
+			p="<" ;;
+		*)	    # diverged from upstream
+			p="<>" ;;
+		esac
+	else
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p=" u=" ;;
+		"0	"*) # ahead of upstream
+			p=" u+${count#0	}" ;;
+		*"	0") # behind upstream
+			p=" u-${count%	0}" ;;
+		*)	    # diverged from upstream
+			p=" u+${count#*	}-${count%	*}" ;;
+		esac
+		if [[ -n "$count" && -n "$name" ]]; then
+			__git_ps1_upstream_name=$(git rev-parse \
+				--abbrev-ref "$upstream" 2>/dev/null)
+			if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
+				p="$p \${__git_ps1_upstream_name}"
+			else
+				p="$p ${__git_ps1_upstream_name}"
+				# not needed anymore; keep user's
+				# environment clean
+				unset __git_ps1_upstream_name
+			fi
+		fi
+	fi
+
+}
+
+# Helper function that is meant to be called from __git_ps1.  It
+# injects color codes into the appropriate gitstring variables used
+# to build a gitstring.
+__git_ps1_colorize_gitstring ()
+{
+	if [[ -n ${ZSH_VERSION-} ]]; then
+		local c_red='%F{red}'
+		local c_green='%F{green}'
+		local c_lblue='%F{blue}'
+		local c_clear='%f'
+	else
+		# Using \[ and \] around colors is necessary to prevent
+		# issues with command line editing/browsing/completion!
+		local c_red='\[\e[31m\]'
+		local c_green='\[\e[32m\]'
+		local c_lblue='\[\e[1;34m\]'
+		local c_clear='\[\e[0m\]'
+	fi
+	local bad_color=$c_red
+	local ok_color=$c_green
+	local flags_color="$c_lblue"
+
+	local branch_color=""
+	if [ $detached = no ]; then
+		branch_color="$ok_color"
+	else
+		branch_color="$bad_color"
+	fi
+	c="$branch_color$c"
+
+	z="$c_clear$z"
+	if [ "$w" = "*" ]; then
+		w="$bad_color$w"
+	fi
+	if [ -n "$i" ]; then
+		i="$ok_color$i"
+	fi
+	if [ -n "$s" ]; then
+		s="$flags_color$s"
+	fi
+	if [ -n "$u" ]; then
+		u="$bad_color$u"
+	fi
+	r="$c_clear$r"
+}
+
+__git_eread ()
+{
+	local f="$1"
+	shift
+	test -r "$f" && read "$@" <"$f"
+}
+
+# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
+# when called from PS1 using command substitution
+# in this mode it prints text to add to bash PS1 prompt (includes branch name)
+#
+# __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
+# in that case it _sets_ PS1. The arguments are parts of a PS1 string.
+# when two arguments are given, the first is prepended and the second appended
+# to the state string when assigned to PS1.
+# The optional third parameter will be used as printf format string to further
+# customize the output of the git-status string.
+# In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
+__git_ps1 ()
+{
+	# preserve exit status
+	local exit=$?
+	local pcmode=no
+	local detached=no
+	local ps1pc_start='\u@\h:\w '
+	local ps1pc_end='\$ '
+	local printf_format=' (%s)'
+
+	case "$#" in
+		2|3)	pcmode=yes
+			ps1pc_start="$1"
+			ps1pc_end="$2"
+			printf_format="${3:-$printf_format}"
+			# set PS1 to a plain prompt so that we can
+			# simply return early if the prompt should not
+			# be decorated
+			PS1="$ps1pc_start$ps1pc_end"
+		;;
+		0|1)	printf_format="${1:-$printf_format}"
+		;;
+		*)	return $exit
+		;;
+	esac
+
+	# ps1_expanded:  This variable is set to 'yes' if the shell
+	# subjects the value of PS1 to parameter expansion:
+	#
+	#   * bash does unless the promptvars option is disabled
+	#   * zsh does not unless the PROMPT_SUBST option is set
+	#   * POSIX shells always do
+	#
+	# If the shell would expand the contents of PS1 when drawing
+	# the prompt, a raw ref name must not be included in PS1.
+	# This protects the user from arbitrary code execution via
+	# specially crafted ref names.  For example, a ref named
+	# 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the
+	# shell to execute 'sudo rm -rf /' when the prompt is drawn.
+	#
+	# Instead, the ref name should be placed in a separate global
+	# variable (in the __git_ps1_* namespace to avoid colliding
+	# with the user's environment) and that variable should be
+	# referenced from PS1.  For example:
+	#
+	#     __git_ps1_foo=$(do_something_to_get_ref_name)
+	#     PS1="...stuff...\${__git_ps1_foo}...stuff..."
+	#
+	# If the shell does not expand the contents of PS1, the raw
+	# ref name must be included in PS1.
+	#
+	# The value of this variable is only relevant when in pcmode.
+	#
+	# Assume that the shell follows the POSIX specification and
+	# expands PS1 unless determined otherwise.  (This is more
+	# likely to be correct if the user has a non-bash, non-zsh
+	# shell and safer than the alternative if the assumption is
+	# incorrect.)
+	#
+	local ps1_expanded=yes
+	[ -z "${ZSH_VERSION-}" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no
+	[ -z "${BASH_VERSION-}" ] || shopt -q promptvars || ps1_expanded=no
+
+	local repo_info rev_parse_exit_code
+	repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+		--is-bare-repository --is-inside-work-tree \
+		--short HEAD 2>/dev/null)"
+	rev_parse_exit_code="$?"
+
+	if [ -z "$repo_info" ]; then
+		return $exit
+	fi
+
+	local short_sha=""
+	if [ "$rev_parse_exit_code" = "0" ]; then
+		short_sha="${repo_info##*$'\n'}"
+		repo_info="${repo_info%$'\n'*}"
+	fi
+	local inside_worktree="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local bare_repo="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local inside_gitdir="${repo_info##*$'\n'}"
+	local g="${repo_info%$'\n'*}"
+
+	if [ "true" = "$inside_worktree" ] &&
+	   [ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] &&
+	   [ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] &&
+	   git check-ignore -q .
+	then
+		return $exit
+	fi
+
+	local r=""
+	local b=""
+	local step=""
+	local total=""
+	if [ -d "$g/rebase-merge" ]; then
+		__git_eread "$g/rebase-merge/head-name" b
+		__git_eread "$g/rebase-merge/msgnum" step
+		__git_eread "$g/rebase-merge/end" total
+		if [ -f "$g/rebase-merge/interactive" ]; then
+			r="|REBASE-i"
+		else
+			r="|REBASE-m"
+		fi
+	else
+		if [ -d "$g/rebase-apply" ]; then
+			__git_eread "$g/rebase-apply/next" step
+			__git_eread "$g/rebase-apply/last" total
+			if [ -f "$g/rebase-apply/rebasing" ]; then
+				__git_eread "$g/rebase-apply/head-name" b
+				r="|REBASE"
+			elif [ -f "$g/rebase-apply/applying" ]; then
+				r="|AM"
+			else
+				r="|AM/REBASE"
+			fi
+		elif [ -f "$g/MERGE_HEAD" ]; then
+			r="|MERGING"
+		elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+			r="|CHERRY-PICKING"
+		elif [ -f "$g/REVERT_HEAD" ]; then
+			r="|REVERTING"
+		elif [ -f "$g/BISECT_LOG" ]; then
+			r="|BISECTING"
+		fi
+
+		if [ -n "$b" ]; then
+			:
+		elif [ -h "$g/HEAD" ]; then
+			# symlink symbolic ref
+			b="$(git symbolic-ref HEAD 2>/dev/null)"
+		else
+			local head=""
+			if ! __git_eread "$g/HEAD" head; then
+				return $exit
+			fi
+			# is it a symbolic ref?
+			b="${head#ref: }"
+			if [ "$head" = "$b" ]; then
+				detached=yes
+				b="$(
+				case "${GIT_PS1_DESCRIBE_STYLE-}" in
+				(contains)
+					git describe --contains HEAD ;;
+				(branch)
+					git describe --contains --all HEAD ;;
+				(tag)
+					git describe --tags HEAD ;;
+				(describe)
+					git describe HEAD ;;
+				(* | default)
+					git describe --tags --exact-match HEAD ;;
+				esac 2>/dev/null)" ||
+
+				b="$short_sha..."
+				b="($b)"
+			fi
+		fi
+	fi
+
+	if [ -n "$step" ] && [ -n "$total" ]; then
+		r="$r $step/$total"
+	fi
+
+	local w=""
+	local i=""
+	local s=""
+	local u=""
+	local c=""
+	local p=""
+
+	if [ "true" = "$inside_gitdir" ]; then
+		if [ "true" = "$bare_repo" ]; then
+			c="BARE:"
+		else
+			b="GIT_DIR!"
+		fi
+	elif [ "true" = "$inside_worktree" ]; then
+		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
+		then
+			git diff --no-ext-diff --quiet || w="*"
+			git diff --no-ext-diff --cached --quiet || i="+"
+			if [ -z "$short_sha" ] && [ -z "$i" ]; then
+				i="#"
+			fi
+		fi
+		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
+		   git rev-parse --verify --quiet refs/stash >/dev/null
+		then
+			s="$"
+		fi
+
+		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+		   git ls-files --others --exclude-standard --directory --no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null
+		then
+			u="%${ZSH_VERSION+%}"
+		fi
+
+		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+			__git_ps1_show_upstream
+		fi
+	fi
+
+	local z="${GIT_PS1_STATESEPARATOR-" "}"
+
+	# NO color option unless in PROMPT_COMMAND mode
+	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+		__git_ps1_colorize_gitstring
+	fi
+
+	b=${b##refs/heads/}
+	if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
+		__git_ps1_branch_name=$b
+		b="\${__git_ps1_branch_name}"
+	fi
+
+	local f="$w$i$s$u"
+	local gitstring="$c$b${f:+$z$f}$r$p"
+
+	if [ $pcmode = yes ]; then
+		if [ "${__git_printf_supports_v-}" != yes ]; then
+			gitstring=$(printf -- "$printf_format" "$gitstring")
+		else
+			printf -v gitstring -- "$printf_format" "$gitstring"
+		fi
+		PS1="$ps1pc_start$gitstring$ps1pc_end"
+	else
+		printf -- "$printf_format" "$gitstring"
+	fi
+
+	return $exit
+}