From db55c63c774674d794cf6b765dd6159b12e4d65b Mon Sep 17 00:00:00 2001 From: Ethan Edwards Date: Tue, 6 Feb 2018 11:08:44 -0600 Subject: [PATCH 001/107] GH-1142 add behavior to address using set -e --- themes/base.theme.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/base.theme.bash b/themes/base.theme.bash index a18c3729..e27cd5f1 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -125,8 +125,8 @@ function scm_prompt_info_common { 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 + { [[ ${SCM:-} == ${SCM_HG} ]] && hg_prompt_info && return; } || true + { [[ ${SCM:-} == ${SCM_SVN} ]] && svn_prompt_info && return; } || true } function git_prompt_minimal_info { From e5332cb25314751399db7c9949fe1f70e5cabebf Mon Sep 17 00:00:00 2001 From: Ethan Edwards Date: Tue, 6 Feb 2018 11:30:36 -0600 Subject: [PATCH 002/107] GH-1142 add additional set -e coverage --- themes/githelpers.theme.bash | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/themes/githelpers.theme.bash b/themes/githelpers.theme.bash index e6bda810..ca4f88cd 100644 --- a/themes/githelpers.theme.bash +++ b/themes/githelpers.theme.bash @@ -71,7 +71,7 @@ function _git-hide-status { } function _git-status { - [[ "${SCM_GIT_IGNORE_UNTRACKED}" = "true" ]] && local git_status_flags='-uno' + [[ "${SCM_GIT_IGNORE_UNTRACKED}" = "true" ]] && local git_status_flags='-uno' || true git status --porcelain ${git_status_flags} 2> /dev/null } @@ -100,9 +100,9 @@ function _git-status-counts { } function _git-remote-info { - [[ "$(_git-upstream)" == "" ]] && return + [[ "$(_git-upstream)" == "" ]] && return || true - [[ "$(_git-branch)" == "$(_git-upstream-branch)" ]] && local same_branch_name=true + [[ "$(_git-branch)" == "$(_git-upstream-branch)" ]] && local same_branch_name=true || true if ([[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "auto" ]] && [[ "$(_git-num-remotes)" -ge 2 ]]) || [[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "true" ]]; then if [[ "${same_branch_name}" != "true" ]]; then From 76de592cafb021c3168d89b2dd5d4571eb0e895c Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Thu, 30 Aug 2018 18:43:00 -0500 Subject: [PATCH 003/107] Add Crystal auto-completion on Mac --- completion/available/crystal.completion.bash | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 completion/available/crystal.completion.bash diff --git a/completion/available/crystal.completion.bash b/completion/available/crystal.completion.bash new file mode 100644 index 00000000..b83be253 --- /dev/null +++ b/completion/available/crystal.completion.bash @@ -0,0 +1,8 @@ +if which crystal >/dev/null 2>&1; then + BREW_PREFIX=$(brew --prefix) + + if [ -f "$BREW_PREFIX"/etc/bash_completion.d/crystal ]; then + . "$BREW_PREFIX"/etc/bash_completion.d/crystal + fi + +fi From 4ff305c009c9fb74b66aece0c8e786dbcd3bd55c Mon Sep 17 00:00:00 2001 From: cornfeedhobo Date: Fri, 9 Nov 2018 18:55:19 -0500 Subject: [PATCH 004/107] add multiple path support to go plugin --- plugins/available/go.plugin.bash | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/available/go.plugin.bash b/plugins/available/go.plugin.bash index 827ac388..819ebc3a 100755 --- a/plugins/available/go.plugin.bash +++ b/plugins/available/go.plugin.bash @@ -5,7 +5,18 @@ about-plugin 'go environment variables & path configuration' [ ! command -v go &>/dev/null ] && return +function _split_path_reverse() { + local r= + for p in ${@//:/ } ; do + r="$p $r" + done + echo "$r" +} + export GOROOT=${GOROOT:-$(go env GOROOT)} pathmunge "${GOROOT}/bin" + export GOPATH=${GOPATH:-$(go env GOPATH)} -pathmunge "${GOPATH}/bin" +for p in $( _split_path_reverse ${GOPATH} ) ; do + pathmunge "${p}/bin" +done From b3f7de38937a12cfd0cef6eb40069dc7d91b529c Mon Sep 17 00:00:00 2001 From: Eduardo Bellido Bellido Date: Sun, 11 Nov 2018 14:14:02 +0100 Subject: [PATCH 005/107] Support XDG in fzf plugin --- plugins/available/fzf.plugin.bash | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/available/fzf.plugin.bash b/plugins/available/fzf.plugin.bash index f2eddeb1..def60825 100644 --- a/plugins/available/fzf.plugin.bash +++ b/plugins/available/fzf.plugin.bash @@ -4,7 +4,11 @@ cite about-plugin about-plugin 'load fzf, if you are using it' -[ -f ~/.fzf.bash ] && source ~/.fzf.bash +if [ -f ~/.fzf.bash ]; then + source ~/.fzf.bash +elif [ -f "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash ]; then + source "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash +fi if [ -z ${FZF_DEFAULT_COMMAND+x} ]; then command -v fd &> /dev/null && export FZF_DEFAULT_COMMAND='fd --type f' From 4df44b1fa998d44819a84477f8685f12ecab7e1d Mon Sep 17 00:00:00 2001 From: Eduardo Bellido Bellido Date: Mon, 12 Nov 2018 22:59:14 +0100 Subject: [PATCH 006/107] Bash-it don't returns to the previous path after update --- lib/helpers.bash | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index a2c0d3aa..565173ed 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -167,6 +167,8 @@ _bash-it_update() { _about 'updates Bash-it' _group 'lib' + local old_pwd="${PWD}" + cd "${BASH_IT}" || return if [ -z $BASH_IT_REMOTE ]; then @@ -194,7 +196,7 @@ _bash-it_update() { else echo "Bash-it is up to date, nothing to do!" fi - cd - &> /dev/null || return + cd "${old_pwd}" &> /dev/null || return } _bash-it-migrate() { From 7e26ae28bf2cf47ea62d3acf0bde5f8ca0ffad0a Mon Sep 17 00:00:00 2001 From: Jeremy Mathevet Date: Tue, 13 Nov 2018 11:25:59 +0000 Subject: [PATCH 007/107] Add kubernetes-context segment to powerline --- themes/base.theme.bash | 4 ++++ themes/powerline-naked/README.md | 4 +++- themes/powerline-naked/powerline-naked.theme.bash | 3 +++ themes/powerline-plain/README.md | 4 +++- themes/powerline-plain/powerline-plain.theme.bash | 3 +++ themes/powerline/README.md | 4 +++- themes/powerline/powerline.base.bash | 10 ++++++++++ themes/powerline/powerline.theme.bash | 3 +++ 8 files changed, 32 insertions(+), 3 deletions(-) diff --git a/themes/base.theme.bash b/themes/base.theme.bash index 51d5f359..e4879f3c 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -336,6 +336,10 @@ function ruby_version_prompt { echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)" } +function k8s_context_prompt { + echo -e "$(kubectl config current-context)" +} + function virtualenv_prompt { if [[ -n "$VIRTUAL_ENV" ]]; then virtualenv=`basename "$VIRTUAL_ENV"` diff --git a/themes/powerline-naked/README.md b/themes/powerline-naked/README.md index 62238bd5..da5e254b 100644 --- a/themes/powerline-naked/README.md +++ b/themes/powerline-naked/README.md @@ -14,6 +14,7 @@ A colorful theme, where shows a lot information about your shell session. * An indicator when the current shell is inside the Vim editor * Battery charging status (depends on the [../../plugins/available/battery.plugin.bash](battery plugin)) * SCM Repository status (e.g. Git, SVN) +* The current Kubernetes environment * The current Python environment (Virtualenv, venv, and Conda are supported) in use * The current Ruby environment (rvm and rbenv are supported) in use * Last command exit code (only shown when the exit code is greater than 0) @@ -48,11 +49,12 @@ The contents of the prompt can be "reordered", all the "segments" (every piece o * `cwd` - Current working directory including full folder hierarchy (c.f. `wd`) * `hostname` - Host name of machine * `in_vim` - Show identifier if running in `:terminal` from vim +* `k8s_context` - Show current kubernetes context * `last_status` - Exit status of last run command * `python_venv` - Python virtual environment information (`virtualenv`, `venv` and `conda` supported) * `ruby` - Current ruby version if using `rvm` -* `scm` - Version control information, `git` +* `scm` - Version control information, `git` * `user_info` - Current user * `wd` - Working directory, like `cwd` but doesn't show the full folder hierarchy, only the directory you're currently in. diff --git a/themes/powerline-naked/powerline-naked.theme.bash b/themes/powerline-naked/powerline-naked.theme.bash index 4e06273c..81025c84 100644 --- a/themes/powerline-naked/powerline-naked.theme.bash +++ b/themes/powerline-naked/powerline-naked.theme.bash @@ -33,6 +33,9 @@ RBENV_THEME_PROMPT_SUFFIX="" RUBY_THEME_PROMPT_COLOR=161 RUBY_CHAR=${POWERLINE_RUBY_CHAR:="❲r❳ "} +KUBERNETES_CONTEXT_THEME_CHAR=${POWERLINE_KUBERNETES_CONTEXT_CHAR:="⎈ "} +KUBERNETES_CONTEXT_THEME_PROMPT_COLOR=26 + AWS_PROFILE_CHAR="${POWERLINE_AWS_PROFILE_CHAR:=❲aws❳ }" AWS_PROFILE_PROMPT_COLOR=208 diff --git a/themes/powerline-plain/README.md b/themes/powerline-plain/README.md index ef773cd8..701b9fa1 100644 --- a/themes/powerline-plain/README.md +++ b/themes/powerline-plain/README.md @@ -12,6 +12,7 @@ A colorful theme, where shows a lot information about your shell session. * An indicator when the current shell is inside the Vim editor * Battery charging status (depends on the [../../plugins/available/battery.plugin.bash](battery plugin)) * SCM Repository status (e.g. Git, SVN) +* The current Kubernetes environment * The current Python environment (Virtualenv, venv, and Conda are supported) in use * The current Ruby environment (rvm and rbenv are supported) in use * Last command exit code (only shown when the exit code is greater than 0) @@ -46,11 +47,12 @@ The contents of the prompt can be "reordered", all the "segments" (every piece o * `cwd` - Current working directory including full folder hierarchy (c.f. `wd`) * `hostname` - Host name of machine * `in_vim` - Show identifier if running in `:terminal` from vim +* `k8s_context` - Show current kubernetes context * `last_status` - Exit status of last run command * `python_venv` - Python virtual environment information (`virtualenv`, `venv` and `conda` supported) * `ruby` - Current ruby version if using `rvm` -* `scm` - Version control information, `git` +* `scm` - Version control information, `git` * `user_info` - Current user * `wd` - Working directory, like `cwd` but doesn't show the full folder hierarchy, only the directory you're currently in. diff --git a/themes/powerline-plain/powerline-plain.theme.bash b/themes/powerline-plain/powerline-plain.theme.bash index 0757dc9e..bddb6450 100644 --- a/themes/powerline-plain/powerline-plain.theme.bash +++ b/themes/powerline-plain/powerline-plain.theme.bash @@ -28,6 +28,9 @@ RBENV_THEME_PROMPT_SUFFIX="" RUBY_THEME_PROMPT_COLOR=161 RUBY_CHAR=${POWERLINE_RUBY_CHAR:="💎 "} +KUBERNETES_CONTEXT_THEME_CHAR=${POWERLINE_KUBERNETES_CONTEXT_CHAR:="⎈ "} +KUBERNETES_CONTEXT_THEME_PROMPT_COLOR=26 + AWS_PROFILE_CHAR="${POWERLINE_AWS_PROFILE_CHAR:=❲aws❳ }" AWS_PROFILE_PROMPT_COLOR=208 diff --git a/themes/powerline/README.md b/themes/powerline/README.md index d3f7fbca..974bcbeb 100644 --- a/themes/powerline/README.md +++ b/themes/powerline/README.md @@ -16,6 +16,7 @@ A colorful theme, where shows a lot information about your shell session. * An indicator when the current shell is inside the Vim editor * Battery charging status (depends on the [../../plugins/available/battery.plugin.bash](battery plugin)) * SCM Repository status (e.g. Git, SVN) +* The current Kubernetes environment * The current Python environment (Virtualenv, venv, and Conda are supported) in use * The current Ruby environment (rvm and rbenv are supported) in use * Last command exit code (only shown when the exit code is greater than 0) @@ -50,11 +51,12 @@ The contents of the prompt can be "reordered", all the "segments" (every piece o * `cwd` - Current working directory including full folder hierarchy (c.f. `wd`) * `hostname` - Host name of machine * `in_vim` - Show identifier if running in `:terminal` from vim +* `k8s_context` - Show current kubernetes context * `last_status` - Exit status of last run command * `python_venv` - Python virtual environment information (`virtualenv`, `venv` and `conda` supported) * `ruby` - Current ruby version if using `rvm` -* `scm` - Version control information, `git` +* `scm` - Version control information, `git` * `user_info` - Current user * `wd` - Working directory, like `cwd` but doesn't show the full folder hierarchy, only the directory you're currently in. diff --git a/themes/powerline/powerline.base.bash b/themes/powerline/powerline.base.bash index 7dded057..08da5f7c 100644 --- a/themes/powerline/powerline.base.bash +++ b/themes/powerline/powerline.base.bash @@ -52,6 +52,16 @@ function __powerline_ruby_prompt { [[ -n "${ruby_version}" ]] && echo "${RUBY_CHAR}${ruby_version}|${RUBY_THEME_PROMPT_COLOR}" } +function __powerline_k8s_context_prompt { + local kubernetes_context="" + + if _command_exists kubectl; then + kubernetes_context="$(k8s_context_prompt)" + fi + + [[ -n "${kubernetes_context}" ]] && echo "${KUBERNETES_CONTEXT_THEME_CHAR}${kubernetes_context}|${KUBERNETES_CONTEXT_THEME_PROMPT_COLOR}" +} + function __powerline_python_venv_prompt { set +u local python_venv="" diff --git a/themes/powerline/powerline.theme.bash b/themes/powerline/powerline.theme.bash index 9f0e6f04..482b3464 100644 --- a/themes/powerline/powerline.theme.bash +++ b/themes/powerline/powerline.theme.bash @@ -31,6 +31,9 @@ RBENV_THEME_PROMPT_SUFFIX="" RUBY_THEME_PROMPT_COLOR=161 RUBY_CHAR=${POWERLINE_RUBY_CHAR:="❲r❳ "} +KUBERNETES_CONTEXT_THEME_CHAR=${POWERLINE_KUBERNETES_CONTEXT_CHAR:="⎈ "} +KUBERNETES_CONTEXT_THEME_PROMPT_COLOR=26 + AWS_PROFILE_CHAR="${POWERLINE_AWS_PROFILE_CHAR:=❲aws❳ }" AWS_PROFILE_PROMPT_COLOR=208 From 75564a050f5fb738cb35cdf03239418d9dbdfab8 Mon Sep 17 00:00:00 2001 From: Ira Abramov Date: Thu, 15 Nov 2018 10:35:17 +0200 Subject: [PATCH 008/107] Add completions for Opscode Chef's knife command --- completion/available/knife.completion.bash | 207 +++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 completion/available/knife.completion.bash diff --git a/completion/available/knife.completion.bash b/completion/available/knife.completion.bash new file mode 100644 index 00000000..6316ce08 --- /dev/null +++ b/completion/available/knife.completion.bash @@ -0,0 +1,207 @@ +#!/usr/bin/env bash + +############## +### CONFIG ### +############## +### feel free to change those constants +# the dir where to store the cache (must be writable and readable by the current user) +# must be an absolute path +_KNIFE_AUTOCOMPLETE_CACHE_DIR="$HOME/.knife_autocomplete_cache" +# the maximum # of _seconds_ after which a cache will be considered stale +# (a cache is refreshed whenever it is used! this is only for caches that might not have been used for a long time) +# WARNING: keep that value > 100 +_KNIFE_AUTOCOMPLETE_MAX_CACHE_AGE=86400 + +############################################### +### END OF CONFIG - DON'T CHANGE CODE BELOW ### +############################################### + +### init +_KAC_CACHE_TMP_DIR="$_KNIFE_AUTOCOMPLETE_CACHE_DIR/tmp" +# make sure the cache dir exists +mkdir -p $_KAC_CACHE_TMP_DIR + +############################## +### Cache helper functions ### +############################## + +# GNU or BSD stat? +stat -c %Y /dev/null > /dev/null 2>&1 && _KAC_STAT_COMMAND="stat -c %Y" || _KAC_STAT_COMMAND="stat -f %m" + +# returns 0 iff the file whose path is given as 1st argument +# exists and has last been modified in the last $2 seconds +# returns 1 otherwise +_KAC_is_file_newer_than() +{ + [ -f "$1" ] || return 1 + [ $(( $(date +%s) - $($_KAC_STAT_COMMAND "$1") )) -gt $2 ] && return 1 || return 0 +} + +# helper function for _KAC_get_and_regen_cache, see doc below +_KAC_regen_cache() +{ + local CACHE_NAME=$1 + local CACHE_PATH="$_KNIFE_AUTOCOMPLETE_CACHE_DIR/$CACHE_NAME" + local TMP_FILE=$(mktemp "$_KAC_CACHE_TMP_DIR/$CACHE_NAME.XXXX") + shift 1 + "$@" > $TMP_FILE 2> /dev/null + # discard the temp file if it's empty AND the previous command didn't exit successfully, but still mark the cache as updated + [[ $? != 0 ]] && [[ $(cat $TMP_FILE | wc -l) == 0 ]] && rm -f $TMP_FILE && touch $CACHE_PATH && return 1 \ + || mv -f $TMP_FILE $CACHE_PATH +} + +# cached files can't have spaces in their names +_KAC_get_cache_name_from_command() +{ + echo "$@" | sed 's/ /_SPACE_/g' +} + +# the reverse operation from the function above +_KAC_get_command_from_cache_name() +{ + echo "$@" | sed 's/_SPACE_/ /g' +} + +# given a command as argument, it fetches the cache for that command if it can find it +# otherwise it waits for the cache to be generated +# in either case, it regenerates the cache, and sets the _KAC_CACHE_PATH env variable +# for obvious reason, do NOT call that in a sub-shell (in particular, no piping) +_KAC_get_and_regen_cache() +{ + # the cache name can't have space in it + local CACHE_NAME=$(_KAC_get_cache_name_from_command "$@") + local REGEN_CMD="_KAC_regen_cache $CACHE_NAME $@" + _KAC_CACHE_PATH="$_KNIFE_AUTOCOMPLETE_CACHE_DIR/$CACHE_NAME" + # no need to wait for the regen if the file already exists + [ -f $_KAC_CACHE_PATH ] && ($REGEN_CMD &) || $REGEN_CMD +} + +# performs two things: first, deletes all obsolete temp files +# then refreshes stale caches that haven't been called in a long time +_KAC_clean_cache() +{ + local FILE CMD + # delete all obsolete temp files, could be lingering there for any kind of crash in the caching process + for FILE in $(ls $_KAC_CACHE_TMP_DIR) + do + _KAC_is_file_newer_than $FILE $_KNIFE_AUTOCOMPLETE_MAX_CACHE_AGE || rm -f $FILE + done + # refresh really stale caches + for FILE in $(find $_KNIFE_AUTOCOMPLETE_CACHE_DIR -maxdepth 1 -type f -not -name '.*') + do + _KAC_is_file_newer_than $FILE $_KNIFE_AUTOCOMPLETE_MAX_CACHE_AGE && continue + # first let's get the original command + CMD=$(_KAC_get_command_from_cache_name $(basename "$FILE")) + # then regen the cache + _KAC_get_and_regen_cache "$CMD" > /dev/null + done +} + +# perform a cache cleaning when loading this file +_KAC_clean_cache + +##################################### +### End of cache helper functions ### +##################################### + + +# returns all the possible knife sub-commands +_KAC_knife_commands() +{ + knife --help | grep -E "^knife" | sed -E 's/ \(options\)//g' +} + +# rebuilds the knife base command currently being completed, and assigns it to $_KAC_CURRENT_COMMAND +# additionnally, returns 1 iff the current base command is not complete, 0 otherwise +# also sets $_KAC_CURRENT_COMMAND_NB_WORDS if the base command is complete +_KAC_get_current_base_command() +{ + local PREVIOUS="knife" + local I=1 + local CURRENT + while [ $I -le $COMP_CWORD ] + do + # command words are all lower-case + echo ${COMP_WORDS[$I]} | grep -E "^[a-z]+$" > /dev/null || break + CURRENT="$PREVIOUS ${COMP_WORDS[$I]}" + cat $_KAC_CACHE_PATH | grep -E "^$CURRENT" > /dev/null || break + PREVIOUS=$CURRENT + I=$(( $I + 1)) + done + _KAC_CURRENT_COMMAND=$PREVIOUS + [ $I -le $COMP_CWORD ] && _KAC_CURRENT_COMMAND_NB_WORDS=$I +} + +# searches the position of the currently completed argument in the current base command +# (i.e. handles "plural" arguments such as knife cookbook upload cookbook1 cookbook2 and so on...) +# assumes the current base command is complete +_KAC_get_current_arg_position() +{ + local CURRENT_ARG_POS=$(( $_KAC_CURRENT_COMMAND_NB_WORDS + 1 )) + local COMPLETE_COMMAND=$(cat $_KAC_CACHE_PATH | grep -E "^$_KAC_CURRENT_COMMAND") + local CURRENT_ARG + while [ $CURRENT_ARG_POS -le $COMP_CWORD ] + do + CURRENT_ARG=$(echo $COMPLETE_COMMAND | cut -d ' ' -f $CURRENT_ARG_POS) + # we break if the current arg is a "plural" arg + echo $CURRENT_ARG | grep -E "^\\[[^]]+(\\.\\.\\.\\]|$)" > /dev/null && break + CURRENT_ARG_POS=$(( $CURRENT_ARG_POS + 1 )) + done + echo $CURRENT_ARG_POS +} + +# the actual auto-complete function +_knife() +{ + _KAC_get_and_regen_cache _KAC_knife_commands + local RAW_LIST ITEM REGEN_CMD ARG_POSITION + COMREPLY=() + # get correct command & arg pos + _KAC_get_current_base_command && ARG_POSITION=$(_KAC_get_current_arg_position) || ARG_POSITION=$(( $COMP_CWORD + 1 )) + RAW_LIST=$(cat $_KAC_CACHE_PATH | grep -E "^$_KAC_CURRENT_COMMAND" | cut -d ' ' -f $ARG_POSITION | uniq) + + # we need to process that raw list a bit, most notably for placeholders + # NOTE: I chose to explicitely fetch & cache _certain_ informations for the server (cookbooks & node names, etc) + # as opposed to a generic approach by trying to find a 'list' knife command corresponding to the + # current base command - that might limit my script in some situation, but that way I'm sure it caches only + # not-sensitive stuff (a generic approach could be pretty bad e.g. with the knife-rackspace plugin) + LIST="" + for ITEM in $RAW_LIST + do + # always relevant if only lower-case chars : continuation of the base command + echo $ITEM | grep -E "^[a-z]+$" > /dev/null && LIST="$LIST $ITEM" && continue + case $ITEM in + *COOKBOOK*) + # special case for cookbooks : from site or local + [[ ${COMP_WORDS[2]} == 'site' ]] && REGEN_CMD="knife cookbook site list" || REGEN_CMD="knife cookbook list" + _KAC_get_and_regen_cache $REGEN_CMD + LIST="$LIST $(cat $_KAC_CACHE_PATH | cut -d ' ' -f 1)" + continue + ;; + *ITEM*) + # data bag item : another special case + local DATA_BAG_NAME=${COMP_WORDS[$(( COMP_CWORD-1 ))]} + REGEN_CMD="knife data bag show $DATA_BAG_NAME" + ;; + *INDEX*) + # see doc @ http://docs.opscode.com/knife_search.html + LIST="$LIST client environment node role" + REGEN_CMD="knife data bag list" + ;; + *BAG*) REGEN_CMD="knife data bag list";; + *CLIENT*) REGEN_CMD="knife client list";; + *NODE*) REGEN_CMD="knife node list";; + *ENVIRONMENT*) REGEN_CMD="knife environment list";; + *ROLE*) REGEN_CMD="knife role list";; + *USER*) REGEN_CMD="knife user list";; + # not a generic argument we support... + *) continue;; + esac + _KAC_get_and_regen_cache $REGEN_CMD + LIST="$LIST $(cat $_KAC_CACHE_PATH)" + done + COMPREPLY=( $(compgen -W "${LIST}" -- ${COMP_WORDS[COMP_CWORD]})) +} + +#complete -f -F _knife knife +complete -F _knife knife From 96819ba7f30e2a1f62c9518da9dbcd7f16396511 Mon Sep 17 00:00:00 2001 From: Tony Feng <337940626@qq.com> Date: Thu, 15 Nov 2018 16:57:08 +0800 Subject: [PATCH 009/107] fix the phoenix mix command -> 'phoenx' to 'phx'. --- aliases/available/phoenix.aliases.bash | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aliases/available/phoenix.aliases.bash b/aliases/available/phoenix.aliases.bash index 2a4ec5e1..64728a2e 100644 --- a/aliases/available/phoenix.aliases.bash +++ b/aliases/available/phoenix.aliases.bash @@ -3,7 +3,7 @@ about-alias 'phoenix abbreviations' # Phoenix Commands alias i='iex' -alias ips='iex -S mix phoenix.server' +alias ips='iex -S mix phx.server' alias ism='iex -S mix' alias m='mix' alias mab='mix archive.build' @@ -32,14 +32,14 @@ alias mho='mix hex.outdated' alias mlh='mix local.hex' alias mn='mix new' alias mns='mix new --sup' -alias mpgc='mix phoenix.gen.channel' -alias mpgh='mix phoenix.gen.html' -alias mpgj='mix phoenix.gen.json' -alias mpgm='mix phoenix.gen.model' -alias mpgs='mix phoenix.gen.secret' -alias mpn='mix phoenix.new' -alias mpr='mix phoenix.routes' -alias mps='mix phoenix.server' +alias mpgc='mix phx.gen.channel' +alias mpgh='mix phx.gen.html' +alias mpgj='mix phx.gen.json' +alias mpgm='mix phx.gen.model' +alias mpgs='mix phx.gen.secret' +alias mpn='mix phx.new' +alias mpr='mix phx.routes' +alias mps='mix phx.server' alias mr='mix run' alias mrnh='mix run --no-halt' alias mrl='mix release' From baae0305b6ded4b7e709ace3755ee0c424239f3b Mon Sep 17 00:00:00 2001 From: Konstantin Gredeskoul Date: Sat, 17 Nov 2018 17:45:44 -0800 Subject: [PATCH 010/107] Speed up bash-it Search & support exact matches This commit improves Bash-It search functionality in a couple of ways: * bash-it search (with no arguments) will print detailed help. * bash-it search now accepts terms prefixed with '@' sign, indicating an exact match. * bash-it search now performs smarter caching of the component listings/status New search syntax is as follows: bash-it search [-|@]term1 [-|@]term2 [ --enable | --disable | --help ] --- lib/helpers.bash | 8 +- lib/search.bash | 453 ++++++++++++++++++++++++++++++++---------- test/lib/helpers.bats | 1 + test/lib/search.bats | 92 ++++++--- 4 files changed, 419 insertions(+), 135 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 565173ed..cbcdd42d 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -70,7 +70,7 @@ bash-it () example '$ bash-it disable alias hg [tmux]...' example '$ bash-it migrate' example '$ bash-it update' - example '$ bash-it search ruby [[-]rake]... [--enable | --disable]' + example '$ bash-it search [-|@]term1 [-|@]term2 ... [--enable | --disable | --help | --refresh | --no-color ]' example '$ bash-it version' example '$ bash-it reload' typeset verb=${1:-} @@ -393,6 +393,9 @@ _disable-thing () fi fi + local flag="DEFER_CACHE_CLEANUP_FOR_${file_type}" + [[ -z ${!flag} ]] && _bash_it_search_cache_clean "${file_type}" + if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then exec ${0/-/} fi @@ -488,6 +491,9 @@ _enable-thing () ln -s ../$subdirectory/available/$to_enable "${BASH_IT}/enabled/${use_load_priority}${BASH_IT_LOAD_PRIORITY_SEPARATOR}${to_enable}" fi + local flag="DEFER_CACHE_CLEANUP_FOR_${file_type}" + [[ -z ${!flag} ]] && _bash_it_search_cache_clean "${file_type}" + if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then exec ${0/-/} fi diff --git a/lib/search.bash b/lib/search.bash index f643ad12..a54971f5 100644 --- a/lib/search.bash +++ b/lib/search.bash @@ -1,3 +1,4 @@ +#!/usr/bin/env bash # # Search by Konstantin Gredeskoul «github.com/kigster» #——————————————————————————————————————————————————————————————————————————————— @@ -5,46 +6,172 @@ # whose name or description matches one of the search terms provided as arguments. # # Usage: -# ❯ bash-it search term1 [[-]term2] ... [[-]termN] [ --enable | --disable ] +# ❯ bash-it search [-|@]term1 [-|@]term2 ... \ +# [ --enable | -e ] \ +# [ --disable | -d ] \ +# [ --refresh | -r ] +# [ --help | -h ] # -# Exmplanation: # Single dash, as in "-chruby", indicates a negative search term. # Double dash indicates a command that is to be applied to the search result. -# At the moment only --enable and --disable are supported. +# At the moment only --help, --enable and --disable are supported. +# An '@' sign indicates an exact (not partial) match. # # Examples: # ❯ bash-it search ruby rbenv rvm gem rake -# aliases : bundler -# plugins : chruby chruby-auto rbenv ruby rvm -# completions : gem rake - +# aliases: bundler +# plugins: chruby chruby-auto ruby rbenv rvm ruby +# completions: rvm gem rake +# # ❯ bash-it search ruby rbenv rvm gem rake -chruby -# aliases : bundler -# plugins : rbenv ruby rvm -# completions : gem rake +# aliases: bundler +# plugins: ruby rbenv rvm ruby +# completions: rvm gem rake # # Examples of enabling or disabling results of the search: # # ❯ bash-it search ruby -# aliases => bundler -# plugins => chruby chruby-auto ruby +# aliases: bundler +# plugins: chruby chruby-auto ruby # # ❯ bash-it search ruby -chruby --enable -# aliases => ✓bundler -# plugins => ✓ruby +# aliases: bundler +# plugins: ruby # +# Examples of using exact match: + +# ❯ bash-it search @git @ruby +# aliases: git +# plugins: git ruby +# completions: git # + _bash-it-search() { _about 'searches for given terms amongst bash-it plugins, aliases and completions' _param '1: term1' _param '2: [ term2 ]...' - _example '$ _bash-it-search ruby rvm rake bundler' + _example '$ _bash-it-search @git ruby -rvm rake bundler' - declare -a _components=(aliases plugins completions) + local component + export BASH_IT_SEARCH_USE_COLOR=true + export BASH_IT_GREP=${BASH_IT_GREP:-$(which egrep)} + declare -a BASH_IT_COMPONENTS=(aliases plugins completions) - for _component in "${_components[@]}" ; do - _bash-it-search-component "${_component}" "$@" + if [[ -z "$*" ]] ; then + _bash-it-search-help + return 0 + fi + + local -a args=() + for word in $@; do + if [[ ${word} == "--help" || ${word} == "-h" ]]; then + _bash-it-search-help + return 0 + elif [[ ${word} == "--refresh" || ${word} == "-r" ]]; then + _bash_it_search_cache_clean + elif [[ ${word} == "--no-color" ]]; then + export BASH_IT_SEARCH_USE_COLOR=false + else + args=(${args[@]} ${word}) + fi done + + for component in "${BASH_IT_COMPONENTS[@]}" ; do + _bash-it-search-component "${component}" "${args[@]}" + done + + return 0 +} + +_bash-it-search-help() { + printf "${echo_normal} +${echo_underline_yellow}USAGE${echo_normal} + + bash-it search [-|@]term1 [-|@]term2 ... \\ + [ --enable | --disable | --help | --refresh | --no-color ] + +${echo_underline_yellow}DESCRIPTION${echo_normal} + + Use ${echo_bold_green}search${echo_normal} bash-it command to search for a list of terms or term negations + across all components: aliases, completions and plugins. Components that are + enabled are shown in green (or with a check box if --no-color option is used). + + In addition to simply finding the right component, you can use the results + of the search to enable or disable all components that the search returns. + + When search is used to enable/disable components it becomes clear that + you must be able to perform not just a partial match, but an exact match, + as well as be able to exclude some components. + + * To exclude a component (or all components matching a substring) use + a search term with minus as a prefix, eg '-flow' + + * To perform an exact match, use character '@' in front of the term, + eg. '@git' would only match aliases, plugins and completions named 'git'. + +${echo_underline_yellow}FLAGS${echo_normal} + --enable ${echo_purple}Enable all matching componenents.${echo_normal} + --disable ${echo_purple}Disable all matching componenents.${echo_normal} + --help ${echo_purple}Print this help.${echo_normal} + --refresh ${echo_purple}Force a refresh of the search cache.${echo_normal} + --no-color ${echo_purple}Disable color output and use monochrome text.${echo_normal} + +${echo_underline_yellow}EXAMPLES${echo_normal} + + For example, ${echo_bold_green}bash-it search git${echo_normal} would match any alias, completion + or plugin that has the word 'git' in either the module name or + it's description. You should see something like this when you run this + command: + + ${echo_bold_green}❯ bash-it search git${echo_bold_blue} + ${echo_bold_yellow}aliases: ${echo_bold_green}git ${echo_normal}gitsvn + ${echo_bold_yellow}plugins: ${echo_normal}autojump fasd ${echo_bold_green}git ${echo_normal}git-subrepo jgitflow jump + ${echo_bold_yellow}completions: ${echo_bold_green}git ${echo_normal}git_flow git_flow_avh${echo_normal} + + You can exclude some terms by prefixing a term with a minus, eg: + + ${echo_bold_green}❯ bash-it search git -flow -svn${echo_bold_blue} + ${echo_bold_yellow}aliases: ${echo_normal}git + ${echo_bold_yellow}plugins: ${echo_normal}autojump fasd git git-subrepo jump + ${echo_bold_yellow}completions: ${echo_normal}git${echo_normal} + + Finally, if you prefix a term with '@' symbol, that indicates an exact + match. Note, that we also pass the '--enable' flag, which would ensure + that all matches are automatically enabled. The example is below: + + ${echo_bold_green}❯ bash-it search @git --enable${echo_bold_blue} + ${echo_bold_yellow}aliases: ${echo_normal}git + ${echo_bold_yellow}plugins: ${echo_normal}git + ${echo_bold_yellow}completions: ${echo_normal}git${echo_normal} + +${echo_underline_yellow}SUMMARY${echo_normal} + + Take advantage of the search functionality to discover what Bash-It can do + for you. Try searching for partial term matches, mix and match with the + negative terms, or specify an exact matches of any number of terms. Once + you created the search command that returns ONLY the modules you need, + simply append '--enable' or '--disable' at the end to activate/deactivate + each module. + +" +} + +_bash-it-cache-file() { + local component="${1}" + local file="/tmp/bash_it/${component}.status" + mkdir -p $(dirname ${file}) + printf ${file} +} + +_bash_it_search_cache_clean() { + local component="$1" + if [[ -z ${component} ]] ; then + for component in "${BASH_IT_COMPONENTS[@]}" ; do + _bash_it_search_cache_clean "${component}" + done + else + rm -f $(_bash-it-cache-file ${component}) + fi } #——————————————————————————————————————————————————————————————————————————————— @@ -58,137 +185,261 @@ _bash-it-array-contains-element () { echo -n $r } +_bash-it-array-dedup() { + echo "$*" | tr ' ' '\n' | sort -u | tr '\n' ' ' +} + +_bash-it-grep() { + if [[ -z "${BASH_IT_GREP}" ]] ; then + export BASH_IT_GREP="$(which egrep || which grep || '/usr/bin/grep')" + fi + printf "%s " "${BASH_IT_GREP}" +} + +_bash-it-is-partial-match() { + local component="$1" + local term="$2" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -i -q -- "${term}" +} + +_bash-it-component-term-matches-negation() { + local match="$1"; shift + local negative + for negative in "$@"; do + [[ "${match}" =~ "${negative}" ]] && return 0 + done + + return 1 +} + +_bash-it-component-help() { + local component="$1" + local file=$(_bash-it-cache-file ${component}) + if [[ ! -s "${file}" || -z $(find "${file}" -mmin -2) ]] ; then + rm -f "${file}" 2>/dev/null + local func="_bash-it-${component}" + ${func} | $(_bash-it-grep) -E ' \[' | cat > ${file} + fi + cat "${file}" +} + +_bash-it-component-list() { + local component="$1" + _bash-it-component-help "${component}" | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +_bash-it-component-list-matching() { + local component="$1"; shift + local term="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -- "${term}" | awk '{print $1}' | sort | uniq +} + +_bash-it-component-list-enabled() { + local component="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +_bash-it-component-list-disabled() { + local component="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +_bash-it-component-item-is-enabled() { + local component="$1" + local item="$2" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" +} + +_bash-it-component-item-is-disabled() { + local component="$1" + local item="$2" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" +} + + _bash-it-search-component() { - _about 'searches for given terms amongst a given component' - _param '1: component type, one of: [ aliases | plugins | completions ]' - _param '2: term1 ' - _param '3: [-]term2 [-]term3 ...' - _example '$ _bash-it-search-component aliases rake bundler -chruby' - - _component=$1 - - local func=_bash-it-${_component} - local help=$($func) + local component="$1" shift + _about 'searches for given terms amongst a given component' + _param '1: component type, one of: [ aliases | plugins | completions ]' + _param '2: term1 term2 @term3' + _param '3: [-]term4 [-]term5 ...' + _example '$ _bash-it-search-component aliases @git rake bundler -chruby' + # if one of the search terms is --enable or --disable, we will apply - # this action to the matches further down. - local action action_func component_singular - declare -a _search_commands=(enable disable) - for _search_command in "${_search_commands[@]}"; do - if [[ $(_bash-it-array-contains-element "--${_search_command}" "$@") == "true" ]]; then - action=$_search_command - component_singular=${_component} + # this action to the matches further ` down. + local component_singular action action_func + local -a search_commands=(enable disable) + for search_command in "${search_commands[@]}"; do + if [[ $(_bash-it-array-contains-element "--${search_command}" "$@") == "true" ]]; then + component_singular=${component} component_singular=${component_singular/es/} # aliases -> alias component_singular=${component_singular/ns/n} # plugins -> plugin + + action="${search_command}" action_func="_${action}-${component_singular}" break fi done - local _grep=$((which --skip-alias grep 2> /dev/null || which grep) | tail -n 1) + local -a terms=($@) # passed on the command line - declare -a terms=($@) # passed on the command line - declare -a matches=() # results that we found - declare -a negative_terms=() # terms that began with a dash + unset exact_terms + unset partial_terms + unset negative_terms + + local -a exact_terms=() # terms that should be included only if they match exactly + local -a partial_terms=() # terms that should be included if they match partially + local -a negative_terms=() # negated partial terms that should be excluded + + unset component_list + local -a component_list=( $(_bash-it-component-list "${component}") ) + local term for term in "${terms[@]}"; do - # -- can only be used for the actions: enable/disable - [[ "${term:0:2}" == "--" ]] && continue - [[ "${term:0:1}" == "-" ]] && negative_terms=(${negative_terms[@]} ${term:1}) && continue - - # print asterisk next to each result that is already enabled by the user - local term_match=($(echo "${help}"| ${_grep} -i -- ${term} | ${_grep} -E '\[( |x)\]' | cut -b -30 | sed 's/ *\[ \]//g;s/ *\[x\]/*/g;' )) - [[ "${#term_match[@]}" -gt 0 ]] && { - matches=(${matches[@]} ${term_match[@]}) # append to the list of results - } + local search_term="${term:1}" + if [[ "${term:0:2}" == "--" ]] ; then + continue + elif [[ "${term:0:1}" == "-" ]] ; then + negative_terms=(${negative_terms[@]} "${search_term}") + elif [[ "${term:0:1}" == "@" ]] ; then + if [[ $(_bash-it-array-contains-element "${search_term}" "${component_list[@]}") == "true" ]]; then + exact_terms=(${exact_terms[@]} "${search_term}") + fi + else + partial_terms=(${partial_terms[@]} $(_bash-it-component-list-matching "${component}" "${term}") ) + fi done - # now check if we found any negative terms, and subtract them - [[ ${#negative_terms} -gt 0 ]] && { - declare -a filtered_matches=() - for match in "${matches[@]}"; do - local negations=0 - for nt in "${negative_terms[@]}"; do - [[ "${match}" =~ "${nt}" ]] && negations=$(($negations+1)) - done - [[ $negations -eq 0 ]] && filtered_matches=(${filtered_matches[@]} ${match}) - done - matches=(${filtered_matches[@]}) - } + local -a total_matches=( $(_bash-it-array-dedup ${exact_terms[@]} ${partial_terms[@]}) ) - _bash-it-search-result $action $action_func - - unset matches filtered_matches terms + unset matches + declare -a matches=() + for match in ${total_matches[@]}; do + local include_match=true + if [[ ${#negative_terms[@]} -gt 0 ]]; then + ( _bash-it-component-term-matches-negation "${match}" "${negative_terms[@]}" ) && include_match=false + fi + ( ${include_match} ) && matches=(${matches[@]} "${match}") + done + _bash-it-search-result "${component}" "${action}" "${action_func}" "${matches[@]}" + unset matches final_matches terms } _bash-it-search-result() { - local action=$1; shift - local action_func=$1; shift + local component="$1"; shift + local action="$1"; shift + local action_func="$1"; shift + local -a matches=($@) + local color_component color_enable color_disable color_off - [[ -z "$NO_COLOR" ]] && { + color_sep=':' + + ( ${BASH_IT_SEARCH_USE_COLOR} ) && { color_component='\e[1;34m' color_enable='\e[1;32m' + suffix_enable='' + suffix_disable='' color_disable='\e[0;0m' color_off='\e[0;0m' - color_sep=':' } - [[ -n "$NO_COLOR" ]] && { + ( ${BASH_IT_SEARCH_USE_COLOR} ) || { color_component='' - color_sep=' => ' - color_enable='✓' + suffix_enable=' ✓ ︎' + suffix_disable=' ' + color_enable='' color_disable='' color_off='' } - if [[ "${#matches[*]}" -gt 0 ]] ; then - printf "${color_component}%13s${color_sep} ${color_off}" "${_component}" + local match + local modified=0 - sorted_matches=($(echo "${matches[*]}" | tr ' ' '\n' | sort | uniq)) + local flag="DEFER_CACHE_CLEANUP_FOR_${component}" + eval "export ${flag}=true" - for match in "${sorted_matches[@]}"; do - local match_color compatible_action - if [[ $match =~ "*" ]]; then - match_color=$color_enable + if [[ "${#matches[@]}" -gt 0 ]] ; then + printf "${color_component}%13s${color_sep} ${color_off}" "${component}" + + for match in "${matches[@]}"; do + local enabled=0 + ( _bash-it-component-item-is-enabled "${component}" "${match}" ) && enabled=1 + + local match_color compatible_action suffix opposite_suffix + + (( ${enabled} )) && { + match_color=${color_enable} + suffix=${suffix_enable} + opposite_suffix=${suffix_disable} compatible_action="disable" - else - match_color=$color_disable - compatible_action="enable" - fi + } - match_value=${match/\*/} # remove asterisk - len=${#match_value} - if [[ -n $NO_COLOR ]]; then - local m="${match_color}${match_value}" + (( ${enabled} )) || { + match_color=${color_disable} + suffix=${suffix_disable} + opposite_suffix=${suffix_enable} + compatible_action="enable" + } + + local len + if ( ${BASH_IT_SEARCH_USE_COLOR} ); then + local m="${match_color}${match}${suffix}" + len=${#m} + else + local m="${match}${suffix}" len=${#m} fi - printf " ${match_color}${match_value}" # print current state - + printf " ${match_color}${match}${suffix}" # print current state if [[ "${action}" == "${compatible_action}" ]]; then - # oh, i see – we need to either disable enabled, or enable disabled - # component. Let's start with the most important part: redrawing - # the search result backwards. Because style. - - printf "\033[${len}D" - for a in {0..30}; do - [[ $a -gt $len ]] && break - printf "%.*s" $a " " - sleep 0.07 # who knew you could sleep for fraction of the cost :) - done - printf "\033[${len}D" - result=$(${action_func} ${match_value}) + if [[ ${action} == "enable" && ${BASH_IT_SEARCH_USE_COLOR} == false ]]; then + _bash-it-flash-term ${len} "${match}${suffix}" + else + _bash-it-erase-term ${len} + fi + modified=1 + result=$(${action_func} ${match}) local temp="color_${compatible_action}" match_color=${!temp} - printf "${match_color}${match_value}" + _bash-it-rewind ${len} + printf "${match_color}${match}${opposite_suffix}" fi printf "${color_off}" done + [[ ${modified} -gt 0 ]] && _bash_it_search_cache_clean ${component} printf "\n" fi - +} + +_bash-it-rewind() { + local len="$1" + printf "\033[${len}D" +} + +_bash-it-flash-term() { + local len="$1" + local match="$2" + local delay=0.1 + local color + + for color in ${text_black} ${echo_bold_blue} ${bold_yellow} ${bold_red} ${echo_bold_green} ; do + sleep ${delay} + _bash-it-rewind "${len}" + printf "${color}${match}" + done +} + +_bash-it-erase-term() { + local len="$1" + _bash-it-rewind ${len} + for a in {0..30}; do + [[ ${a} -gt ${len} ]] && break + printf "%.*s" $a " " + sleep 0.05 + done } diff --git a/test/lib/helpers.bats b/test/lib/helpers.bats index 7720b930..563bc380 100644 --- a/test/lib/helpers.bats +++ b/test/lib/helpers.bats @@ -2,6 +2,7 @@ load ../test_helper load ../../lib/composure +load ../../lib/search load ../../plugins/available/base.plugin cite _about _param _example _group _author _version diff --git a/test/lib/search.bats b/test/lib/search.bats index 1043c1a4..29e861d7 100644 --- a/test/lib/search.bats +++ b/test/lib/search.bats @@ -1,16 +1,20 @@ #!/usr/bin/env bats load ../test_helper - load ../../lib/composure +load ../../lib/helpers +load ../../lib/search load ../../plugins/available/base.plugin +load ../../aliases/available/git.aliases +load ../../plugins/available/ruby.plugin +load ../../plugins/available/rails.plugin +load ../../completion/available/bundler.completion +load ../../completion/available/gem.completion +load ../../completion/available/rake.completion cite _about _param _example _group _author _version load ../../lib/helpers -load ../../lib/search - -NO_COLOR=true function local_setup { mkdir -p "$BASH_IT" @@ -23,46 +27,68 @@ function local_setup { rm -rf "$BASH_IT"/aliases/enabled rm -rf "$BASH_IT"/completion/enabled rm -rf "$BASH_IT"/plugins/enabled + + mkdir -p "$BASH_IT"/enabled + mkdir -p "$BASH_IT"/aliases/enabled + mkdir -p "$BASH_IT"/completion/enabled + mkdir -p "$BASH_IT"/plugins/enabled + + export OLD_PATH="$PATH" + export PATH="/usr/bin:/bin:/usr/sbin" +} + +function local_teardown { + export PATH="$OLD_PATH" + unset OLD_PATH } @test "search: plugin base" { + export BASH_IT_SEARCH_USE_COLOR=false run _bash-it-search-component 'plugins' 'base' - [[ "${lines[0]}" =~ 'plugins' && "${lines[0]}" =~ 'base' ]] + assert_line -n 0 ' plugins: base ' +} + +@test "search: git" { + run _bash-it-search 'git' --no-color + assert_line -n 0 ' aliases: git gitsvn ' + assert_line -n 1 ' plugins: autojump fasd git git-subrepo jgitflow jump ' + assert_line -n 2 ' completions: git git_flow git_flow_avh ' } @test "search: ruby gem bundle rake rails" { - # first disable them all, so that the output does not appear with a checkbox - # and we can compare the result - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' - # Now perform the search - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' - # And verify - assert [ "${lines[0]/✓/}" == ' aliases => bundler rails' ] - assert [ "${lines[1]/✓/}" == ' plugins => chruby chruby-auto rails ruby' ] - assert [ "${lines[2]/✓/}" == ' completions => bundler gem rake' ] + run _bash-it-search rails ruby gem bundler rake --no-color + + assert_line -n 0 ' aliases: bundler rails ' + assert_line -n 1 ' plugins: chruby chruby-auto rails ruby ' + assert_line -n 2 ' completions: bundler gem rake ' } -@test "search: ruby gem bundle -chruby rake rails" { - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' - run _bash-it-search 'ruby' 'gem' 'bundle' '-chruby' 'rake' 'rails' - assert [ "${lines[0]/✓/}" == ' aliases => bundler rails' ] - assert [ "${lines[1]/✓/}" == ' plugins => rails ruby' ] - assert [ "${lines[2]/✓/}" == ' completions => bundler gem rake' ] +@test "search: rails ruby gem bundler rake -chruby" { + run _bash-it-search rails ruby gem bundler rake -chruby --no-color + + assert_line -n 0 ' aliases: bundler rails ' + assert_line -n 1 ' plugins: rails ruby ' + assert_line -n 2 ' completions: bundler gem rake ' } -@test "search: (rails enabled) ruby gem bundle rake rails" { - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' '--disable' - run _enable-alias 'rails' - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' 'rails' - assert_line -n 0 ' aliases => bundler ✓rails' - assert_line -n 1 ' plugins => chruby chruby-auto rails ruby' - assert_line -n 2 ' completions => bundler gem rake' +@test "search: @git" { + run _bash-it-search '@git' --no-color + assert_line -n 0 ' aliases: git ' + assert_line -n 1 ' plugins: git ' + assert_line -n 2 ' completions: git ' } -@test "search: (all enabled) ruby gem bundle rake rails" { - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' '-chruby' 'rails' '--enable' - run _bash-it-search 'ruby' 'gem' 'bundle' 'rake' '-chruby' 'rails' - assert_line -n 0 ' aliases => ✓bundler ✓rails' - assert_line -n 1 ' plugins => ✓rails ✓ruby' - assert_line -n 2 ' completions => ✓bundler ✓gem ✓rake' +@test "search: @git --enable / --disable" { + set -e + run _bash-it-search '@git' --enable --no-color + run _bash-it-search '@git' --no-color + + [[ "${lines[0]}" =~ '✓' ]] + + run _bash-it-search '@git' --disable --no-color + run _bash-it-search '@git' --no-color + + assert_line -n 0 ' aliases: git ' + assert_line -n 0 ' aliases: git ' + assert_line -n 2 ' completions: git ' } From 05529dbd6b29ee273900fa386ccfff7c9a159822 Mon Sep 17 00:00:00 2001 From: Matthew Adams Date: Tue, 20 Nov 2018 07:59:16 -0600 Subject: [PATCH 011/107] more docker aliases --- aliases/available/docker.aliases.bash | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aliases/available/docker.aliases.bash b/aliases/available/docker.aliases.bash index 011135c6..e7738882 100644 --- a/aliases/available/docker.aliases.bash +++ b/aliases/available/docker.aliases.bash @@ -26,6 +26,10 @@ alias dkideps='docker-image-dependencies' # Output a graph of image dependencie alias dkre='docker-runtime-environment' # List environmental variables of the supplied image ID alias dkelc='docker exec -it `dklcid` bash' # Enter last container (works with Docker 1.3 and above) alias dkex='docker exec -it ' # Useful to run any commands into container without leaving host +alias dkri='docker run --rm -i ' +alias dkrit='docker run --rm -it ' +alias dkalp='docker run --rm -it alpine' +alias dkubu='docker run --rm -it ubuntu' # Added more recent cleanup options from newer docker versions alias dkip='docker image prune -a -f' From 1f80b1147683e91cbb3058986babee984567366b Mon Sep 17 00:00:00 2001 From: Matthew Adams Date: Tue, 20 Nov 2018 09:29:15 -0600 Subject: [PATCH 012/107] more aliases --- aliases/available/docker.aliases.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aliases/available/docker.aliases.bash b/aliases/available/docker.aliases.bash index e7738882..c002f17d 100644 --- a/aliases/available/docker.aliases.bash +++ b/aliases/available/docker.aliases.bash @@ -1,6 +1,8 @@ cite 'about-alias' about-alias 'docker abbreviations' +alias d='docker' +alias dk='docker' alias dklc='docker ps -l' # List last Docker container alias dklcid='docker ps -l -q' # List last Docker container ID alias dklcip='docker inspect -f "{{.NetworkSettings.IPAddress}}" $(docker ps -l -q)' # Get IP of last Docker container From 310ee837c9e2f635b0a36831cb7ab02c816be9ce Mon Sep 17 00:00:00 2001 From: Septian Dwic Date: Wed, 21 Nov 2018 02:05:19 +0700 Subject: [PATCH 013/107] init - bash its automatically load auto-completion --- plugins/available/jenv.plugin.bash | 4 +--- plugins/available/nodenv.plugin.bash | 5 +---- plugins/available/plenv.plugin.bash | 9 +++------ plugins/available/pyenv.plugin.bash | 7 ++----- plugins/available/rbenv.plugin.bash | 5 +---- 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/plugins/available/jenv.plugin.bash b/plugins/available/jenv.plugin.bash index 3cb2bcfc..08470688 100644 --- a/plugins/available/jenv.plugin.bash +++ b/plugins/available/jenv.plugin.bash @@ -4,6 +4,4 @@ about-plugin 'load jenv, if you are using it' export JENV_ROOT="$HOME/.jenv" pathmunge "$JENV_ROOT/bin" -if which jenv > /dev/null; then eval "$(jenv init -)"; fi - -[[ -e $JENV_ROOT/completions/jenv.bash ]] && source $JENV_ROOT/completions/jenv.bash +if which jenv > /dev/null; then eval "$(jenv init - bash)"; fi diff --git a/plugins/available/nodenv.plugin.bash b/plugins/available/nodenv.plugin.bash index f28e4045..1bbe7fbd 100644 --- a/plugins/available/nodenv.plugin.bash +++ b/plugins/available/nodenv.plugin.bash @@ -4,7 +4,4 @@ about-plugin 'load nodenv, if you are using it' export NODENV_ROOT="$HOME/.nodenv" pathmunge "$NODENV_ROOT/bin" -[[ `which nodenv` ]] && eval "$(nodenv init -)" - -# Load the auto-completion script if nodenv was loaded. -[[ -e $NODENV_ROOT/completions/nodenv.bash ]] && source $NODENV_ROOT/completions/nodenv.bash +[[ `which nodenv` ]] && eval "$(nodenv init - bash)" diff --git a/plugins/available/plenv.plugin.bash b/plugins/available/plenv.plugin.bash index 1e527b72..1da2d61b 100644 --- a/plugins/available/plenv.plugin.bash +++ b/plugins/available/plenv.plugin.bash @@ -4,18 +4,15 @@ cite about-plugin about-plugin 'plenv plugin for Perl' if [[ -e "${HOME}/.plenv/bin" ]] ; then - + # load plenv bin dir into path if it exists pathmunge "${HOME}/.plenv/bin" - + fi if [[ `which plenv` ]] ; then # init plenv - eval "$(plenv init -)" - - # Load the auto-completion script if it exists. - [[ -e "${HOME}/.plenv/completions/plenv.bash" ]] && source "${HOME}/.plenv/completions/plenv.bash" + eval "$(plenv init - bash)" fi diff --git a/plugins/available/pyenv.plugin.bash b/plugins/available/pyenv.plugin.bash index 0f6bffb8..dced31a8 100644 --- a/plugins/available/pyenv.plugin.bash +++ b/plugins/available/pyenv.plugin.bash @@ -4,12 +4,9 @@ about-plugin 'load pyenv, if you are using it' export PYENV_ROOT="$HOME/.pyenv" pathmunge "$PYENV_ROOT/bin" -[[ `which pyenv` ]] && eval "$(pyenv init -)" +[[ `which pyenv` ]] && eval "$(pyenv init - bash)" #Load pyenv virtualenv if the virtualenv plugin is installed. if pyenv virtualenv-init - &> /dev/null; then - eval "$(pyenv virtualenv-init -)" + eval "$(pyenv virtualenv-init - bash)" fi - -# Load the auto-completion script if pyenv was loaded. -[[ -e $PYENV_ROOT/completions/pyenv.bash ]] && source $PYENV_ROOT/completions/pyenv.bash diff --git a/plugins/available/rbenv.plugin.bash b/plugins/available/rbenv.plugin.bash index 75d24154..ecba0c89 100644 --- a/plugins/available/rbenv.plugin.bash +++ b/plugins/available/rbenv.plugin.bash @@ -4,7 +4,4 @@ about-plugin 'load rbenv, if you are using it' export RBENV_ROOT="$HOME/.rbenv" pathmunge "$RBENV_ROOT/bin" -[[ `which rbenv` ]] && eval "$(rbenv init -)" - -# Load the auto-completion script if rbenv was loaded. -[[ -e $RBENV_ROOT/completions/rbenv.bash ]] && source $RBENV_ROOT/completions/rbenv.bash +[[ `which rbenv` ]] && eval "$(rbenv init - bash)" From 1ba023c97a33c2ac87abb46ac75a9afdd585ba5b Mon Sep 17 00:00:00 2001 From: Christophe Aguettaz Date: Fri, 23 Nov 2018 22:25:14 +0100 Subject: [PATCH 014/107] [bugfix][wip] Fixed issue with Debian's bash-completion --- bash_it.sh | 10 +++++++++- lib/helpers.bash | 37 +++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/bash_it.sh b/bash_it.sh index e2b00de7..82b7e1b9 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -43,9 +43,17 @@ _load_global_bash_it_files # Load enabled aliases, completion, plugins for file_type in "aliases" "plugins" "completion" do - _load_bash_it_files $file_type + _bash_it_list_bash_it_files_return=() + _list_bash_it_files $file_type + + for config_file in "${_bash_it_list_bash_it_files_return[@]}" ; do + . "$config_file" + done done +unset _bash_it_list_bash_it_files_return +unset _bash_it_config_file + # Load theme, if a theme was set if [[ ! -z "${BASH_IT_THEME}" ]]; then # Load colors and helpers first so they can be used in base theme diff --git a/lib/helpers.bash b/lib/helpers.bash index 565173ed..bb592bab 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -14,16 +14,18 @@ function _command_exists () type "$1" &> /dev/null ; } -# Helper function loading various enable-able files -function _load_bash_it_files() { +# Helper function listing various enable-able files to be sourced +# The files need to be sourced in global scope to preserve scope of 'declare' +function _list_bash_it_files() { subdirectory="$1" if [ -d "${BASH_IT}/${subdirectory}/enabled" ] then FILES="${BASH_IT}/${subdirectory}/enabled/*.bash" - for config_file in $FILES + + for _bash_it_config_file in $FILES do - if [ -e "${config_file}" ]; then - source $config_file + if [ -e "${_bash_it_config_file}" ]; then + _bash_it_list_bash_it_files_return+=("$_bash_it_config_file") fi done fi @@ -43,20 +45,23 @@ function _load_global_bash_it_files() { fi } -# Function for reloading aliases -function reload_aliases() { - _load_bash_it_files "aliases" +function _make_reload_alias() { + printf %s '\ + _bash_it_list_bash_it_files_return=() ;\ + _list_bash_it_files '"$1"' ;\ + for _bash_it_config_file in "${_bash_it_list_bash_it_files_return[@]}"; do \ + . "$_bash_it_config_file" ;\ + done' } -# Function for reloading auto-completion -function reload_completion() { - _load_bash_it_files "completion" -} +# Alias for reloading aliases +alias reload_aliases="$(_make_reload_alias aliases)" -# Function for reloading plugins -function reload_plugins() { - _load_bash_it_files "plugins" -} +# Alias for reloading auto-completion +alias reload_completion="$(_make_reload_alias completion)" + +# Alias for reloading plugins +alias reload_plugins="$(_make_reload_alias plugins)" bash-it () { From 2f3d4bd1300960b47f44f4403e1cd390ed1cb2b1 Mon Sep 17 00:00:00 2001 From: Christophe Aguettaz Date: Fri, 23 Nov 2018 22:59:19 +0100 Subject: [PATCH 015/107] [cleanup] Added missing global variable cleanup --- lib/helpers.bash | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index bb592bab..9c3e53f7 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -51,7 +51,9 @@ function _make_reload_alias() { _list_bash_it_files '"$1"' ;\ for _bash_it_config_file in "${_bash_it_list_bash_it_files_return[@]}"; do \ . "$_bash_it_config_file" ;\ - done' + done ;\ + unset _bash_it_list_bash_it_files_return ;\ + unset _bash_it_config_file' } # Alias for reloading aliases From 09c2be9d6bec0d0d6b917203e3c222970ea8ebe2 Mon Sep 17 00:00:00 2001 From: Konstantin Gredeskoul Date: Fri, 23 Nov 2018 16:14:12 -0800 Subject: [PATCH 016/107] =?UTF-8?q?Refactor=20(extract=20utilities=20+=20a?= =?UTF-8?q?dd=20tests)=20&=20more=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Extracting common utilities into utilities.bash * Adding new tests for utilities * Relocating the cache file to be under $BASH_IT * Removing cache cleanup deferral code for now * Wiping the cache in local_setup in tests. --- .gitignore | 1 + lib/helpers.bash | 9 ++- lib/search.bash | 142 ++++++++------------------------------- lib/utilities.bash | 144 ++++++++++++++++++++++++++++++++++++++++ test/lib/helpers.bats | 1 + test/lib/search.bats | 2 + test/lib/utilities.bats | 108 ++++++++++++++++++++++++++++++ 7 files changed, 289 insertions(+), 118 deletions(-) mode change 100644 => 100755 lib/search.bash create mode 100644 lib/utilities.bash create mode 100644 test/lib/utilities.bats diff --git a/.gitignore b/.gitignore index 2e6fb7c0..6fad6279 100755 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ bats *.sublime-workspace *.sublime-project enabled/* +tmp/ diff --git a/lib/helpers.bash b/lib/helpers.bash index cbcdd42d..bec603f1 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -70,7 +70,7 @@ bash-it () example '$ bash-it disable alias hg [tmux]...' example '$ bash-it migrate' example '$ bash-it update' - example '$ bash-it search [-|@]term1 [-|@]term2 ... [--enable | --disable | --help | --refresh | --no-color ]' + example '$ bash-it search [-|@]term1 [-|@]term2 ... [ -e/--enable ] [ -d/--disable ] [ -r/--refresh ] [ -c/--no-color ]' example '$ bash-it version' example '$ bash-it reload' typeset verb=${1:-} @@ -78,6 +78,7 @@ bash-it () typeset component=${1:-} shift typeset func + case $verb in show) func=_bash-it-$component;; @@ -393,8 +394,7 @@ _disable-thing () fi fi - local flag="DEFER_CACHE_CLEANUP_FOR_${file_type}" - [[ -z ${!flag} ]] && _bash_it_search_cache_clean "${file_type}" + _bash-it-clean-component-cache "${file_type}" if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then exec ${0/-/} @@ -491,8 +491,7 @@ _enable-thing () ln -s ../$subdirectory/available/$to_enable "${BASH_IT}/enabled/${use_load_priority}${BASH_IT_LOAD_PRIORITY_SEPARATOR}${to_enable}" fi - local flag="DEFER_CACHE_CLEANUP_FOR_${file_type}" - [[ -z ${!flag} ]] && _bash_it_search_cache_clean "${file_type}" + _bash-it-clean-component-cache "${file_type}" if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then exec ${0/-/} diff --git a/lib/search.bash b/lib/search.bash old mode 100644 new mode 100755 index a54971f5..1c487a3e --- a/lib/search.bash +++ b/lib/search.bash @@ -7,10 +7,11 @@ # # Usage: # ❯ bash-it search [-|@]term1 [-|@]term2 ... \ -# [ --enable | -e ] \ -# [ --disable | -d ] \ -# [ --refresh | -r ] -# [ --help | -h ] +# [ --enable | -e ] \ +# [ --disable | -d ] \ +# [ --no-color | -c ] \ +# [ --refresh | -r ] \ +# [ --help | -h ] # # Single dash, as in "-chruby", indicates a negative search term. # Double dash indicates a command that is to be applied to the search result. @@ -52,6 +53,8 @@ _bash-it-search() { _param '2: [ term2 ]...' _example '$ _bash-it-search @git ruby -rvm rake bundler' + [[ -z "$(type _bash-it-array-contains-element 2>/dev/null)" ]] && source "${BASH_IT}/lib/utilities.bash" + local component export BASH_IT_SEARCH_USE_COLOR=true export BASH_IT_GREP=${BASH_IT_GREP:-$(which egrep)} @@ -68,17 +71,19 @@ _bash-it-search() { _bash-it-search-help return 0 elif [[ ${word} == "--refresh" || ${word} == "-r" ]]; then - _bash_it_search_cache_clean - elif [[ ${word} == "--no-color" ]]; then + _bash-it-clean-component-cache + elif [[ ${word} == "--no-color" || ${word} == '-c' ]]; then export BASH_IT_SEARCH_USE_COLOR=false else args=(${args[@]} ${word}) fi done - for component in "${BASH_IT_COMPONENTS[@]}" ; do - _bash-it-search-component "${component}" "${args[@]}" - done + if [[ ${#args} -gt 0 ]]; then + for component in "${BASH_IT_COMPONENTS[@]}" ; do + _bash-it-search-component "${component}" "${args[@]}" + done + fi return 0 } @@ -88,7 +93,11 @@ _bash-it-search-help() { ${echo_underline_yellow}USAGE${echo_normal} bash-it search [-|@]term1 [-|@]term2 ... \\ - [ --enable | --disable | --help | --refresh | --no-color ] + [ --enable | -e ] \\ + [ --disable | -d ] \\ + [ --no-color | -c ] \\ + [ --refresh | -r ] \\ + [ --help | -h ] ${echo_underline_yellow}DESCRIPTION${echo_normal} @@ -110,11 +119,11 @@ ${echo_underline_yellow}DESCRIPTION${echo_normal} eg. '@git' would only match aliases, plugins and completions named 'git'. ${echo_underline_yellow}FLAGS${echo_normal} - --enable ${echo_purple}Enable all matching componenents.${echo_normal} - --disable ${echo_purple}Disable all matching componenents.${echo_normal} - --help ${echo_purple}Print this help.${echo_normal} - --refresh ${echo_purple}Force a refresh of the search cache.${echo_normal} - --no-color ${echo_purple}Disable color output and use monochrome text.${echo_normal} + --enable | -e ${echo_purple}Enable all matching componenents.${echo_normal} + --disable | -d ${echo_purple}Disable all matching componenents.${echo_normal} + --help | -h ${echo_purple}Print this help.${echo_normal} + --refresh | -r ${echo_purple}Force a refresh of the search cache.${echo_normal} + --no-color | -c ${echo_purple}Disable color output and use monochrome text.${echo_normal} ${echo_underline_yellow}EXAMPLES${echo_normal} @@ -156,46 +165,6 @@ ${echo_underline_yellow}SUMMARY${echo_normal} " } -_bash-it-cache-file() { - local component="${1}" - local file="/tmp/bash_it/${component}.status" - mkdir -p $(dirname ${file}) - printf ${file} -} - -_bash_it_search_cache_clean() { - local component="$1" - if [[ -z ${component} ]] ; then - for component in "${BASH_IT_COMPONENTS[@]}" ; do - _bash_it_search_cache_clean "${component}" - done - else - rm -f $(_bash-it-cache-file ${component}) - fi -} - -#——————————————————————————————————————————————————————————————————————————————— -# array=("something to search for" "a string" "test2000") -# _bash-it-array-contains-element "a string" "${array[@]}" -# ( prints "true" or "false" ) -_bash-it-array-contains-element () { - local e - local r=false - for e in "${@:2}"; do [[ "$e" == "$1" ]] && r=true; done - echo -n $r -} - -_bash-it-array-dedup() { - echo "$*" | tr ' ' '\n' | sort -u | tr '\n' ' ' -} - -_bash-it-grep() { - if [[ -z "${BASH_IT_GREP}" ]] ; then - export BASH_IT_GREP="$(which egrep || which grep || '/usr/bin/grep')" - fi - printf "%s " "${BASH_IT_GREP}" -} - _bash-it-is-partial-match() { local component="$1" local term="$2" @@ -212,51 +181,6 @@ _bash-it-component-term-matches-negation() { return 1 } -_bash-it-component-help() { - local component="$1" - local file=$(_bash-it-cache-file ${component}) - if [[ ! -s "${file}" || -z $(find "${file}" -mmin -2) ]] ; then - rm -f "${file}" 2>/dev/null - local func="_bash-it-${component}" - ${func} | $(_bash-it-grep) -E ' \[' | cat > ${file} - fi - cat "${file}" -} - -_bash-it-component-list() { - local component="$1" - _bash-it-component-help "${component}" | awk '{print $1}' | uniq | sort | tr '\n' ' ' -} - -_bash-it-component-list-matching() { - local component="$1"; shift - local term="$1" - _bash-it-component-help "${component}" | $(_bash-it-grep) -E -- "${term}" | awk '{print $1}' | sort | uniq -} - -_bash-it-component-list-enabled() { - local component="$1" - _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' -} - -_bash-it-component-list-disabled() { - local component="$1" - _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' -} - -_bash-it-component-item-is-enabled() { - local component="$1" - local item="$2" - _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" -} - -_bash-it-component-item-is-disabled() { - local component="$1" - local item="$2" - _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" -} - - _bash-it-search-component() { local component="$1" shift @@ -272,7 +196,7 @@ _bash-it-search-component() { local component_singular action action_func local -a search_commands=(enable disable) for search_command in "${search_commands[@]}"; do - if [[ $(_bash-it-array-contains-element "--${search_command}" "$@") == "true" ]]; then + if $(_bash-it-array-contains-element "--${search_command}" "$@"); then component_singular=${component} component_singular=${component_singular/es/} # aliases -> alias component_singular=${component_singular/ns/n} # plugins -> plugin @@ -304,7 +228,7 @@ _bash-it-search-component() { elif [[ "${term:0:1}" == "-" ]] ; then negative_terms=(${negative_terms[@]} "${search_term}") elif [[ "${term:0:1}" == "@" ]] ; then - if [[ $(_bash-it-array-contains-element "${search_term}" "${component_list[@]}") == "true" ]]; then + if $(_bash-it-array-contains-element "${search_term}" "${component_list[@]}"); then exact_terms=(${exact_terms[@]} "${search_term}") fi else @@ -358,9 +282,6 @@ _bash-it-search-result() { local match local modified=0 - local flag="DEFER_CACHE_CLEANUP_FOR_${component}" - eval "export ${flag}=true" - if [[ "${#matches[@]}" -gt 0 ]] ; then printf "${color_component}%13s${color_sep} ${color_off}" "${component}" @@ -384,14 +305,9 @@ _bash-it-search-result() { compatible_action="enable" } + local m="${match}${suffix}" local len - if ( ${BASH_IT_SEARCH_USE_COLOR} ); then - local m="${match_color}${match}${suffix}" - len=${#m} - else - local m="${match}${suffix}" - len=${#m} - fi + len=${#m} printf " ${match_color}${match}${suffix}" # print current state if [[ "${action}" == "${compatible_action}" ]]; then @@ -411,7 +327,7 @@ _bash-it-search-result() { printf "${color_off}" done - [[ ${modified} -gt 0 ]] && _bash_it_search_cache_clean ${component} + [[ ${modified} -gt 0 ]] && _bash-it-clean-component-cache ${component} printf "\n" fi } diff --git a/lib/utilities.bash b/lib/utilities.bash new file mode 100644 index 00000000..93e96606 --- /dev/null +++ b/lib/utilities.bash @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +# +# A collection of reusable functions. + +########################################################################### +# Component-specific functions (component is either an alias, a plugin, or a +# completion). +########################################################################### + +_bash-it-component-help() { + local component=$(_bash-it-pluralize-component "${1}") + local file=$(_bash-it-component-cache-file ${component}) + if [[ ! -s "${file}" || -z $(find "${file}" -mmin -300) ]] ; then + rm -f "${file}" 2>/dev/null + local func="_bash-it-${component}" + ${func} | $(_bash-it-grep) -E ' \[' | cat > ${file} + fi + cat "${file}" +} + +_bash-it-component-cache-file() { + local component=$(_bash-it-pluralize-component "${1}") + local file="${BASH_IT}/tmp/cache/${component}" + [[ -f ${file} ]] || mkdir -p $(dirname ${file}) + printf "${file}" +} + +_bash-it-pluralize-component() { + local component="${1}" + local len=$(( ${#component} - 1 )) + # pluralize component name for consistency + [[ ${component:${len}:1} != 's' ]] && component="${component}s" + [[ ${component} == "alias" ]] && component="aliases" + printf ${component} +} + +_bash-it-clean-component-cache() { + local component="$1" + local cache + local -a BASH_IT_COMPONENTS=(aliases plugins completions) + if [[ -z ${component} ]] ; then + for component in "${BASH_IT_COMPONENTS[@]}" ; do + _bash-it-clean-component-cache "${component}" + done + else + cache="$(_bash-it-component-cache-file ${component})" + [[ -f "${cache}" ]] && rm -f "${cache}" + fi +} + +########################################################################### +# Generic utilies +########################################################################### + +# This function searches an array for an exact match against the term passed +# as the first argument to the function. This function exits as soon as +# a match is found. +# +# Returns: +# 0 when a match is found, otherwise 1. +# +# Examples: +# $ declare -a fruits=(apple orange pear mandarin) +# +# $ _bash-it-array-contains-element apple "@{fruits[@]}" && echo 'contains apple' +# contains apple +# +# $ if $(_bash-it-array-contains-element pear "${fruits[@]}"); then +# echo "contains pear!" +# fi +# contains pear! +# +# +_bash-it-array-contains-element() { + local e + for e in "${@:2}"; do + [[ "$e" == "$1" ]] && return 0 + done + return 1 +} + +# Dedupe a simple array of words without spaces. +_bash-it-array-dedup() { + echo "$*" | tr ' ' '\n' | sort -u | tr '\n' ' ' +} + +# Outputs a full path of the gre found on the filesystem +_bash-it-grep() { + if [[ -z "${BASH_IT_GREP}" ]] ; then + export BASH_IT_GREP="$(which egrep || which grep || '/usr/bin/grep')" + fi + printf "%s " "${BASH_IT_GREP}" +} + + +# Returns an array of items within each compoenent. +_bash-it-component-list() { + local component="$1" + _bash-it-component-help "${component}" | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +_bash-it-component-list-matching() { + local component="$1"; shift + local term="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -- "${term}" | awk '{print $1}' | sort | uniq +} + +_bash-it-component-list-enabled() { + local component="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +_bash-it-component-list-disabled() { + local component="$1" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | awk '{print $1}' | uniq | sort | tr '\n' ' ' +} + +# Checks if a given item is enabled for a particular component/file-type. +# Uses the component cache if available. +# +# Returns: +# 0 if an item of the component is enabled, 1 otherwise. +# +# Examples: +# _bash-it-component-item-is-enabled alias git && echo "git alias is enabled" +_bash-it-component-item-is-enabled() { + local component="$1" + local item="$2" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" +} + +# Checks if a given item is disabled for a particular component/file-type. +# Uses the component cache if available. +# +# Returns: +# 0 if an item of the component is enabled, 1 otherwise. +# +# Examples: +# _bash-it-component-item-is-disabled alias git && echo "git aliases are disabled" +_bash-it-component-item-is-disabled() { + local component="$1" + local item="$2" + _bash-it-component-help "${component}" | $(_bash-it-grep) -E -v '\[x\]' | $(_bash-it-grep) -E -q -- "^${item}\s" +} diff --git a/test/lib/helpers.bats b/test/lib/helpers.bats index 563bc380..6c4f706a 100644 --- a/test/lib/helpers.bats +++ b/test/lib/helpers.bats @@ -2,6 +2,7 @@ load ../test_helper load ../../lib/composure +load ../../lib/utilities load ../../lib/search load ../../plugins/available/base.plugin diff --git a/test/lib/search.bats b/test/lib/search.bats index 29e861d7..56cda073 100644 --- a/test/lib/search.bats +++ b/test/lib/search.bats @@ -3,6 +3,7 @@ load ../test_helper load ../../lib/composure load ../../lib/helpers +load ../../lib/utilities load ../../lib/search load ../../plugins/available/base.plugin load ../../aliases/available/git.aliases @@ -27,6 +28,7 @@ function local_setup { rm -rf "$BASH_IT"/aliases/enabled rm -rf "$BASH_IT"/completion/enabled rm -rf "$BASH_IT"/plugins/enabled + rm -rf "$BASH_IT"/tmp/cache mkdir -p "$BASH_IT"/enabled mkdir -p "$BASH_IT"/aliases/enabled diff --git a/test/lib/utilities.bats b/test/lib/utilities.bats new file mode 100644 index 00000000..be21fa40 --- /dev/null +++ b/test/lib/utilities.bats @@ -0,0 +1,108 @@ +#!/usr/bin/env bats + +load ../test_helper +load ../../lib/composure +load ../../lib/helpers +load ../../lib/utilities +load ../../lib/search + +cite _about _param _example _group _author _version + +function local_setup { + mkdir -p "$BASH_IT" + lib_directory="$(cd "$(dirname "$0")" && pwd)" + # Use rsync to copy Bash-it to the temp folder + # rsync is faster than cp, since we can exclude the large ".git" folder + rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT" + + rm -rf "$BASH_IT"/enabled + rm -rf "$BASH_IT"/aliases/enabled + rm -rf "$BASH_IT"/completion/enabled + rm -rf "$BASH_IT"/plugins/enabled + rm -rf "$BASH_IT"/tmp/cache + + mkdir -p "$BASH_IT"/enabled + mkdir -p "$BASH_IT"/aliases/enabled + mkdir -p "$BASH_IT"/completion/enabled + mkdir -p "$BASH_IT"/plugins/enabled +} + +function has_match() { + $(_bash-it-array-contains-element ${@}) && echo "has" "$1" +} + +function item_enabled() { + $(_bash-it-component-item-is-enabled ${@}) && echo "$1" "$2" "is enabled" +} + +function item_disabled() { + $(_bash-it-component-item-is-disabled ${@}) && echo "$1" "$2" "is disabled" +} + +@test "_bash-it-component-item-is-enabled() - for a disabled item" { + run item_enabled aliases svn + assert_line -n 0 '' +} + +@test "_bash-it-component-item-is-enabled() - for an enabled/disabled item" { + run bash-it enable alias svn + assert_line -n 0 'svn enabled with priority 150.' + + run item_enabled alias svn + assert_line -n 0 'alias svn is enabled' + + run bash-it disable alias svn + assert_line -n 0 'svn disabled.' + + run item_enabled alias svn + assert_line -n 0 '' +} + +@test "_bash-it-component-item-is-disabled() - for a disabled item" { + run item_disabled alias svn + assert_line -n 0 'alias svn is disabled' +} + +@test "_bash-it-component-item-is-disabled() - for an enabled/disabled item" { + run bash-it enable alias svn + assert_line -n 0 'svn enabled with priority 150.' + + run item_disabled alias svn + assert_line -n 0 '' + + run bash-it disable alias svn + assert_line -n 0 'svn disabled.' + + run item_disabled alias svn + assert_line -n 0 'alias svn is disabled' +} + +@test "_bash-it-array-contains-element() - when match is found, and is the first" { + declare -a fruits=(apple pear orange mandarin) + run has_match apple "${fruits[@]}" + assert_line -n 0 'has apple' +} + +@test "_bash-it-array-contains-element() - when match is found, and is the last" { + declare -a fruits=(apple pear orange mandarin) + run has_match mandarin "${fruits[@]}" + assert_line -n 0 'has mandarin' +} + +@test "_bash-it-array-contains-element() - when match is found, and is in the middle" { + declare -a fruits=(apple pear orange mandarin) + run has_match pear "${fruits[@]}" + assert_line -n 0 'has pear' +} + +@test "_bash-it-array-contains-element() - when match is found, and it has spaces" { + declare -a fruits=(apple pear orange mandarin "yellow watermelon") + run has_match "yellow watermelon" "${fruits[@]}" + assert_line -n 0 'has yellow watermelon' +} + +@test "_bash-it-array-contains-element() - when match is not found" { + declare -a fruits=(apple pear orange mandarin) + run has_match xyz "${fruits[@]}" + assert_line -n 0 '' +} From 6fcb32f85143d44236ce509012dab2982e7df564 Mon Sep 17 00:00:00 2001 From: Matthew Adams Date: Sat, 24 Nov 2018 08:44:46 -0600 Subject: [PATCH 017/107] rm d, dkalp & dkubu --- aliases/available/docker.aliases.bash | 3 --- 1 file changed, 3 deletions(-) diff --git a/aliases/available/docker.aliases.bash b/aliases/available/docker.aliases.bash index c002f17d..5606b619 100644 --- a/aliases/available/docker.aliases.bash +++ b/aliases/available/docker.aliases.bash @@ -1,7 +1,6 @@ cite 'about-alias' about-alias 'docker abbreviations' -alias d='docker' alias dk='docker' alias dklc='docker ps -l' # List last Docker container alias dklcid='docker ps -l -q' # List last Docker container ID @@ -30,8 +29,6 @@ alias dkelc='docker exec -it `dklcid` bash' # Enter last container (works with D alias dkex='docker exec -it ' # Useful to run any commands into container without leaving host alias dkri='docker run --rm -i ' alias dkrit='docker run --rm -it ' -alias dkalp='docker run --rm -it alpine' -alias dkubu='docker run --rm -it ubuntu' # Added more recent cleanup options from newer docker versions alias dkip='docker image prune -a -f' From bd0c1d92c508a1f6945f7822d0c36ee0ee2c78ef Mon Sep 17 00:00:00 2001 From: icanhazstring Date: Tue, 27 Nov 2018 12:07:40 +0100 Subject: [PATCH 018/107] Add support for composer aliases --- aliases/available/composer.aliases.bash | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 aliases/available/composer.aliases.bash diff --git a/aliases/available/composer.aliases.bash b/aliases/available/composer.aliases.bash new file mode 100644 index 00000000..4820d017 --- /dev/null +++ b/aliases/available/composer.aliases.bash @@ -0,0 +1,40 @@ +cite 'about-alias' +about-alias 'common composer abbreviations' + +# Aliases +alias cab='composer about' +alias car='composer archive' +alias cb='composer browser' +alias ccpq='composer check-platform-reqs' +alias ccc='composer clear-cache' +alias cconf='composer config' +alias ccp='composer create-project' +alias cdep='composer depends' +alias cdiag='composer diagnose' +alias cdump='composer dump-autoload' +alias cdumpo='composer dump-autoload -o' +alias cex='composer exec' +alias cglob='composer global' +alias ch='composer help' +alias chome='composer home' +alias ci='composer install' +alias cinfo='composer info' +alias cinit='composer init' +alias clic='composer license' +alias clist='composer list' +alias cout='composer outdated' +alias cp='composer prohibits' +alias crem='composer remove' +alias creq='composer require' +alias creqd='composer require --dev' +alias crs='composer run-script' +alias cs='composer search' +alias csu='composer self-update' +alias cshow='composer show' +alias cstat='composer status' +alias csugg='composer suggest' +alias cupd='composer update' +alias cupg='composer upgrade' +alias cval='composer validate' +alias cwhy='composer why' +alias cwhyn='composer why-not' From dbe4cc690f5906f18dca636fe19d96fe6bad60f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Fr=C3=B6mer?= Date: Wed, 28 Nov 2018 10:40:56 +0100 Subject: [PATCH 019/107] Change default prefix to 'co' Should resolve problem with accidental overriding global default commands like `cp` --- aliases/available/composer.aliases.bash | 71 ++++++++++++------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/aliases/available/composer.aliases.bash b/aliases/available/composer.aliases.bash index 4820d017..5ccb2e24 100644 --- a/aliases/available/composer.aliases.bash +++ b/aliases/available/composer.aliases.bash @@ -2,39 +2,38 @@ cite 'about-alias' about-alias 'common composer abbreviations' # Aliases -alias cab='composer about' -alias car='composer archive' -alias cb='composer browser' -alias ccpq='composer check-platform-reqs' -alias ccc='composer clear-cache' -alias cconf='composer config' -alias ccp='composer create-project' -alias cdep='composer depends' -alias cdiag='composer diagnose' -alias cdump='composer dump-autoload' -alias cdumpo='composer dump-autoload -o' -alias cex='composer exec' -alias cglob='composer global' -alias ch='composer help' -alias chome='composer home' -alias ci='composer install' -alias cinfo='composer info' -alias cinit='composer init' -alias clic='composer license' -alias clist='composer list' -alias cout='composer outdated' -alias cp='composer prohibits' -alias crem='composer remove' -alias creq='composer require' -alias creqd='composer require --dev' -alias crs='composer run-script' -alias cs='composer search' -alias csu='composer self-update' -alias cshow='composer show' -alias cstat='composer status' -alias csugg='composer suggest' -alias cupd='composer update' -alias cupg='composer upgrade' -alias cval='composer validate' -alias cwhy='composer why' -alias cwhyn='composer why-not' +alias coab='composer about' +alias coar='composer archive' +alias cob='composer browser' +alias cocpr='composer check-platform-reqs' +alias cocc='composer clear-cache' +alias cocfg='composer config' +alias cocp='composer create-project' +alias codp='composer depends' +alias codiag='composer diagnose' +alias codmp='composer dump-autoload' +alias coex='composer exec' +alias coglob='composer global' +alias coh='composer help' +alias cohome='composer home' +alias coi='composer install' +alias coinf='composer info' +alias coini='composer init' +alias coli='composer license' +alias colis='composer list' +alias coout='composer outdated' +alias cop='composer prohibits' +alias corem='composer remove' +alias coreq='composer require' +alias coreqd='composer require --dev' +alias cors='composer run-script' +alias cos='composer search' +alias cosu='composer self-update' +alias coshow='composer show' +alias costat='composer status' +alias cosugg='composer suggest' +alias coup='composer update' +alias coupg='composer upgrade' +alias coval='composer validate' +alias cowhy='composer why' +alias cowhyn='composer why-not' From 8e7a566d96e59440dfc06f7568fbc9a0e1374567 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Sun, 2 Dec 2018 10:16:33 -0600 Subject: [PATCH 020/107] Show update prompt when running bash-it update This utilizes the body of the merged PR requests to show the commits that are included in this update. It gives the user a chance to decline the upgrades by pressing n or N. --- lib/helpers.bash | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 565173ed..5652a2b8 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -181,18 +181,31 @@ _bash-it_update() { status="$(git rev-list master..${BASH_IT_REMOTE}/master 2> /dev/null)" if [[ -n "${status}" ]]; then - git pull --rebase &> /dev/null - if [[ $? -eq 0 ]]; then - echo "Bash-it successfully updated." - echo "" - echo "Migrating your installation to the latest version now..." - _bash-it-migrate - echo "" - echo "All done, enjoy!" - bash-it reload - else - echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean." - fi + git log --merges --format="%h: %b (%an)" master..${BASH_IT_REMOTE}/master + echo "" + read -e -n 1 -p "Would you like to update to $(git log -1 --format=%h origin/master)? [Y/n] " RESP + case $RESP in + [yY]|"") + git pull --rebase &> /dev/null + if [[ $? -eq 0 ]]; then + echo "Bash-it successfully updated." + echo "" + echo "Migrating your installation to the latest version now..." + _bash-it-migrate + echo "" + echo "All done, enjoy!" + bash-it reload + else + echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean." + fi + ;; + [nN]) + echo "Not upgrading…" + ;; + *) + echo -e "\033[91mPlease choose y or n.\033[m" + ;; + esac else echo "Bash-it is up to date, nothing to do!" fi From 185c2879d56637babc4aae2eba8a20ecb9977752 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Sun, 2 Dec 2018 10:47:37 -0600 Subject: [PATCH 021/107] Update to show the subject if the body is empty --- lib/helpers.bash | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 5652a2b8..4cc2d574 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -181,7 +181,16 @@ _bash-it_update() { status="$(git rev-list master..${BASH_IT_REMOTE}/master 2> /dev/null)" if [[ -n "${status}" ]]; then - git log --merges --format="%h: %b (%an)" master..${BASH_IT_REMOTE}/master + + for i in $(git rev-list --merges master..${BASH_IT_REMOTE}); do + num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l) + if [ $num_of_lines -eq 1 ]; then + description="%s" + else + description="%b" + fi + git log --format="%h: $description (%an)" -1 $i + done echo "" read -e -n 1 -p "Would you like to update to $(git log -1 --format=%h origin/master)? [Y/n] " RESP case $RESP in From 6706814dbc36d9974e497d382a1bf57297235364 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Sun, 2 Dec 2018 20:44:00 -0600 Subject: [PATCH 022/107] Adjust so this only runs when Homebrew is installed (thanks @nwinkler) --- completion/available/crystal.completion.bash | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/completion/available/crystal.completion.bash b/completion/available/crystal.completion.bash index b83be253..cbc891d7 100644 --- a/completion/available/crystal.completion.bash +++ b/completion/available/crystal.completion.bash @@ -1,8 +1,11 @@ if which crystal >/dev/null 2>&1; then - BREW_PREFIX=$(brew --prefix) - if [ -f "$BREW_PREFIX"/etc/bash_completion.d/crystal ]; then - . "$BREW_PREFIX"/etc/bash_completion.d/crystal + if which brew >/dev/null 2>&1; then + BREW_PREFIX=$(brew --prefix) + + if [ -f "$BREW_PREFIX"/etc/bash_completion.d/crystal ]; then + . "$BREW_PREFIX"/etc/bash_completion.d/crystal + fi fi fi From babb1e667544281093bd292c186f0abcccd30b45 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Mon, 3 Dec 2018 21:17:49 -0600 Subject: [PATCH 023/107] Adjust to only show merges into master Adding `--first-parent` ensures that only commits from the master branch are used when showing the history. I've verified this change directly by comparing the `rev-list` output for `703105c..97df5c45`: ```console $ git rev-list --merges 703105c...97df5c4 97df5c4540534c57da2381b1675cd2461274b2a6 b5976ada25a351ee603fa6a2c4aee99d56f0cabe $ git rev-list --merges --first-parent 703105c...97df5c4 97df5c4540534c57da2381b1675cd2461274b2a6 ``` Note: I've created this branch from 703105c so that I can merge `master` into it and test `bash-it update` once merged. --- lib/helpers.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 4cc2d574..b5172d02 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -182,7 +182,7 @@ _bash-it_update() { if [[ -n "${status}" ]]; then - for i in $(git rev-list --merges master..${BASH_IT_REMOTE}); do + for i in $(git rev-list --merges --first-parent master..${BASH_IT_REMOTE}); do num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l) if [ $num_of_lines -eq 1 ]; then description="%s" From f06439edc354d354eb3c2573008b8e7d206e8cde Mon Sep 17 00:00:00 2001 From: caguettaz Date: Tue, 4 Dec 2018 14:30:11 +0100 Subject: [PATCH 024/107] [cleanup] Harmonized variable names, added support for global config files --- bash_it.sh | 29 +++++++++++++---------------- lib/helpers.bash | 46 +++++++++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/bash_it.sh b/bash_it.sh index 82b7e1b9..1d34b407 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -29,31 +29,28 @@ cite _about _param _example _group _author _version # libraries, but skip appearance (themes) for now LIB="${BASH_IT}/lib/*.bash" APPEARANCE_LIB="${BASH_IT}/lib/appearance.bash" -for config_file in $LIB +for _bash_it_config_file in $LIB do - if [ "$config_file" != "$APPEARANCE_LIB" ]; then + if [ "$_bash_it_config_file" != "$APPEARANCE_LIB" ]; then # shellcheck disable=SC1090 - source "$config_file" + source "$_bash_it_config_file" fi done # Load the global "enabled" directory -_load_global_bash_it_files +# "family" param is empty so that files get sources in glob order +for _bash_it_config_file in $(_list_global_bash_it_files "") ; do + . "${BASH_IT}/$_bash_it_config_file" +done # Load enabled aliases, completion, plugins for file_type in "aliases" "plugins" "completion" do - _bash_it_list_bash_it_files_return=() - _list_bash_it_files $file_type - - for config_file in "${_bash_it_list_bash_it_files_return[@]}" ; do - . "$config_file" + for _bash_it_config_file in $(_list_bash_it_files "$file_type") ; do + . "${BASH_IT}/$_bash_it_config_file" done done -unset _bash_it_list_bash_it_files_return -unset _bash_it_config_file - # Load theme, if a theme was set if [[ ! -z "${BASH_IT_THEME}" ]]; then # Load colors and helpers first so they can be used in base theme @@ -83,15 +80,15 @@ done # Custom CUSTOM="${BASH_IT_CUSTOM:=${BASH_IT}/custom}/*.bash ${BASH_IT_CUSTOM:=${BASH_IT}/custom}/**/*.bash" -for config_file in $CUSTOM +for _bash_it_config_file in $CUSTOM do - if [ -e "${config_file}" ]; then + if [ -e "${_bash_it_config_file}" ]; then # shellcheck disable=SC1090 - source "$config_file" + source "$_bash_it_config_file" fi done -unset config_file +unset _bash_it_config_file if [[ $PROMPT ]]; then export PS1="\[""$PROMPT""\]" fi diff --git a/lib/helpers.bash b/lib/helpers.bash index 9c3e53f7..3474aece 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -17,42 +17,54 @@ function _command_exists () # Helper function listing various enable-able files to be sourced # The files need to be sourced in global scope to preserve scope of 'declare' function _list_bash_it_files() { - subdirectory="$1" - if [ -d "${BASH_IT}/${subdirectory}/enabled" ] + local subdirectory="$1" + pushd "${BASH_IT}" >/dev/null + + if [ -d "./${subdirectory}/enabled" ] then - FILES="${BASH_IT}/${subdirectory}/enabled/*.bash" + local FILES="./${subdirectory}/enabled/*.bash" + local _bash_it_config_file for _bash_it_config_file in $FILES do if [ -e "${_bash_it_config_file}" ]; then - _bash_it_list_bash_it_files_return+=("$_bash_it_config_file") + printf "$_bash_it_config_file\n" fi done fi + + popd >/dev/null } -function _load_global_bash_it_files() { +function _list_global_bash_it_files() { + local family="$1" + pushd "${BASH_IT}" >/dev/null + # In the new structure - if [ -d "${BASH_IT}/enabled" ] + if [ -d "./enabled" ] then - FILES="${BASH_IT}/enabled/*.bash" - for config_file in $FILES + local FILES="./enabled/*$family.bash" + local _bash_it_config_file + + for _bash_it_config_file in $FILES do - if [ -e "${config_file}" ]; then - source $config_file + if [ -e "${_bash_it_config_file}" ]; then + printf "$_bash_it_config_file\n" fi done fi } function _make_reload_alias() { - printf %s '\ - _bash_it_list_bash_it_files_return=() ;\ - _list_bash_it_files '"$1"' ;\ - for _bash_it_config_file in "${_bash_it_list_bash_it_files_return[@]}"; do \ - . "$_bash_it_config_file" ;\ - done ;\ - unset _bash_it_list_bash_it_files_return ;\ + printf %s ' + + for _bash_it_config_file in $(_list_global_bash_it_files '"$1"'); do \ + . "${BASH_IT}/$_bash_it_config_file" ; + done ; + + for _bash_it_config_file in $(_list_bash_it_files '"$1"'); do + . "${BASH_IT}/$_bash_it_config_file" ; + done ; unset _bash_it_config_file' } From 87d74c31d8c2ee09f05384993846ec1eccd56cec Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Tue, 4 Dec 2018 07:49:32 -0600 Subject: [PATCH 025/107] Tweak the language around force pushes --- CONTRIBUTING.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 04451473..e62b2c47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,9 +19,13 @@ Most of this is common sense, but please try to stick to the conventions listed Create a _Pull Request_ from your feature branch against Bash-it's _master_ branch. * Limit each Pull Request to one feature. Don't bundle multiple features/changes (e.g. a new _Theme_ and a fix to an existing plugin) into a single Pull Request - create one PR for the theme, and a separate PR for the fix. -* For complex changes, try to _squash_ your changes into a single commit. - Don't create a PR consisting of 20 commits that show your work in progress. - Before you create the PR, _squash_ your changes into a single commit. +* For complex changes, try to _squash_ your changes into a single commit before + pushing code. Once you've pushed your code and opened a PR, please refrain + from force-pushing changes to the PR branch – remember, bash-it is a + distributed project and your branch may be in use already. +* When in doubt, open a PR with too many commits. Bash-it is a learning project + for everyone involved. Showing your work provides a great history for folks + to learn what works and what didn't. ## Code Style From e198d8dc3da11ee5f3aed1ee1bcdf5390478f003 Mon Sep 17 00:00:00 2001 From: caguettaz Date: Tue, 4 Dec 2018 14:58:13 +0100 Subject: [PATCH 026/107] [bugfix] Fixed config family names for reload aliases --- lib/helpers.bash | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 3474aece..a6e4a6f1 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -56,26 +56,28 @@ function _list_global_bash_it_files() { } function _make_reload_alias() { - printf %s ' + local global_family="$1" + local subdirectory="$2" - for _bash_it_config_file in $(_list_global_bash_it_files '"$1"'); do \ + printf %s ' + for _bash_it_config_file in $(_list_global_bash_it_files '"$global_family"'); do \ . "${BASH_IT}/$_bash_it_config_file" ; done ; - for _bash_it_config_file in $(_list_bash_it_files '"$1"'); do + for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do . "${BASH_IT}/$_bash_it_config_file" ; done ; unset _bash_it_config_file' } # Alias for reloading aliases -alias reload_aliases="$(_make_reload_alias aliases)" +alias reload_aliases="$(_make_reload_alias alias aliases)" # Alias for reloading auto-completion -alias reload_completion="$(_make_reload_alias completion)" +alias reload_completion="$(_make_reload_alias completion completion)" # Alias for reloading plugins -alias reload_plugins="$(_make_reload_alias plugins)" +alias reload_plugins="$(_make_reload_alias plugin plugins)" bash-it () { From a1bbecc4a5d48b92346fb16b5c248b703576f06d Mon Sep 17 00:00:00 2001 From: caguettaz Date: Tue, 4 Dec 2018 15:58:21 +0100 Subject: [PATCH 027/107] [bugfix] Fixed reload aliases --- lib/helpers.bash | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index a6e4a6f1..38cc3ad8 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -53,6 +53,8 @@ function _list_global_bash_it_files() { fi done fi + + popd >/dev/null } function _make_reload_alias() { @@ -61,12 +63,13 @@ function _make_reload_alias() { printf %s ' for _bash_it_config_file in $(_list_global_bash_it_files '"$global_family"'); do \ - . "${BASH_IT}/$_bash_it_config_file" ; - done ; - - for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do - . "${BASH_IT}/$_bash_it_config_file" ; - done ; + . "${BASH_IT}/$_bash_it_config_file" ;\ + done ;\ + \ + for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do \ + . "${BASH_IT}/$_bash_it_config_file" ;\ + done ;\ + \ unset _bash_it_config_file' } From 13b6f3d870830aaeec8d2506d697484c1aaf446d Mon Sep 17 00:00:00 2001 From: caguettaz Date: Tue, 4 Dec 2018 16:31:03 +0100 Subject: [PATCH 028/107] [cleanup] Cleaned escaped newlines for alias reload --- lib/helpers.bash | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index 38cc3ad8..beba262a 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -62,14 +62,12 @@ function _make_reload_alias() { local subdirectory="$2" printf %s ' - for _bash_it_config_file in $(_list_global_bash_it_files '"$global_family"'); do \ - . "${BASH_IT}/$_bash_it_config_file" ;\ + for _bash_it_config_file in $(_list_global_bash_it_files '"$global_family"'); do + . "${BASH_IT}/$_bash_it_config_file" done ;\ - \ - for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do \ - . "${BASH_IT}/$_bash_it_config_file" ;\ + for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do + . "${BASH_IT}/$_bash_it_config_file" done ;\ - \ unset _bash_it_config_file' } From e5b68695c0e77403e9ceda6e2707c1be326da81b Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Tue, 4 Dec 2018 22:02:10 -0600 Subject: [PATCH 029/107] Attempt to simplify by not using aliases --- bash_it.sh | 8 ++------ lib/helpers.bash | 33 +-------------------------------- scripts/reloader.bash | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 38 deletions(-) create mode 100644 scripts/reloader.bash diff --git a/bash_it.sh b/bash_it.sh index 1d34b407..8d26bc55 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -39,16 +39,12 @@ done # Load the global "enabled" directory # "family" param is empty so that files get sources in glob order -for _bash_it_config_file in $(_list_global_bash_it_files "") ; do - . "${BASH_IT}/$_bash_it_config_file" -done +source "${BASH_IT}/scripts/reloader.bash" # Load enabled aliases, completion, plugins for file_type in "aliases" "plugins" "completion" do - for _bash_it_config_file in $(_list_bash_it_files "$file_type") ; do - . "${BASH_IT}/$_bash_it_config_file" - done + source "${BASH_IT}/scripts/reloader.bash" "false" "$file_type" done # Load theme, if a theme was set diff --git a/lib/helpers.bash b/lib/helpers.bash index beba262a..fb5d9cc7 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -36,39 +36,8 @@ function _list_bash_it_files() { popd >/dev/null } -function _list_global_bash_it_files() { - local family="$1" - pushd "${BASH_IT}" >/dev/null - - # In the new structure - if [ -d "./enabled" ] - then - local FILES="./enabled/*$family.bash" - local _bash_it_config_file - - for _bash_it_config_file in $FILES - do - if [ -e "${_bash_it_config_file}" ]; then - printf "$_bash_it_config_file\n" - fi - done - fi - - popd >/dev/null -} - function _make_reload_alias() { - local global_family="$1" - local subdirectory="$2" - - printf %s ' - for _bash_it_config_file in $(_list_global_bash_it_files '"$global_family"'); do - . "${BASH_IT}/$_bash_it_config_file" - done ;\ - for _bash_it_config_file in $(_list_bash_it_files '"$subdirectory"'); do - . "${BASH_IT}/$_bash_it_config_file" - done ;\ - unset _bash_it_config_file' + echo "source \${BASH_IT}/scripts/reloader.bash ${1} ${2}" } # Alias for reloading aliases diff --git a/scripts/reloader.bash b/scripts/reloader.bash new file mode 100644 index 00000000..b208a98c --- /dev/null +++ b/scripts/reloader.bash @@ -0,0 +1,30 @@ +#!/bin/bash +pushd "${BASH_IT}" >/dev/null + +# TODO: Add debugging output + +if [ "$1" != "false" ] && [ -d "./enabled" ]; then + for _bash_it_config_file in $(ls ./enabled/*${1}.bash 2>/dev/null); do + if [ -e "${_bash_it_config_file}" ]; then + source $_bash_it_config_file + else + echo "Unable to read ${_bash_it_config_file}" > /dev/stderr + fi + done +fi + + +if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then + # TODO: We should warn users they're using legacy enabling + for _bash_it_config_file in $(ls ./${2}/enabled/*.bash 2>/dev/null); do + if [ -e "$_bash_it_config_file" ]; then + source "$_bash_it_config_file" + else + # TODO Display an error? + echo "Unable to locate ${_bash_it_config_file}" > /dev/null + fi + done +fi + +unset _bash_it_config_file +popd >/dev/null From 3a7889e05b84dcb3686e57ff2f993de484990490 Mon Sep 17 00:00:00 2001 From: Nils Winkler Date: Wed, 5 Dec 2018 08:37:13 +0100 Subject: [PATCH 030/107] Update CONTRIBUTING.md Fixed capitalization of Bash-it. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e62b2c47..8c251c6c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ Most of this is common sense, but please try to stick to the conventions listed Don't bundle multiple features/changes (e.g. a new _Theme_ and a fix to an existing plugin) into a single Pull Request - create one PR for the theme, and a separate PR for the fix. * For complex changes, try to _squash_ your changes into a single commit before pushing code. Once you've pushed your code and opened a PR, please refrain - from force-pushing changes to the PR branch – remember, bash-it is a + from force-pushing changes to the PR branch – remember, Bash-it is a distributed project and your branch may be in use already. * When in doubt, open a PR with too many commits. Bash-it is a learning project for everyone involved. Showing your work provides a great history for folks From 286e69591046d4a0395ebbf239e6c5aeb2c49500 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 20:59:37 -0600 Subject: [PATCH 031/107] Ensure that shellcheck can find these files (SC1090) --- bash_it.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bash_it.sh b/bash_it.sh index 8d26bc55..1b092cc9 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -39,11 +39,13 @@ done # Load the global "enabled" directory # "family" param is empty so that files get sources in glob order +# shellcheck source=./scripts/reloader.bash source "${BASH_IT}/scripts/reloader.bash" # Load enabled aliases, completion, plugins for file_type in "aliases" "plugins" "completion" do + # shellcheck source=./scripts/reloader.bash source "${BASH_IT}/scripts/reloader.bash" "false" "$file_type" done From 61380e686f33482a42776202dbef67b768393e19 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:00:01 -0600 Subject: [PATCH 032/107] Remove unused function --- lib/helpers.bash | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index fb5d9cc7..ed229b3a 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -14,28 +14,6 @@ function _command_exists () type "$1" &> /dev/null ; } -# Helper function listing various enable-able files to be sourced -# The files need to be sourced in global scope to preserve scope of 'declare' -function _list_bash_it_files() { - local subdirectory="$1" - pushd "${BASH_IT}" >/dev/null - - if [ -d "./${subdirectory}/enabled" ] - then - local FILES="./${subdirectory}/enabled/*.bash" - local _bash_it_config_file - - for _bash_it_config_file in $FILES - do - if [ -e "${_bash_it_config_file}" ]; then - printf "$_bash_it_config_file\n" - fi - done - fi - - popd >/dev/null -} - function _make_reload_alias() { echo "source \${BASH_IT}/scripts/reloader.bash ${1} ${2}" } From 0793eb41a716ccb42ec0b23287394715a2430375 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:00:41 -0600 Subject: [PATCH 033/107] =?UTF-8?q?Ignore=20SC2139=20=E2=80=93=20it's=20ok?= =?UTF-8?q?=20that=20these=20are=20expanded=20when=20evaluated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/helpers.bash | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/helpers.bash b/lib/helpers.bash index ed229b3a..d71120b8 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -19,12 +19,15 @@ function _make_reload_alias() { } # Alias for reloading aliases +# shellcheck disable=SC2139 alias reload_aliases="$(_make_reload_alias alias aliases)" # Alias for reloading auto-completion +# shellcheck disable=SC2139 alias reload_completion="$(_make_reload_alias completion completion)" # Alias for reloading plugins +# shellcheck disable=SC2139 alias reload_plugins="$(_make_reload_alias plugin plugins)" bash-it () From 992b87b816c57e6ac2ea195d18cb1ba6888b5552 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:00:59 -0600 Subject: [PATCH 034/107] Shellcheck clean up based on comments from @nwinkler --- scripts/reloader.bash | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/reloader.bash b/scripts/reloader.bash index b208a98c..cac77a21 100644 --- a/scripts/reloader.bash +++ b/scripts/reloader.bash @@ -1,11 +1,12 @@ #!/bin/bash -pushd "${BASH_IT}" >/dev/null +pushd "${BASH_IT}" >/dev/null || exit 1 # TODO: Add debugging output if [ "$1" != "false" ] && [ -d "./enabled" ]; then - for _bash_it_config_file in $(ls ./enabled/*${1}.bash 2>/dev/null); do + for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${1}.bash")); do if [ -e "${_bash_it_config_file}" ]; then + # shellcheck source=/dev/null source $_bash_it_config_file else echo "Unable to read ${_bash_it_config_file}" > /dev/stderr @@ -16,8 +17,9 @@ fi if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then # TODO: We should warn users they're using legacy enabling - for _bash_it_config_file in $(ls ./${2}/enabled/*.bash 2>/dev/null); do + for _bash_it_config_file in $(sort <(compgen -G "./${2}/enabled/*.bash")); do if [ -e "$_bash_it_config_file" ]; then + # shellcheck source=/dev/null source "$_bash_it_config_file" else # TODO Display an error? @@ -27,4 +29,4 @@ if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then fi unset _bash_it_config_file -popd >/dev/null +popd >/dev/null || exit 1 From c76263dc47b008600602228c374d7ccb90e8cacd Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:04:55 -0600 Subject: [PATCH 035/107] Ensure this debugging output is generated (oops) --- scripts/reloader.bash | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/reloader.bash b/scripts/reloader.bash index cac77a21..66236042 100644 --- a/scripts/reloader.bash +++ b/scripts/reloader.bash @@ -22,8 +22,7 @@ if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then # shellcheck source=/dev/null source "$_bash_it_config_file" else - # TODO Display an error? - echo "Unable to locate ${_bash_it_config_file}" > /dev/null + echo "Unable to locate ${_bash_it_config_file}" > /dev/stderr fi done fi From 5b8f8d874e21feb8323e6fc1c919edcafc2a8468 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:53:39 -0600 Subject: [PATCH 036/107] Default to loading everything The tests are failing because $1 is being passed through from the initial loading. When this loads in the shell, $1 is empty though so the code works-for-me, but just not the tests. This filters the $1 input to ensure its one of the valid types expected inside the ./enabled directory. --- scripts/reloader.bash | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/reloader.bash b/scripts/reloader.bash index 66236042..e5cf178f 100644 --- a/scripts/reloader.bash +++ b/scripts/reloader.bash @@ -4,7 +4,11 @@ pushd "${BASH_IT}" >/dev/null || exit 1 # TODO: Add debugging output if [ "$1" != "false" ] && [ -d "./enabled" ]; then - for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${1}.bash")); do + _bash_it_config_type="" + if [[ "${1}" =~ ^(alias|completion|plugin)$ ]]; then + _bash_it_config_type=$1 + fi + for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${_bash_it_config_type}.bash")); do if [ -e "${_bash_it_config_file}" ]; then # shellcheck source=/dev/null source $_bash_it_config_file @@ -28,4 +32,5 @@ if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then fi unset _bash_it_config_file +unset _bash_it_config_type popd >/dev/null || exit 1 From 7b32dd64241599200a67c38ba1241d926c555be7 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:54:59 -0600 Subject: [PATCH 037/107] Add filtering to the $2 input in addition to $1 --- scripts/reloader.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/reloader.bash b/scripts/reloader.bash index e5cf178f..c26d3626 100644 --- a/scripts/reloader.bash +++ b/scripts/reloader.bash @@ -19,7 +19,7 @@ if [ "$1" != "false" ] && [ -d "./enabled" ]; then fi -if [ ! -z "${2}" ] && [ -d "${2}/enabled" ]; then +if [ ! -z "${2}" ] && [[ "${2}" =~ ^(aliases|completion|plugins)$ ]] && [ -d "${2}/enabled" ]; then # TODO: We should warn users they're using legacy enabling for _bash_it_config_file in $(sort <(compgen -G "./${2}/enabled/*.bash")); do if [ -e "$_bash_it_config_file" ]; then From 2d6085b033be1af89526a6c46c47d0dfc853051f Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Wed, 5 Dec 2018 21:58:13 -0600 Subject: [PATCH 038/107] =?UTF-8?q?Switch=20from=20false=20to=20skip=20?= =?UTF-8?q?=E2=80=93=20I=20think=20that's=20more=20clear?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bash_it.sh | 2 +- scripts/reloader.bash | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bash_it.sh b/bash_it.sh index 1b092cc9..ab911019 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -46,7 +46,7 @@ source "${BASH_IT}/scripts/reloader.bash" for file_type in "aliases" "plugins" "completion" do # shellcheck source=./scripts/reloader.bash - source "${BASH_IT}/scripts/reloader.bash" "false" "$file_type" + source "${BASH_IT}/scripts/reloader.bash" "skip" "$file_type" done # Load theme, if a theme was set diff --git a/scripts/reloader.bash b/scripts/reloader.bash index c26d3626..b0fe7e41 100644 --- a/scripts/reloader.bash +++ b/scripts/reloader.bash @@ -3,7 +3,7 @@ pushd "${BASH_IT}" >/dev/null || exit 1 # TODO: Add debugging output -if [ "$1" != "false" ] && [ -d "./enabled" ]; then +if [ "$1" != "skip" ] && [ -d "./enabled" ]; then _bash_it_config_type="" if [[ "${1}" =~ ^(alias|completion|plugin)$ ]]; then _bash_it_config_type=$1 From 3645305644ff62f217c3a68713adba3dcddd3e45 Mon Sep 17 00:00:00 2001 From: cornfeedhobo Date: Thu, 6 Dec 2018 17:07:03 -0500 Subject: [PATCH 039/107] add go plugin tests and update list reversal logic --- plugins/available/go.plugin.bash | 11 ++++++++-- test/plugins/go.plugin.bats | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/plugins/go.plugin.bats diff --git a/plugins/available/go.plugin.bash b/plugins/available/go.plugin.bash index 819ebc3a..910194e5 100755 --- a/plugins/available/go.plugin.bash +++ b/plugins/available/go.plugin.bash @@ -6,9 +6,16 @@ about-plugin 'go environment variables & path configuration' [ ! command -v go &>/dev/null ] && return function _split_path_reverse() { + local a=( ${@//:/ } ) + local i=${#a[@]} local r= - for p in ${@//:/ } ; do - r="$p $r" + while [ $i -gt 0 ] ; do + i=$(( i - 1 )) + if [ $(( i + 1 )) -eq ${#a[@]} ] ; then + r="${a[i]}" + else + r="${r} ${a[i]}" + fi done echo "$r" } diff --git a/test/plugins/go.plugin.bats b/test/plugins/go.plugin.bats new file mode 100644 index 00000000..0cc257ed --- /dev/null +++ b/test/plugins/go.plugin.bats @@ -0,0 +1,37 @@ +#!/usr/bin/env bats + +#load ../test_helper +load ../../lib/helpers +load ../../lib/composure +load ../../plugins/available/go.plugin + +@test 'plugins go: reverse path: single entry' { + run _split_path_reverse '/foo' + echo "output = ${output}" + [ "$output" = "/foo" ] +} + +@test 'plugins go: reverse path: single entry, colon empty' { + run _split_path_reverse '/foo:' + echo "output = ${output}" + [ "$output" = "/foo" ] +} + +@test 'plugins go: reverse path: single entry, colon whitespace' { + run _split_path_reverse '/foo: ' + echo "output = ${output}" + [ "$output" = "/foo" ] +} + +@test 'plugins go: reverse path: multiple entries' { + run _split_path_reverse '/foo:/bar' + echo "output = ${output}" + [ "$output" = "/bar /foo" ] +} + +@test 'plugins go: multiple entries in GOPATH' { + export GOPATH="/foo:/bar" + load ../../plugins/available/go.plugin + echo "$(echo $PATH | cut -d':' -f1,2)" + [ "$(echo $PATH | cut -d':' -f1,2)" = "/foo/bin:/bar/bin" ] +} From 1030c0e9e1ccaddbeb21c9b12b60649921f64e61 Mon Sep 17 00:00:00 2001 From: cornfeedhobo Date: Thu, 6 Dec 2018 17:11:13 -0500 Subject: [PATCH 040/107] one more test ... why not --- test/plugins/go.plugin.bats | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/plugins/go.plugin.bats b/test/plugins/go.plugin.bats index 0cc257ed..e2b27e02 100644 --- a/test/plugins/go.plugin.bats +++ b/test/plugins/go.plugin.bats @@ -29,6 +29,13 @@ load ../../plugins/available/go.plugin [ "$output" = "/bar /foo" ] } +@test 'plugins go: single entry in GOPATH' { + export GOPATH="/foo" + load ../../plugins/available/go.plugin + echo "$(echo $PATH | cut -d':' -f1,2)" + [ "$(echo $PATH | cut -d':' -f1)" = "/foo/bin" ] +} + @test 'plugins go: multiple entries in GOPATH' { export GOPATH="/foo:/bar" load ../../plugins/available/go.plugin From 7136604b57edfc3f9fb3c77f9262ebca47a7bb03 Mon Sep 17 00:00:00 2001 From: con-f-use Date: Mon, 10 Dec 2018 15:03:10 +0100 Subject: [PATCH 041/107] Fix dependency of docker aliases on docker plugin Some of the docker aliases use functions found in the docker plugin. If the plugin is not enabled, these aliases do not work. This commit only defines the aliases if the plugin is enabled. Also changed: `dkelc` now creates an explicit login shell, has the synonym `dkbash` and uses no backticks. Reason: on some docker images the status as login-shell is not set automatically, which causes e.g. `/etc/bash.bashrc` and `/etc/profile` not to be loaded in these images. Note: There should be a convenience function in `lib/helpers.bash` that checks if a plugin is available/enabled/disabled. The if-statement if rather clonky. --- aliases/available/docker.aliases.bash | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/aliases/available/docker.aliases.bash b/aliases/available/docker.aliases.bash index 5606b619..59322b39 100644 --- a/aliases/available/docker.aliases.bash +++ b/aliases/available/docker.aliases.bash @@ -9,7 +9,6 @@ alias dkps='docker ps' # List running Docker containers alias dkpsa='docker ps -a' # List all Docker containers alias dki='docker images' # List Docker images alias dkrmac='docker rm $(docker ps -a -q)' # Delete all Docker containers -alias dkrmlc='docker-remove-most-recent-container' # Delete most recent (i.e., last) Docker container case $OSTYPE in darwin*|*bsd*|*BSD*) @@ -20,12 +19,17 @@ case $OSTYPE in ;; esac -alias dkrmall='docker-remove-stale-assets' # Delete all untagged images and exited containers -alias dkrmli='docker-remove-most-recent-image' # Delete most recent (i.e., last) Docker image -alias dkrmi='docker-remove-images' # Delete images for supplied IDs or all if no IDs are passed as arguments -alias dkideps='docker-image-dependencies' # Output a graph of image dependencies using Graphiz -alias dkre='docker-runtime-environment' # List environmental variables of the supplied image ID -alias dkelc='docker exec -it `dklcid` bash' # Enter last container (works with Docker 1.3 and above) +if [ ! -z "$(command ls "${BASH_IT}/$subdirectory/"{[0-9][0-9][0-9]${BASH_IT_LOAD_PRIORITY_SEPARATOR}docker,docker}.plugin.bash 2>/dev/null | head -1)" ]; then +# Function aliases from docker plugin: + alias dkrmlc='docker-remove-most-recent-container' # Delete most recent (i.e., last) Docker container + alias dkrmall='docker-remove-stale-assets' # Delete all untagged images and exited containers + alias dkrmli='docker-remove-most-recent-image' # Delete most recent (i.e., last) Docker image + alias dkrmi='docker-remove-images' # Delete images for supplied IDs or all if no IDs are passed as arguments + alias dkideps='docker-image-dependencies' # Output a graph of image dependencies using Graphiz + alias dkre='docker-runtime-environment' # List environmental variables of the supplied image ID +fi +alias dkelc='docker exec -it $(dklcid) bash --login' # Enter last container (works with Docker 1.3 and above) +alias dkbash='dkelc' alias dkex='docker exec -it ' # Useful to run any commands into container without leaving host alias dkri='docker run --rm -i ' alias dkrit='docker run --rm -it ' From 60b3572f7c4ce08a37dcfc27703f6c4b0aab9457 Mon Sep 17 00:00:00 2001 From: con-f-use Date: Tue, 11 Dec 2018 21:10:52 +0100 Subject: [PATCH 042/107] Purge `$subdirectory` leftover in docker aliases --- aliases/available/docker.aliases.bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aliases/available/docker.aliases.bash b/aliases/available/docker.aliases.bash index 59322b39..52ccc4c6 100644 --- a/aliases/available/docker.aliases.bash +++ b/aliases/available/docker.aliases.bash @@ -19,7 +19,7 @@ case $OSTYPE in ;; esac -if [ ! -z "$(command ls "${BASH_IT}/$subdirectory/"{[0-9][0-9][0-9]${BASH_IT_LOAD_PRIORITY_SEPARATOR}docker,docker}.plugin.bash 2>/dev/null | head -1)" ]; then +if [ ! -z "$(command ls "${BASH_IT}/enabled/"{[0-9][0-9][0-9]${BASH_IT_LOAD_PRIORITY_SEPARATOR}docker,docker}.plugin.bash 2>/dev/null | head -1)" ]; then # Function aliases from docker plugin: alias dkrmlc='docker-remove-most-recent-container' # Delete most recent (i.e., last) Docker container alias dkrmall='docker-remove-stale-assets' # Delete all untagged images and exited containers @@ -29,6 +29,7 @@ if [ ! -z "$(command ls "${BASH_IT}/$subdirectory/"{[0-9][0-9][0-9]${BASH_IT_LOA alias dkre='docker-runtime-environment' # List environmental variables of the supplied image ID fi alias dkelc='docker exec -it $(dklcid) bash --login' # Enter last container (works with Docker 1.3 and above) +alias dkrmflast='docker rm -f $(dklcid)' alias dkbash='dkelc' alias dkex='docker exec -it ' # Useful to run any commands into container without leaving host alias dkri='docker run --rm -i ' From ca5c512a35b79676f4478251445650fc6fdac3a0 Mon Sep 17 00:00:00 2001 From: Nils Winkler Date: Tue, 18 Dec 2018 09:26:25 +0100 Subject: [PATCH 043/107] Removed 'local' keyword --- plugins/available/percol.plugin.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/available/percol.plugin.bash b/plugins/available/percol.plugin.bash index 27b98708..66610662 100644 --- a/plugins/available/percol.plugin.bash +++ b/plugins/available/percol.plugin.bash @@ -27,7 +27,7 @@ _replace_by_history() { if command -v percol>/dev/null; then - local current_version=${BASH_VERSION%%[^0-9]*} + current_version=${BASH_VERSION%%[^0-9]*} if [ $current_version -lt 4 ]; then echo -e "\033[91mWarning: You have to upgrade Bash to Bash v4.x to use the 'percol' plugin.\033[m" echo -e "\033[91m Your current Bash version is $BASH_VERSION.\033[m" From 2bc990269ab503268f8e8cff9781b96d0e0bf077 Mon Sep 17 00:00:00 2001 From: Li Zou Date: Sat, 22 Dec 2018 15:25:08 -0800 Subject: [PATCH 044/107] Add alias for listing untracked files --- aliases/available/git.aliases.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index 169fe7b8..75b7997a 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -77,6 +77,8 @@ alias gcsam="git commit -S -am" alias gstd="git stash drop" alias gstl="git stash list" alias gh='cd "$(git rev-parse --show-toplevel)"' +# Show untracked files +alias gu='git ls-files . --exclude-standard --others' case $OSTYPE in darwin*) From 7b41736d1747939cb9978d3537744f578cab0651 Mon Sep 17 00:00:00 2001 From: Dan Beste Date: Sun, 22 Jul 2018 16:44:06 -0500 Subject: [PATCH 045/107] New theme: essential A simple, console-compatible Bash-it theme. Features: * Reactive coloring for: * Privileged and standard users. * Local and remote hosts. * Exit status for prompt strings 1 and 2. * Console-compatible! * No unicode "tofu" in console sessions. * Matching alignment for prompt strings 1 and 2. Preview: $PS1| $TIME $USER@$HOST:$PWD $PS1| + function foo() { $PS2| | bar $PS2| | baz $PS2| | } --- themes/essential/essential.theme.bash | 96 +++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 themes/essential/essential.theme.bash diff --git a/themes/essential/essential.theme.bash b/themes/essential/essential.theme.bash new file mode 100644 index 00000000..c0b1a38e --- /dev/null +++ b/themes/essential/essential.theme.bash @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# https://github.com/koalaman/shellcheck/wiki/Sc2154 +# shellcheck disable=SC2154 + +function _user-prompt() { + local -r user='\\u' + + if [[ "${EUID}" -eq 0 ]]; then + # Privileged users: + local -r user_color="${bold_red}" + else + # Standard users: + local -r user_color="${bold_green}" + fi + + # Print the current user's name (colored according to their current EUID): + echo -e "${user_color}${user}${normal}" +} + +function _host-prompt() { + local -r host='\\h' + + # Check whether or not $SSH_TTY is set: + if [[ -z "${SSH_TTY}" ]]; then + # For local hosts, set the host's prompt color to blue: + local -r host_color="${bold_blue}" + else + # For remote hosts, set the host's prompt color to red: + local -r host_color="${bold_red}" + fi + + # Print the current hostname (colored according to $SSH_TTY's status): + echo -e "${host_color}${host}${normal}" +} + +function _user-at-host-prompt() { + # Concatenate the user and host prompts into: user@host: + echo -e "$(_user-prompt)${bold_white}@$(_host-prompt)" +} + +function _exit-status-prompt() { + local -r prompt_string="${1}" + local -r exit_status="${2}" + + # Check the exit status of the last command captured by $exit_status: + if [[ "${exit_status}" -eq 0 ]]; then + # For commands that return an exit status of zero, set the exit status's + # notifier to green: + local -r exit_status_color="${bold_green}" + else + # For commands that return a non-zero exit status, set the exit status's + # notifier to red: + local -r exit_status_color="${bold_red}" + fi + + echo -ne "${exit_status_color}" + if [[ "${prompt_string}" -eq 1 ]]; then + # $PS1: + echo -e " +${normal} " + elif [[ "${prompt_string}" -eq 2 ]]; then + # $PS2: + echo -e " |${normal} " + else + # Default: + echo -e " ?${normal} " + fi +} + +function _ps1() { + local -r time='\\t' + + echo -ne "${bold_white}${time} " + echo -ne "$(_user-at-host-prompt)" + echo -e "${bold_white}:${normal}${PWD}" + echo -e "$(_exit-status-prompt 1 "${exit_status}")" +} + +function _ps2() { + echo -e "$(_exit-status-prompt 2 "${exit_status}")" +} + +function prompt_command() { + # Capture the exit status of the last command: + local -r exit_status="${?}" + + # Build the $PS1 prompt: + PS1="$(_ps1)" + + # Build the $PS2 prompt: + PS2="$(_ps2)" +} + +safe_append_prompt_command prompt_command + +# vim: sw=2 ts=2 et: From 0fe631ea7cda5b2c1e5ad73e2a83a0770a57e1bf Mon Sep 17 00:00:00 2001 From: Claudia Date: Wed, 2 Jan 2019 17:45:43 +0100 Subject: [PATCH 046/107] Make `bash-it reload` preserve working directory In e5b6869 (part of #1283), a regression was introduced, which caused `bash-it reload` to return with the working directory set to `.bash_it` and the original working directory discarded. The root cause is the function wrapper of `bash-it reload`, which has always relied on the working directory not to change during execution of the wrapped code. This assumption no longer holds with the changes introduced in #1283. This commit fixes the regression by using `pushd`/`popd` in `bash-it reload`. --- lib/helpers.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/helpers.bash b/lib/helpers.bash index e632b80b..4d11e657 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -256,7 +256,7 @@ _bash-it-reload() { _about 'reloads a profile file' _group 'lib' - cd "${BASH_IT}" || return + pushd "${BASH_IT}" &> /dev/null || return case $OSTYPE in darwin*) @@ -267,7 +267,7 @@ _bash-it-reload() { ;; esac - cd - &> /dev/null || return + popd &> /dev/null || return } _bash-it-describe () From fe8f5e42d09abd78051df82829227b37996135e7 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Mon, 7 Jan 2019 01:10:21 +0530 Subject: [PATCH 047/107] added wpscan completions --- completion/available/wpscan.completion.bash | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 completion/available/wpscan.completion.bash diff --git a/completion/available/wpscan.completion.bash b/completion/available/wpscan.completion.bash new file mode 100644 index 00000000..ec517aec --- /dev/null +++ b/completion/available/wpscan.completion.bash @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +if command -v wpscan > /dev/null; then + __wpscan_completion() { + local OPTS=("--help --hh --version --ignore-main-redirect --verbose --output --format --detection-mode --scope --headers --user-agent --vhost --random-user-agent --user-agents-list --http-auth --max-threads --throttle --request-timeout --connect-timeout --disable-tlc-checks --proxy --proxy-auth --cookie-string --cookie-jar --cache-ttl --clear-cache --server --cache-dir --update --no-update --wp-content-dir --wp-plugins-dir --wp-version-detection --main-theme-detection --enumrate --exclude-content-based --plugins-list --plugins-detection --plugins-version-all --plugins-version-detection --themes-list --themes-detection --themes-version-all --themes-version-detection --timthumbs-list --timthumbs-detection --config-backups-list --config-backups-detection --db-exports-list --db-exports-detection --medias-detection --users-list --users-detection --passwords --usernames --multicall-max-passwords --password-attack --stealthy") + COMPREPLY=() + for _opt_ in ${OPTS[@]}; do + if [[ "$_opt_" == "$2"* ]]; then + COMPREPLY+=("$_opt_") + fi + done + } + + complete -F __wpscan_completion wpscan +fi + From 508f82eb95d8aa3d04f3bf722af244cf97ae0379 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Mon, 7 Jan 2019 01:18:37 +0530 Subject: [PATCH 048/107] added vuejs completions --- completion/available/vuejs.completion.bash | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 completion/available/vuejs.completion.bash diff --git a/completion/available/vuejs.completion.bash b/completion/available/vuejs.completion.bash new file mode 100644 index 00000000..2959f29b --- /dev/null +++ b/completion/available/vuejs.completion.bash @@ -0,0 +1,15 @@ +#!/usr/bin/bash + +if command -v vue > /dev/null; then + __vuejs_completion() { + local OPTS=("--version --help create add invoke inspect serve build ui init config upgrade info") + COMPREPLY=() + for _opt_ in ${OPTS[@]}; do + if [[ "$_opt_" == "$2"* ]]; then + COMPREPLY+=("$_opt_") + fi + done + } + + complete -F __vuejs_completion vue +fi From a636f602c84985528e4b02e326adb32e26645a9b Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Mon, 7 Jan 2019 01:23:00 +0530 Subject: [PATCH 049/107] added main option --- completion/available/wpscan.completion.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completion/available/wpscan.completion.bash b/completion/available/wpscan.completion.bash index ec517aec..9f21a0d8 100644 --- a/completion/available/wpscan.completion.bash +++ b/completion/available/wpscan.completion.bash @@ -2,7 +2,7 @@ if command -v wpscan > /dev/null; then __wpscan_completion() { - local OPTS=("--help --hh --version --ignore-main-redirect --verbose --output --format --detection-mode --scope --headers --user-agent --vhost --random-user-agent --user-agents-list --http-auth --max-threads --throttle --request-timeout --connect-timeout --disable-tlc-checks --proxy --proxy-auth --cookie-string --cookie-jar --cache-ttl --clear-cache --server --cache-dir --update --no-update --wp-content-dir --wp-plugins-dir --wp-version-detection --main-theme-detection --enumrate --exclude-content-based --plugins-list --plugins-detection --plugins-version-all --plugins-version-detection --themes-list --themes-detection --themes-version-all --themes-version-detection --timthumbs-list --timthumbs-detection --config-backups-list --config-backups-detection --db-exports-list --db-exports-detection --medias-detection --users-list --users-detection --passwords --usernames --multicall-max-passwords --password-attack --stealthy") + local OPTS=("--help --hh --version --url --ignore-main-redirect --verbose --output --format --detection-mode --scope --headers --user-agent --vhost --random-user-agent --user-agents-list --http-auth --max-threads --throttle --request-timeout --connect-timeout --disable-tlc-checks --proxy --proxy-auth --cookie-string --cookie-jar --cache-ttl --clear-cache --server --cache-dir --update --no-update --wp-content-dir --wp-plugins-dir --wp-version-detection --main-theme-detection --enumrate --exclude-content-based --plugins-list --plugins-detection --plugins-version-all --plugins-version-detection --themes-list --themes-detection --themes-version-all --themes-version-detection --timthumbs-list --timthumbs-detection --config-backups-list --config-backups-detection --db-exports-list --db-exports-detection --medias-detection --users-list --users-detection --passwords --usernames --multicall-max-passwords --password-attack --stealthy") COMPREPLY=() for _opt_ in ${OPTS[@]}; do if [[ "$_opt_" == "$2"* ]]; then From ec088d4271de855e0c173f9df5b3623c38f3b26b Mon Sep 17 00:00:00 2001 From: LanikSJ Date: Tue, 8 Jan 2019 14:01:54 -0800 Subject: [PATCH 050/107] Remove Deprecated Brew Command --- aliases/available/homebrew.aliases.bash | 1 - 1 file changed, 1 deletion(-) diff --git a/aliases/available/homebrew.aliases.bash b/aliases/available/homebrew.aliases.bash index 239d884b..15907518 100644 --- a/aliases/available/homebrew.aliases.bash +++ b/aliases/available/homebrew.aliases.bash @@ -4,7 +4,6 @@ cite 'about-alias' about-alias 'homebrew abbreviations' alias bup='brew update && brew upgrade' -alias bupc='brew update && brew upgrade --cleanup' alias bout='brew outdated' alias bin='brew install' alias brm='brew uninstall' From 56945e3bdfe2b8d00db7ec86dfbbc53388790874 Mon Sep 17 00:00:00 2001 From: Kyle Welsby Date: Wed, 16 Jan 2019 17:15:23 +0000 Subject: [PATCH 051/107] Fixes #1309 _bash-it-clean-component-cache: command not found Silence errors when installing ``` Would you like to enable the ag aliases? [y/N] y ~/.bash_it/lib/helpers.bash: line 488: _bash-it-clean-component-cache: command not found ag enabled with priority 150. ``` --- install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install.sh b/install.sh index c0848cdb..8250c3df 100755 --- a/install.sh +++ b/install.sh @@ -155,6 +155,7 @@ fi # Load dependencies for enabling components source "$BASH_IT/lib/composure.bash" +source "$BASH_IT/lib/utilities.bash" cite _about _param _example _group _author _version source "$BASH_IT/lib/helpers.bash" From fedb72b34f148e9b3dd2c3aa3164c4d58feed2ef Mon Sep 17 00:00:00 2001 From: Kyle Welsby Date: Wed, 16 Jan 2019 17:35:44 +0000 Subject: [PATCH 052/107] Fixes exit 1 issue when tmp cache doesn't exist Found if this `${cache}` file doesn't exist, the single line conditional command would return false causing a `exit 1`. This little change makes the conditional verbose and not cause a false return failing the function. --- lib/utilities.bash | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/utilities.bash b/lib/utilities.bash index 93e96606..d7cf6f3f 100644 --- a/lib/utilities.bash +++ b/lib/utilities.bash @@ -44,7 +44,9 @@ _bash-it-clean-component-cache() { done else cache="$(_bash-it-component-cache-file ${component})" - [[ -f "${cache}" ]] && rm -f "${cache}" + if [[ -f "${cache}" ]] ; then + rm -f "${cache}" + fi fi } From ca58587217661357663967667ff8b2a57df0671a Mon Sep 17 00:00:00 2001 From: Kyle Welsby Date: Wed, 16 Jan 2019 18:16:08 +0000 Subject: [PATCH 053/107] Fixes #1203 convert alias to aliases A ungraceful patch but fixes this one case where the command is singular `alias` while the file are plural with `aliases. --- lib/helpers.bash | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/helpers.bash b/lib/helpers.bash index 7e9ff2ab..3a47cd4a 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -452,6 +452,9 @@ _enable-thing () for f in "${BASH_IT}/$subdirectory/available/"*.bash do to_enable=$(basename $f .$file_type.bash) + if [ "$file_type" = "alias" ]; then + to_enable=$(basename $f ".aliases.bash") + fi _enable-thing $subdirectory $file_type $to_enable $load_priority done else From af1bf11748c16fa6bdff83cf1f20ba76caa62181 Mon Sep 17 00:00:00 2001 From: Kaiming Guo Date: Tue, 22 Jan 2019 14:38:58 +0800 Subject: [PATCH 054/107] add MSYS2 aliases Ignore NTUSER.DAT files in Git/MSYS2 Bash. --- aliases/available/msys2.aliases.bash | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 aliases/available/msys2.aliases.bash diff --git a/aliases/available/msys2.aliases.bash b/aliases/available/msys2.aliases.bash new file mode 100644 index 00000000..83b14a13 --- /dev/null +++ b/aliases/available/msys2.aliases.bash @@ -0,0 +1,16 @@ +#!/bin/bash + +cite 'about-alias' +about-alias 'MSYS2 aliases' + +LS_COMMON="-hG" +LS_COMMON="$LS_COMMON --color=auto" +LS_COMMON="$LS_COMMON -I NTUSER.DAT\* -I ntuser.dat\*" + +test -n "$LS_COMMON" && + +# alias +alias ls="command ls $LS_COMMON" +alias ll="ls -l" +alias la="ls -a" +alias lal="ll -a" From 212eb6636eb659b5390a987675c0604d11f60a6d Mon Sep 17 00:00:00 2001 From: Kai-Ming Guo Date: Tue, 22 Jan 2019 17:19:35 +0800 Subject: [PATCH 055/107] complete condition command `test` command to check `$LS_COMMON` argument exists. and merged the next line. --- aliases/available/msys2.aliases.bash | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aliases/available/msys2.aliases.bash b/aliases/available/msys2.aliases.bash index 83b14a13..a309a5b2 100644 --- a/aliases/available/msys2.aliases.bash +++ b/aliases/available/msys2.aliases.bash @@ -7,10 +7,9 @@ LS_COMMON="-hG" LS_COMMON="$LS_COMMON --color=auto" LS_COMMON="$LS_COMMON -I NTUSER.DAT\* -I ntuser.dat\*" -test -n "$LS_COMMON" && - # alias -alias ls="command ls $LS_COMMON" +# setup the main ls alias if we've established common args +test -n "$LS_COMMON" && alias ls="command ls $LS_COMMON" alias ll="ls -l" alias la="ls -a" alias lal="ll -a" From 34487076ba506437c97ecf796c4560dfda810d37 Mon Sep 17 00:00:00 2001 From: NiilShon <51centimos@gmail.com> Date: Wed, 23 Jan 2019 00:29:11 +0100 Subject: [PATCH 056/107] Update general.aliases.bash --- aliases/available/general.aliases.bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aliases/available/general.aliases.bash b/aliases/available/general.aliases.bash index c3455525..542b76cd 100644 --- a/aliases/available/general.aliases.bash +++ b/aliases/available/general.aliases.bash @@ -99,8 +99,9 @@ alias bshenc="bash-it enable completion" # Shorten extract alias xt="extract" -# sudo vim +# sudo editors alias svim="sudo vim" +alias snano="sudo nano" # Display whatever file is regular file or folder catt() { From cb74bd63b9158072a7b59c223ee284918586a02b Mon Sep 17 00:00:00 2001 From: jrab66 Date: Fri, 25 Jan 2019 15:00:21 -0600 Subject: [PATCH 057/107] squash screenshot --- themes/metal/metal.theme.bash | 81 +++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 themes/metal/metal.theme.bash diff --git a/themes/metal/metal.theme.bash b/themes/metal/metal.theme.bash new file mode 100644 index 00000000..e0eddd26 --- /dev/null +++ b/themes/metal/metal.theme.bash @@ -0,0 +1,81 @@ +#!/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 + +# inspired by previous bash_it theme : cupcake + +# 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=" - 🧱 " +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_green}\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 bash_it $PROMPT setting) +safe_append_prompt_command prompt_command From 55cf918918fb1650eb33bc9a5b706c6e8ceb1201 Mon Sep 17 00:00:00 2001 From: Alex Thiessen Date: Sat, 2 Feb 2019 10:28:24 +0100 Subject: [PATCH 058/107] editorconfig: Respect user rules Editorconfig provides the concept of cascading rules, refer to https://editorconfig.org/#file-location. For instance, I use a rule which limits line length in git commit messages which enables `vim` to re-flow the text by a simple command. Setting `root=true` in LT's own `.editorconfig` file prevents any such user-defined rules from being propagated. Remove `root=true` to enable user-defined rules. --- .editorconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 4dc96bd5..87e50155 100755 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,5 @@ # EditorConfig is awesome: http://EditorConfig.org -root = true - [*] indent_style = space indent_size = 2 From 83c44fac646ef92e70694f1528d63a6f66b99cfd Mon Sep 17 00:00:00 2001 From: Alex Thiessen Date: Mon, 4 Feb 2019 23:32:39 +0100 Subject: [PATCH 059/107] template/profile: Require interactive shell Bash is run either in interactive mode (e.g. in a terminal) or non-interactive mode (e.g. on an SSH server handling an SCP request). In the latter example, any output performed by bash-it's actions will be interpreted as SCP reply on the client side, typically leading to failed transfers. This is a well-known limitation of the SCP: https://bugzilla.redhat.com/show_bug.cgi?id=20527. In bash's own bashrc example, the first lines of code query for the mode and return early if it's non-interactive: http://git.savannah.gnu.org/cgit/bash.git/tree/examples/startup-files/bashrc?h=bash-5.0#n1. This practice is adopted by Linux distributions (e.g. Ubuntu) and probably other systems. Current mode can be queried as described here: https://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html. Copy the according lines from Debian stretch's default .bashrc (as found in https://packages.debian.org/stretch/bash under /etc/skel/.bashrc) to the bash-it profile template to disable bash-it for non-interactive shells. As a side effect, this change makes SCP faster since the server doesn't need to run any bash-it code in context of SCP handling. --- template/bash_profile.template.bash | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/template/bash_profile.template.bash b/template/bash_profile.template.bash index 5e877900..e7f92dd3 100755 --- a/template/bash_profile.template.bash +++ b/template/bash_profile.template.bash @@ -1,5 +1,11 @@ #!/usr/bin/env bash +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + # Path to the bash it configuration export BASH_IT="{{BASH_IT}}" From f14d4fcc3c7228b0eb6d905421407112d7c594cf Mon Sep 17 00:00:00 2001 From: markusdd Date: Fri, 22 Feb 2019 14:41:01 +0100 Subject: [PATCH 060/107] turn coloured cat and less into ccat and cless old approach would override systems cat, which is malicious when used in conjunction with shell piping or redirection --- plugins/available/less-pretty-cat.plugin.bash | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/available/less-pretty-cat.plugin.bash b/plugins/available/less-pretty-cat.plugin.bash index 9221dde6..841122ca 100644 --- a/plugins/available/less-pretty-cat.plugin.bash +++ b/plugins/available/less-pretty-cat.plugin.bash @@ -6,8 +6,9 @@ if $(command -v pygmentize &> /dev/null) ; then CAT_BIN=$(which cat) LESS_BIN=$(which less) - # pigmentize cat and less outputs - function cat() + # pigmentize cat and less outputs - call them ccat and cless to avoid that + # especially cat'ed output in scripts gets mangled with pygemtized meta characters + function ccat() { about 'runs either pygmentize or cat on each file passed in' param '*: files to concatenate (as normally passed to cat)' @@ -18,7 +19,7 @@ if $(command -v pygmentize &> /dev/null) ; then done } - function less() + function cless() { about 'it pigments the file passed in and passes it to less for pagination' param '$1: the file to paginate with less' From 1e17fa1fd2f442836ccbe41b15e376fcb6159894 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Sun, 24 Feb 2019 21:24:13 +0530 Subject: [PATCH 061/107] added flutter completions --- completion/available/flutter.completion.bash | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 completion/available/flutter.completion.bash diff --git a/completion/available/flutter.completion.bash b/completion/available/flutter.completion.bash new file mode 100644 index 00000000..a274b5f3 --- /dev/null +++ b/completion/available/flutter.completion.bash @@ -0,0 +1,5 @@ +#!/usr/bin/bash + +if command -v flutter > /dev/null; then + eval "$(flutter bash-completion)" +fi \ No newline at end of file From 50aebc5c6e09d324e9a1463ba022db5e6be644a8 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Mon, 25 Feb 2019 16:44:54 +0530 Subject: [PATCH 062/107] fixed code style --- completion/available/flutter.completion.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/completion/available/flutter.completion.bash b/completion/available/flutter.completion.bash index a274b5f3..6372dfe4 100644 --- a/completion/available/flutter.completion.bash +++ b/completion/available/flutter.completion.bash @@ -1,5 +1,5 @@ #!/usr/bin/bash if command -v flutter > /dev/null; then - eval "$(flutter bash-completion)" -fi \ No newline at end of file + eval "$(flutter bash-completion)" +fi From 29f79dfa75f305e3322e8f46bac1af5a8607be58 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Mon, 25 Feb 2019 16:45:52 +0530 Subject: [PATCH 063/107] :bug: fix --- completion/available/flutter.completion.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completion/available/flutter.completion.bash b/completion/available/flutter.completion.bash index 6372dfe4..62befc82 100644 --- a/completion/available/flutter.completion.bash +++ b/completion/available/flutter.completion.bash @@ -1,5 +1,5 @@ #!/usr/bin/bash -if command -v flutter > /dev/null; then +if _command_exists flutter; then eval "$(flutter bash-completion)" fi From 81c3f709007e190cf71558c88324d6ff6fa6dc79 Mon Sep 17 00:00:00 2001 From: Anthony Wharton Date: Thu, 7 Mar 2019 20:12:50 +0000 Subject: [PATCH 064/107] Add eval to SCM_BRANCH in powerline theme --- themes/powerline/powerline.base.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/powerline/powerline.base.bash b/themes/powerline/powerline.base.bash index 08da5f7c..b648e2a0 100644 --- a/themes/powerline/powerline.base.bash +++ b/themes/powerline/powerline.base.bash @@ -99,7 +99,7 @@ function __powerline_scm_prompt { elif [[ "${SCM_HG_CHAR}" == "${SCM_CHAR}" ]]; then scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}" fi - echo "${scm_prompt}${scm}|${color}" + echo "$(eval "echo ${scm_prompt}")${scm}|${color}" fi } From 93348838a1573342ea369dc3b3351ed23d9e5786 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Sun, 10 Mar 2019 08:19:14 +0530 Subject: [PATCH 065/107] bug fix in wpscan args --- completion/available/wpscan.completion.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completion/available/wpscan.completion.bash b/completion/available/wpscan.completion.bash index 9f21a0d8..3630183e 100644 --- a/completion/available/wpscan.completion.bash +++ b/completion/available/wpscan.completion.bash @@ -2,7 +2,7 @@ if command -v wpscan > /dev/null; then __wpscan_completion() { - local OPTS=("--help --hh --version --url --ignore-main-redirect --verbose --output --format --detection-mode --scope --headers --user-agent --vhost --random-user-agent --user-agents-list --http-auth --max-threads --throttle --request-timeout --connect-timeout --disable-tlc-checks --proxy --proxy-auth --cookie-string --cookie-jar --cache-ttl --clear-cache --server --cache-dir --update --no-update --wp-content-dir --wp-plugins-dir --wp-version-detection --main-theme-detection --enumrate --exclude-content-based --plugins-list --plugins-detection --plugins-version-all --plugins-version-detection --themes-list --themes-detection --themes-version-all --themes-version-detection --timthumbs-list --timthumbs-detection --config-backups-list --config-backups-detection --db-exports-list --db-exports-detection --medias-detection --users-list --users-detection --passwords --usernames --multicall-max-passwords --password-attack --stealthy") + local OPTS=("--help --hh --version --url --ignore-main-redirect --verbose --output --format --detection-mode --scope --headers --user-agent --vhost --random-user-agent --user-agents-list --http-auth --max-threads --throttle --request-timeout --connect-timeout --disable-tlc-checks --proxy --proxy-auth --cookie-string --cookie-jar --cache-ttl --clear-cache --server --cache-dir --update --no-update --wp-content-dir --wp-plugins-dir --wp-version-detection --main-theme-detection --enumerate --exclude-content-based --plugins-list --plugins-detection --plugins-version-all --plugins-version-detection --themes-list --themes-detection --themes-version-all --themes-version-detection --timthumbs-list --timthumbs-detection --config-backups-list --config-backups-detection --db-exports-list --db-exports-detection --medias-detection --users-list --users-detection --passwords --usernames --multicall-max-passwords --password-attack --stealthy") COMPREPLY=() for _opt_ in ${OPTS[@]}; do if [[ "$_opt_" == "$2"* ]]; then From 2eeaf522c0359e455f4827281cd6d149ba10c399 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Thu, 14 Mar 2019 01:54:35 +0530 Subject: [PATCH 066/107] added parrot os like terminal prompt --- themes/parrot/parrot.theme.bash | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 themes/parrot/parrot.theme.bash diff --git a/themes/parrot/parrot.theme.bash b/themes/parrot/parrot.theme.bash new file mode 100644 index 00000000..63e1cf33 --- /dev/null +++ b/themes/parrot/parrot.theme.bash @@ -0,0 +1,38 @@ +# +# ~/.bashrc +# + +# git branch parser +function parse_git_branch() { + echo -e "\033[1;34m$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')\033[0m" +} + +function parse_git_branch_no_color() { + echo -e "$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')" +} + +function promp() { + # If not running interactively, don't do anything + [[ $- != *i* ]] && return + + force_color_prompt=yes + + if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi + fi + + if [ "$color_prompt" = yes ]; then + PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]$(parse_git_branch) $\[\e[0m\] " + + else + PS1='┌──[\u@\h]─[\w]\n└──╼ $(parse_git_branch_no_color) $ ' + fi +} + From 7a88b6524ec991aa5b9269ac465ce15fcf5d62c7 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Thu, 14 Mar 2019 13:04:37 +0530 Subject: [PATCH 067/107] deleted unnecessary line --- themes/parrot/parrot.theme.bash | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/themes/parrot/parrot.theme.bash b/themes/parrot/parrot.theme.bash index 63e1cf33..1aa0ab93 100644 --- a/themes/parrot/parrot.theme.bash +++ b/themes/parrot/parrot.theme.bash @@ -1,6 +1,4 @@ -# -# ~/.bashrc -# + # git branch parser function parse_git_branch() { From 9576b878c803156985853b0a2f2f27228116ae98 Mon Sep 17 00:00:00 2001 From: tbhaxor Date: Thu, 14 Mar 2019 13:11:04 +0530 Subject: [PATCH 068/107] :bug: fix in prompt --- themes/parrot/parrot.theme.bash | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/themes/parrot/parrot.theme.bash b/themes/parrot/parrot.theme.bash index 1aa0ab93..afc8dd53 100644 --- a/themes/parrot/parrot.theme.bash +++ b/themes/parrot/parrot.theme.bash @@ -9,20 +9,20 @@ function parse_git_branch_no_color() { echo -e "$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')" } -function promp() { +function prompt() { # If not running interactively, don't do anything [[ $- != *i* ]] && return - force_color_prompt=yes + local force_color_prompt=yes if [ -n "$force_color_prompt" ]; then if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then # We have color support; assume it's compliant with Ecma-48 # (ISO/IEC-6429). (Lack of such support is extremely rare, and such # a case would tend to support setf rather than setaf.) - color_prompt=yes + local color_prompt=yes else - color_prompt= + local color_prompt= fi fi @@ -34,3 +34,4 @@ function promp() { fi } +safe_append_prompt_command prompt From c61d716ee4609538825737a46f1223045fd392d0 Mon Sep 17 00:00:00 2001 From: Renan Date: Thu, 14 Mar 2019 15:21:55 +0100 Subject: [PATCH 069/107] add git patch alias --- aliases/available/git.aliases.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index 75b7997a..b4a3274b 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -67,6 +67,7 @@ alias gt="git tag" alias gta="git tag -a" alias gtd="git tag -d" alias gtl="git tag -l" +alias gpatch="git format-patch -1" # From http://blogs.atlassian.com/2014/10/advanced-git-aliases/ # Show commits since last pull alias gnew="git log HEAD@{1}..HEAD@{0}" From 9f37a1a0d0a47a6b44544b261ca99d3dd339b755 Mon Sep 17 00:00:00 2001 From: Sangeeth Sudheer Date: Thu, 21 Mar 2019 13:21:09 +0530 Subject: [PATCH 070/107] feat(git.aliases): alias to push current branch w/ tracking --- aliases/available/git.aliases.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index b4a3274b..29fae023 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -31,6 +31,7 @@ alias gp='git push' alias gpo='git push origin' alias gpu='git push --set-upstream' alias gpuo='git push --set-upstream origin' +alias gpuoc='git push --set-upstream origin $(git symbolic-ref --short HEAD)' alias gpom='git push origin master' alias gr='git remote' alias grv='git remote -v' From 7156011f83ea595f9406bb606ff9f9be68f1b4ed Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:29 +0700 Subject: [PATCH 071/107] Update docker completion --- completion/available/docker.completion.bash | 994 +++++++++++++++----- 1 file changed, 766 insertions(+), 228 deletions(-) diff --git a/completion/available/docker.completion.bash b/completion/available/docker.completion.bash index 3a4fbe3d..2b3e805c 100644 --- a/completion/available/docker.completion.bash +++ b/completion/available/docker.completion.bash @@ -1,12 +1,14 @@ #!/usr/bin/env bash -# shellcheck disable=SC2016,SC2119,SC2155 +# shellcheck disable=SC2016,SC2119,SC2155,SC2206,SC2207 # # Shellcheck ignore list: # - SC2016: Expressions don't expand in single quotes, use double quotes for that. # - SC2119: Use foo "$@" if function's $1 should mean script's $1. # - SC2155: Declare and assign separately to avoid masking return values. -# -# You can find more details for each warning at the following page: +# - SC2206: Quote to prevent word splitting, or split robustly with mapfile or read -a. +# - SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting). +# +# You can find more details for each warning at the following page: # https://github.com/koalaman/shellcheck/wiki/ # # bash completion file for core docker commands @@ -68,7 +70,7 @@ __docker_previous_extglob_setting=$(shopt -p extglob) shopt -s extglob __docker_q() { - docker ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@" + docker ${host:+--host "$host"} ${config:+--config "$config"} ${context:+--context "$context"} 2>/dev/null "$@" } # __docker_configs returns a list of configs. Additional options to @@ -156,6 +158,11 @@ __docker_complete_containers_running() { __docker_complete_containers "$@" --filter status=running } +# shellcheck disable=SC2120 +__docker_complete_containers_stoppable() { + __docker_complete_containers "$@" --filter status=running --filter status=paused +} + # shellcheck disable=SC2120 __docker_complete_containers_stopped() { __docker_complete_containers "$@" --filter status=exited @@ -178,52 +185,103 @@ __docker_complete_container_ids() { COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) } +# __docker_contexts returns a list of contexts without the special "default" context. +# Completions may be added with `--add`, e.g. `--add default`. +__docker_contexts() { + local add=() + while true ; do + case "$1" in + --add) + add+=("$2") + shift 2 + ;; + *) + break + ;; + esac + done + __docker_q context ls -q + echo "${add[@]}" +} + +__docker_complete_contexts() { + local contexts=( $(__docker_contexts "$@") ) + COMPREPLY=( $(compgen -W "${contexts[*]}" -- "$cur") ) +} + + +# __docker_images returns a list of images. For each image, up to three representations +# can be generated: the repository (e.g. busybox), repository:tag (e.g. busybox:latest) +# and the ID (e.g. sha256:ee22cbbd4ea3dff63c86ba60c7691287c321e93adfc1009604eb1dde7ec88645). +# +# The optional arguments `--repo`, `--tag` and `--id` select the representations that +# may be returned. Whether or not a particular representation is actually returned +# depends on the user's customization through several environment variables: +# - image IDs are only shown if DOCKER_COMPLETION_SHOW_IMAGE_IDS=all|non-intermediate. +# - tags can be excluded by setting DOCKER_COMPLETION_SHOW_TAGS=no. +# - repositories are always shown. +# +# In cases where an exact image specification is needed, `--force-tag` can be used. +# It ignores DOCKER_COMPLETION_SHOW_TAGS and only lists valid repository:tag combinations, +# avoiding repository names that would default to a potentially missing default tag. +# +# Additional arguments to `docker image ls` may be specified in order to filter the list, +# e.g. `__docker_images --filter dangling=true`. +# __docker_images() { - local images_args="" + local repo_format='{{.Repository}}' + local tag_format='{{.Repository}}:{{.Tag}}' + local id_format='{{.ID}}' + local all + local format - 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' + if [ "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" = "all" ] ; then + all='--all' 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 + while true ; do + case "$1" in + --repo) + format+="$repo_format\n" + shift + ;; + --tag) + if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then + format+="$tag_format\n" + fi + shift + ;; + --id) + if [[ $DOCKER_COMPLETION_SHOW_IMAGE_IDS =~ ^(all|non-intermediate)$ ]] ; then + format+="$id_format\n" + fi + shift + ;; + --force-tag) + # like `--tag` but ignores environment setting + format+="$tag_format\n" + shift + ;; + *) + break + ;; + esac + done - __docker_q images $images_args | awk "$awk_script" | grep -v '$' + __docker_q image ls --no-trunc --format "${format%\\n}" $all "$@" | grep -v '$' } +# __docker_complete_images applies completion of images based on the current value of `$cur` or +# the value of the optional first option `--cur`, if given. +# See __docker_images for customization of the returned items. __docker_complete_images() { - COMPREPLY=( $(compgen -W "$(__docker_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" + local current="$cur" + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_images "$@")" -- "$current") ) + __ltrim_colon_completions "$current" } # __docker_networks returns a list of all networks. Additional options to @@ -262,10 +320,9 @@ __docker_complete_networks() { COMPREPLY=( $(compgen -W "$(__docker_networks "$@")" -- "$current") ) } -# shellcheck disable=SC2128,SC2178 __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") ) + local containers=($(__docker_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1")) + COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) } # __docker_volumes returns a list of all volumes. Additional options to @@ -321,8 +378,7 @@ __docker_plugins_bundled() { for del in "${remove[@]}" ; do plugins=(${plugins[@]/$del/}) done - # shellcheck disable=SC2145 - echo "${plugins[@]} ${add[@]}" + echo "${plugins[@]}" "${add[@]}" } # __docker_complete_plugins_bundled applies completion of plugins based on the current @@ -539,23 +595,64 @@ __docker_append_to_completions() { COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) } -# __docker_daemon_is_experimental tests whether the currently configured Docker -# daemon runs in experimental mode. If so, the function exits with 0 (true). -# Otherwise, or if the result cannot be determined, the exit value is 1 (false). -__docker_daemon_is_experimental() { - [ "$(__docker_q version -f '{{.Server.Experimental}}')" = "true" ] +# __docker_fetch_info fetches information about the configured Docker server and updates +# several variables with the results. +# The result is cached for the duration of one invocation of bash completion. +__docker_fetch_info() { + if [ -z "$info_fetched" ] ; then + read -r client_experimental server_experimental server_os <<< "$(__docker_q version -f '{{.Client.Experimental}} {{.Server.Experimental}} {{.Server.Os}}')" + info_fetched=true + fi } -# __docker_daemon_os_is tests whether the currently configured Docker daemon runs +# __docker_client_is_experimental tests whether the Docker cli is configured to support +# experimental features. If so, the function exits with 0 (true). +# Otherwise, or if the result cannot be determined, the exit value is 1 (false). +__docker_client_is_experimental() { + __docker_fetch_info + [ "$client_experimental" = "true" ] +} + +# __docker_server_is_experimental tests whether the currently configured Docker +# server runs in experimental mode. If so, the function exits with 0 (true). +# Otherwise, or if the result cannot be determined, the exit value is 1 (false). +__docker_server_is_experimental() { + __docker_fetch_info + [ "$server_experimental" = "true" ] +} + +# __docker_server_os_is tests whether the currently configured Docker server runs # on the operating system passed in as the first argument. -# It does so by querying the daemon for its OS. The result is cached for the duration -# of one invocation of bash completion so that this function can be used to test for -# several different operating systems without additional costs. # Known operating systems: linux, windows. -__docker_daemon_os_is() { +__docker_server_os_is() { local expected_os="$1" - local actual_os=${daemon_os=$(__docker_q version -f '{{.Server.Os}}')} - [ "$actual_os" = "$expected_os" ] + __docker_fetch_info + [ "$server_os" = "$expected_os" ] +} + +# __docker_stack_orchestrator_is tests whether the client is configured to use +# the orchestrator that is passed in as the first argument. +__docker_stack_orchestrator_is() { + case "$1" in + kubernetes) + if [ -z "$stack_orchestrator_is_kubernetes" ] ; then + __docker_q stack ls --help | grep -qe --namespace + stack_orchestrator_is_kubernetes=$? + fi + return $stack_orchestrator_is_kubernetes + ;; + swarm) + if [ -z "$stack_orchestrator_is_swarm" ] ; then + __docker_q stack deploy --help | grep -qe "with-registry-auth" + stack_orchestrator_is_swarm=$? + fi + return $stack_orchestrator_is_swarm + ;; + *) + return 1 + ;; + + esac } # __docker_pos_first_nonflag finds the position of the first word that is neither @@ -816,6 +913,7 @@ __docker_complete_log_drivers() { gelf journald json-file + local logentries none splunk @@ -839,7 +937,8 @@ __docker_complete_log_options() { local gcplogs_options="$common_options1 $common_options2 gcp-log-cmd gcp-meta-id gcp-meta-name gcp-meta-zone gcp-project" local gelf_options="$common_options1 $common_options2 gelf-address gelf-compression-level gelf-compression-type gelf-tcp-max-reconnect gelf-tcp-reconnect-delay tag" local journald_options="$common_options1 $common_options2 tag" - local json_file_options="$common_options1 $common_options2 max-file max-size" + local json_file_options="$common_options1 $common_options2 compress max-file max-size" + local local_options="$common_options1 compress max-file max-size" local logentries_options="$common_options1 $common_options2 line-only logentries-token tag" local splunk_options="$common_options1 $common_options2 splunk-caname splunk-capath splunk-format splunk-gzip splunk-gzip-level splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url splunk-verify-connection tag" local syslog_options="$common_options1 $common_options2 syslog-address syslog-facility syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify tag" @@ -868,6 +967,9 @@ __docker_complete_log_options() { json-file) COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) ) ;; + local) + COMPREPLY=( $( compgen -W "$local_options" -S = -- "$cur" ) ) + ;; logentries) COMPREPLY=( $( compgen -W "$logentries_options" -S = -- "$cur" ) ) ;; @@ -897,7 +999,7 @@ __docker_complete_log_driver_options() { __docker_nospace return ;; - fluentd-async-connect) + compress|fluentd-async-connect) COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) return ;; @@ -1024,6 +1126,23 @@ __docker_complete_signals() { COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo "$cur" | tr '[:lower:]' '[:upper:]')" ) ) } +__docker_complete_stack_orchestrator_options() { + case "$prev" in + --kubeconfig) + _filedir + return 0 + ;; + --namespace) + return 0 + ;; + --orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur") ) + return 0 + ;; + esac + return 1 +} + __docker_complete_user_group() { if [[ $cur == *:* ]] ; then COMPREPLY=( $(compgen -g -- "${cur#*:}") ) @@ -1046,6 +1165,10 @@ _docker_docker() { _filedir -d return ;; + --context|-c) + __docker_complete_contexts + return + ;; --log-level|-l) __docker_complete_log_levels return @@ -1062,7 +1185,8 @@ _docker_docker() { *) local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) if [ "$cword" -eq "$counter" ]; then - __docker_daemon_is_experimental && commands+=(${experimental_commands[*]}) + __docker_client_is_experimental && commands+=(${experimental_client_commands[*]}) + __docker_server_is_experimental && commands+=(${experimental_server_commands[*]}) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) fi ;; @@ -1078,6 +1202,41 @@ _docker_build() { } +_docker_builder() { + local subcommands=" + prune + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_builder_prune() { + case "$prev" in + --filter) + COMPREPLY=( $( compgen -S = -W "description id inuse parent private shared type until unused-for" -- "$cur" ) ) + __docker_nospace + return + ;; + --keep-storage) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter --force -f --help --keep-storage" -- "$cur" ) ) + ;; + esac +} + _docker_checkpoint() { local subcommands=" create @@ -1194,14 +1353,18 @@ _docker_config_create() { --label|-l) return ;; + --template-driver) + COMPREPLY=( $( compgen -W "golang" -- "$cur" ) ) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --label -l" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --label -l --template-driver" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--label|-l') + local counter=$(__docker_pos_first_nonflag '--label|-l|--template-driver') if [ "$cword" -eq "$((counter + 1))" ]; then _filedir fi @@ -1354,11 +1517,8 @@ _docker_container_commit() { if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -1368,7 +1528,7 @@ _docker_container_commit() { _docker_container_cp() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--follow-link -L --help" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--archive -a --follow-link -L --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) @@ -1387,8 +1547,7 @@ _docker_container_cp() { local containers=( ${COMPREPLY[@]} ) COMPREPLY=( $( compgen -W "${files[*]} ${containers[*]}" -- "$cur" ) ) - # shellcheck disable=SC2128 - if [[ "$COMPREPLY" == *: ]]; then + if [[ "${COMPREPLY[*]}" = *: ]]; then __docker_nospace fi return @@ -1529,8 +1688,7 @@ _docker_container_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in ancestor) - cur="${cur##*=}" - __docker_complete_images + __docker_complete_images --cur "${cur##*=}" --repo --tag --id return ;; before) @@ -1720,6 +1878,7 @@ _docker_container_run_and_create() { --dns --dns-option --dns-search + --domainname --entrypoint --env -e --env-file @@ -1772,14 +1931,14 @@ _docker_container_run_and_create() { --volume -v --workdir -w " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --cpu-count --cpu-percent --io-maxbandwidth --io-maxiops --isolation " - __docker_daemon_is_experimental && options_with_args+=" + __docker_server_is_experimental && options_with_args+=" --platform " @@ -1887,8 +2046,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'none host private shareable container:' -- "$cur" ) ) - # shellcheck disable=SC2128 - if [ "$COMPREPLY" = "container:" ]; then + if [ "${COMPREPLY[*]}" = "container:" ]; then __docker_nospace fi ;; @@ -1896,7 +2054,7 @@ _docker_container_run_and_create() { return ;; --isolation) - if __docker_daemon_os_is windows ; then + if __docker_server_os_is windows ; then __docker_complete_isolation return fi @@ -1942,8 +2100,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) - # shellcheck disable=SC2128 - if [ "$COMPREPLY" = "container:" ]; then + if [ "${COMPREPLY[*]}" = "container:" ]; then __docker_nospace fi ;; @@ -1998,7 +2155,7 @@ _docker_container_run_and_create() { *) local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag --id fi ;; esac @@ -2006,15 +2163,14 @@ _docker_container_run_and_create() { _docker_container_start() { __docker_complete_detach_keys && return - # shellcheck disable=SC2078 case "$prev" in --checkpoint) - if [ __docker_daemon_is_experimental ] ; then + if __docker_server_is_experimental ; then return fi ;; --checkpoint-dir) - if [ __docker_daemon_is_experimental ] ; then + if __docker_server_is_experimental ; then _filedir -d return fi @@ -2024,7 +2180,7 @@ _docker_container_start() { case "$cur" in -*) local options="--attach -a --detach-keys --help --interactive -i" - __docker_daemon_is_experimental && options+=" --checkpoint --checkpoint-dir" + __docker_server_is_experimental && options+=" --checkpoint --checkpoint-dir" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) @@ -2062,7 +2218,7 @@ _docker_container_stop() { COMPREPLY=( $( compgen -W "--help --time -t" -- "$cur" ) ) ;; *) - __docker_complete_containers_running + __docker_complete_containers_stoppable ;; esac } @@ -2110,6 +2266,7 @@ _docker_container_update() { --memory -m --memory-reservation --memory-swap + --pids-limit --restart " @@ -2149,6 +2306,172 @@ _docker_container_wait() { } +_docker_context() { + local subcommands=" + create + export + import + inspect + ls + rm + update + use + " + local aliases=" + list + remove + " + __docker_subcommands "$subcommands $aliases" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_context_create() { + case "$prev" in + --default-stack-orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur" ) ) + return + ;; + --description|--docker|--kubernetes) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--default-stack-orchestrator --description --docker --help --kubernetes" -- "$cur" ) ) + ;; + esac +} + +_docker_context_export() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --kubeconfig" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts + elif [ "$cword" -eq "$((counter + 1))" ]; then + _filedir + fi + ;; + esac +} + +_docker_context_import() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + : + elif [ "$cword" -eq "$((counter + 1))" ]; then + _filedir + fi + ;; + esac +} + +_docker_context_inspect() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_contexts + ;; + esac +} + +_docker_context_list() { + _docker_context_ls +} + +_docker_context_ls() { + case "$prev" in + --format|-f) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--format -f --help --quiet -q" -- "$cur" ) ) + ;; + esac +} + +_docker_context_remove() { + _docker_context_rm +} + +_docker_context_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--force -f --help" -- "$cur" ) ) + ;; + *) + __docker_complete_contexts + ;; + esac +} + +_docker_context_update() { + case "$prev" in + --default-stack-orchestrator) + COMPREPLY=( $( compgen -W "all kubernetes swarm" -- "$cur" ) ) + return + ;; + --description|--docker|--kubernetes) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--default-stack-orchestrator --description --docker --help --kubernetes" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts + fi + ;; + esac +} + +_docker_context_use() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_contexts --add default + fi + ;; + esac +} + + _docker_commit() { _docker_container_commit } @@ -2196,6 +2519,7 @@ _docker_daemon() { --cpu-rt-period --cpu-rt-runtime --data-root + --default-address-pool --default-gateway --default-gateway-v6 --default-runtime @@ -2386,13 +2710,75 @@ _docker_daemon() { } _docker_deploy() { - __docker_daemon_is_experimental && _docker_stack_deploy + __docker_server_is_experimental && _docker_stack_deploy } _docker_diff() { _docker_container_diff } + +_docker_engine() { + local subcommands=" + activate + check + update + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_activate() { + case "$prev" in + --containerd|--engine-image|--format|--license|--registry-prefix|--version) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --display-only --engine-image --format --help --license --quiet --registry-prefix --version" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_check() { + case "$prev" in + --containerd|--engine-image|--format|--registry-prefix) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --downgrades --engine-image --format --help --pre-releases --quiet -q --registry-prefix --upgrades" -- "$cur" ) ) + ;; + esac +} + +_docker_engine_update() { + case "$prev" in + --containerd|--engine-image|--registry-prefix|--version) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--containerd --engine-image --help --registry-prefix --version" -- "$cur" ) ) + ;; + esac +} + + _docker_events() { _docker_system_events } @@ -2472,7 +2858,7 @@ _docker_image_build() { --target --ulimit " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --isolation " @@ -2486,7 +2872,7 @@ _docker_image_build() { --quiet -q --rm " - if __docker_daemon_is_experimental ; then + if __docker_server_is_experimental ; then options_with_args+=" --platform " @@ -2513,7 +2899,7 @@ _docker_image_build() { return ;; --cache-from) - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag --id return ;; --file|-f|--iidfile) @@ -2521,7 +2907,7 @@ _docker_image_build() { return ;; --isolation) - if __docker_daemon_os_is windows ; then + if __docker_server_os_is windows ; then __docker_complete_isolation return fi @@ -2541,7 +2927,7 @@ _docker_image_build() { return ;; --tag|-t) - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag return ;; --target) @@ -2587,9 +2973,9 @@ _docker_image_history() { COMPREPLY=( $( compgen -W "--format --help --human=false -H=false --no-trunc --quiet -q" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag) + local counter=$(__docker_pos_first_nonflag '--format') if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --force-tag --id fi ;; esac @@ -2601,24 +2987,24 @@ _docker_image_images() { _docker_image_import() { case "$prev" in - --change|-c|--message|-m) + --change|-c|--message|-m|--platform) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) ) + local options="--change -c --help --message -m" + __docker_server_is_experimental && options+=" --platform" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m') if [ "$cword" -eq "$counter" ]; then + _filedir return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -2651,9 +3037,8 @@ _docker_image_list() { _docker_image_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in - before|since|reference) - cur="${cur##*=}" - __docker_complete_images + before|since) + __docker_complete_images --cur "${cur##*=}" --force-tag --id return ;; dangling) @@ -2663,6 +3048,10 @@ _docker_image_ls() { label) return ;; + reference) + __docker_complete_images --cur "${cur##*=}" --repo --tag + return + ;; esac case "$prev" in @@ -2684,7 +3073,7 @@ _docker_image_ls() { return ;; *) - __docker_complete_image_repos + __docker_complete_images --repo --tag ;; esac } @@ -2714,8 +3103,8 @@ _docker_image_pull() { case "$cur" in -*) - local options="--all-tags -a --disable-content-trust=false --help" - __docker_daemon_is_experimental && options+=" --platform" + local options="--all-tags -a --disable-content-trust=false --help --quiet -q" + __docker_server_is_experimental && options+=" --platform" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; @@ -2725,12 +3114,12 @@ _docker_image_pull() { for arg in "${COMP_WORDS[@]}"; do case "$arg" in --all-tags|-a) - __docker_complete_image_repos + __docker_complete_images --repo return ;; esac done - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag fi ;; esac @@ -2744,7 +3133,7 @@ _docker_image_push() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + __docker_complete_images --repo --tag fi ;; esac @@ -2760,7 +3149,7 @@ _docker_image_rm() { COMPREPLY=( $( compgen -W "--force -f --help --no-prune" -- "$cur" ) ) ;; *) - __docker_complete_images + __docker_complete_images --force-tag --id ;; esac } @@ -2782,7 +3171,7 @@ _docker_image_save() { COMPREPLY=( $( compgen -W "--help --output -o" -- "$cur" ) ) ;; *) - __docker_complete_images + __docker_complete_images --repo --tag --id ;; esac } @@ -2796,13 +3185,10 @@ _docker_image_tag() { local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + __docker_complete_images --force-tag --id return - fi - (( counter++ )) - - if [ "$cword" -eq "$counter" ]; then - __docker_complete_image_repos_and_tags + elif [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --repo --tag return fi ;; @@ -2858,7 +3244,7 @@ _docker_inspect() { '') COMPREPLY=( $( compgen -W " $(__docker_containers --all) - $(__docker_images) + $(__docker_images --force-tag --id) $(__docker_networks) $(__docker_nodes) $(__docker_plugins_installed) @@ -2872,7 +3258,7 @@ _docker_inspect() { __docker_complete_containers_all ;; image) - __docker_complete_images + __docker_complete_images --force-tag --id ;; network) __docker_complete_networks @@ -3045,6 +3431,10 @@ _docker_network_inspect() { _docker_network_ls() { local key=$(__docker_map_key_of_current_option '--filter|-f') case "$key" in + dangling) + COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) ) + return + ;; driver) __docker_complete_plugins_bundled --cur "${cur##*=}" --type Network --add macvlan return @@ -3069,7 +3459,7 @@ _docker_network_ls() { case "$prev" in --filter|-f) - COMPREPLY=( $( compgen -S = -W "driver id label name scope type" -- "$cur" ) ) + COMPREPLY=( $( compgen -S = -W "dangling driver id label name scope type" -- "$cur" ) ) __docker_nospace return ;; @@ -3195,7 +3585,7 @@ _docker_service_logs() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--follow -f --help --no-resolve --no-task-ids --no-trunc --since --tail --timestamps -t" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--details --follow -f --help --no-resolve --no-task-ids --no-trunc --raw --since --tail --timestamps -t" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--since|--tail') @@ -3334,8 +3724,6 @@ _docker_service_update_and_create() { local options_with_args=" --endpoint-mode --entrypoint - --env -e - --force --health-cmd --health-interval --health-retries @@ -3343,13 +3731,12 @@ _docker_service_update_and_create() { --health-timeout --hostname --isolation - --label -l --limit-cpu --limit-memory --log-driver --log-opt - --mount --replicas + --replicas-max-per-node --reserve-cpu --reserve-memory --restart-condition @@ -3373,14 +3760,16 @@ _docker_service_update_and_create() { --user -u --workdir -w " - __docker_daemon_os_is windows && options_with_args+=" + __docker_server_os_is windows && options_with_args+=" --credential-spec " local boolean_options=" --detach -d --help + --init --no-healthcheck + --no-resolve-image --read-only --tty -t --with-registry-auth @@ -3396,52 +3785,31 @@ _docker_service_update_and_create() { --dns --dns-option --dns-search + --env -e --env-file --generic-resource --group --host + --label -l --mode + --mount --name --network --placement-pref --publish -p --secret + --sysctl " case "$prev" in - --config) - __docker_complete_configs - return - ;; --env-file) _filedir return ;; - --group) - COMPREPLY=( $(compgen -g -- "$cur") ) - return - ;; - --host) - case "$cur" in - *:) - __docker_complete_resolved_hostname - return - ;; - esac - ;; --mode) COMPREPLY=( $( compgen -W "global replicated" -- "$cur" ) ) return ;; - --placement-pref) - COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) - __docker_nospace - return - ;; - --secret) - __docker_complete_secrets - return - ;; esac fi if [ "$subcommand" = "update" ] ; then @@ -3459,6 +3827,8 @@ _docker_service_update_and_create() { --dns-rm --dns-search-add --dns-search-rm + --env-add + --env-rm --generic-resource-add --generic-resource-rm --group-add @@ -3466,6 +3836,10 @@ _docker_service_update_and_create() { --host-add --host-rm --image + --label-add + --label-rm + --mount-add + --mount-rm --network-add --network-rm --placement-pref-add @@ -3475,40 +3849,21 @@ _docker_service_update_and_create() { --rollback --secret-add --secret-rm + --sysctl-add + --sysctl-rm + " + + boolean_options="$boolean_options + --force " case "$prev" in - --config-add|--config-rm) - __docker_complete_configs + --env-rm) + COMPREPLY=( $( compgen -e -- "$cur" ) ) return ;; - --group-add|--group-rm) - COMPREPLY=( $(compgen -g -- "$cur") ) - return - ;; - --host-add|--host-rm) - case "$cur" in - *:) - __docker_complete_resolved_hostname - return - ;; - esac - ;; --image) - __docker_complete_image_repos_and_tags - return - ;; - --network-add|--network-rm) - __docker_complete_networks - return - ;; - --placement-pref-add|--placement-pref-rm) - COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) - __docker_nospace - return - ;; - --secret-add|--secret-rm) - __docker_complete_secrets + __docker_complete_images --repo --tag --id return ;; esac @@ -3524,16 +3879,32 @@ _docker_service_update_and_create() { esac case "$prev" in + --config|--config-add|--config-rm) + __docker_complete_configs + return + ;; --endpoint-mode) COMPREPLY=( $( compgen -W "dnsrr vip" -- "$cur" ) ) return ;; - --env|-e) + --env|-e|--env-add) # we do not append a "=" here because "-e VARNAME" is legal systax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return ;; + --group|--group-add|--group-rm) + COMPREPLY=( $(compgen -g -- "$cur") ) + return + ;; + --host|--host-add|--host-rm) + case "$cur" in + *:) + __docker_complete_resolved_hostname + return + ;; + esac + ;; --isolation) __docker_complete_isolation return @@ -3546,10 +3917,15 @@ _docker_service_update_and_create() { __docker_complete_log_options return ;; - --network) + --network|--network-add|--network-rm) __docker_complete_networks return ;; + --placement-pref|--placement-pref-add|--placement-pref-rm) + COMPREPLY=( $( compgen -W "spread" -S = -- "$cur" ) ) + __docker_nospace + return + ;; --restart-condition) COMPREPLY=( $( compgen -W "any none on-failure" -- "$cur" ) ) return @@ -3558,6 +3934,10 @@ _docker_service_update_and_create() { COMPREPLY=( $( compgen -W "continue pause" -- "$cur" ) ) return ;; + --secret|--secret-add|--secret-rm) + __docker_complete_secrets + return + ;; --stop-signal) __docker_complete_signals return @@ -3591,7 +3971,7 @@ _docker_service_update_and_create() { fi else if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag --id fi fi ;; @@ -3654,7 +4034,7 @@ _docker_swarm_init() { COMPREPLY=( $( compgen -W "active drain pause" -- "$cur" ) ) return ;; - --cert-expiry|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit) + --cert-expiry|--data-path-port|--default-addr-pool|--default-addr-pool-mask-length|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit ) return ;; --data-path-addr) @@ -3674,7 +4054,7 @@ _docker_swarm_init() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --data-path-port --default-addr-pool --default-addr-pool-mask-length --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit " -- "$cur" ) ) ;; esac } @@ -3774,6 +4154,109 @@ _docker_swarm_update() { esac } +_docker_manifest() { + local subcommands=" + annotate + create + inspect + push + " + __docker_subcommands "$subcommands" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_manifest_annotate() { + case "$prev" in + --arch) + COMPREPLY=( $( compgen -W " + 386 + amd64 + arm + arm64 + mips64 + mips64le + ppc64le + s390x" -- "$cur" ) ) + return + ;; + --os) + COMPREPLY=( $( compgen -W " + darwin + dragonfly + freebsd + linux + netbsd + openbsd + plan9 + solaris + windows" -- "$cur" ) ) + return + ;; + --os-features|--variant) + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--arch --help --os --os-features --variant" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag "--arch|--os|--os-features|--variant" ) + if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + +_docker_manifest_create() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--amend -a --help --insecure" -- "$cur" ) ) + ;; + *) + __docker_complete_images --force-tag --id + ;; + esac +} + +_docker_manifest_inspect() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --insecure --verbose -v" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag ) + if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + +_docker_manifest_push() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --insecure --purge -p" -- "$cur" ) ) + ;; + *) + local counter=$( __docker_pos_first_nonflag ) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_images --force-tag --id + fi + ;; + esac +} + _docker_node() { local subcommands=" demote @@ -4237,14 +4720,18 @@ _docker_secret_create() { --driver|-d|--label|-l) return ;; + --template-driver) + COMPREPLY=( $( compgen -W "golang" -- "$cur" ) ) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--driver -d --help --label -l" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--driver -d --help --label -l --template-driver" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--driver|-d|--label|-l') + local counter=$(__docker_pos_first_nonflag '--driver|-d|--label|-l|--template-driver') if [ "$cword" -eq "$((counter + 1))" ]; then _filedir fi @@ -4367,11 +4854,15 @@ _docker_stack() { remove up " + + __docker_complete_stack_orchestrator_options && return __docker_subcommands "$subcommands $aliases" && return case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + local options="--help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) @@ -4380,12 +4871,12 @@ _docker_stack() { } _docker_stack_deploy() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --bundle-file) - if __docker_daemon_is_experimental ; then - _filedir dab - return - fi + _filedir dab + return ;; --compose-file|-c) _filedir yml @@ -4399,12 +4890,14 @@ _docker_stack_deploy() { case "$cur" in -*) - local options="--compose-file -c --help --prune --resolve-image --with-registry-auth" - __docker_daemon_is_experimental && options+=" --bundle-file" + local options="--compose-file -c --help --orchestrator" + __docker_server_is_experimental && __docker_stack_orchestrator_is swarm && options+=" --bundle-file" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + __docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth" COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--bundle-file|--compose-file|-c|--resolve-image') + local counter=$(__docker_pos_first_nonflag '--bundle-file|--compose-file|-c|--kubeconfig|--namespace|--orchestrator|--resolve-image') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4421,6 +4914,8 @@ _docker_stack_list() { } _docker_stack_ls() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --format) return @@ -4429,7 +4924,9 @@ _docker_stack_ls() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--format --help" -- "$cur" ) ) + local options="--format --help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --all-namespaces --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; esac } @@ -4451,6 +4948,8 @@ _docker_stack_ps() { ;; esac + __docker_complete_stack_orchestrator_options && return + case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "id name desired-state" -- "$cur" ) ) @@ -4464,10 +4963,12 @@ _docker_stack_ps() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--filter -f --format --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) ) + local options="--filter -f --format --help --no-resolve --no-trunc --orchestrator --quiet -q" + __docker_stack_orchestrator_is kubernetes && options+=" --all-namespaces --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--filter|-f') + local counter=$(__docker_pos_first_nonflag '--all-namespaces|--filter|-f|--format|--kubeconfig|--namespace') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4480,9 +4981,13 @@ _docker_stack_remove() { } _docker_stack_rm() { + __docker_complete_stack_orchestrator_options && return + case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + local options="--help --orchestrator" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) __docker_complete_stacks @@ -4506,6 +5011,8 @@ _docker_stack_services() { ;; esac + __docker_complete_stack_orchestrator_options && return + case "$prev" in --filter|-f) COMPREPLY=( $( compgen -S = -W "id label name" -- "$cur" ) ) @@ -4519,10 +5026,12 @@ _docker_stack_services() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--filter -f --format --help --quiet -q" -- "$cur" ) ) + local options="--filter -f --format --help --orchestrator --quiet -q" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - local counter=$(__docker_pos_first_nonflag '--filter|-f|--format') + local counter=$(__docker_pos_first_nonflag '--filter|-f|--format|--kubeconfig|--namespace|--orchestrator') if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi @@ -4609,6 +5118,7 @@ _docker_system_events() { enable exec_create exec_detach + exec_die exec_start export health_status @@ -4639,16 +5149,19 @@ _docker_system_events() { return ;; image) - cur="${cur##*=}" - __docker_complete_images + __docker_complete_images --cur "${cur##*=}" --repo --tag return ;; network) __docker_complete_networks --cur "${cur##*=}" return ;; + scope) + COMPREPLY=( $( compgen -W "local swarm" -- "${cur##*=}" ) ) + return + ;; type) - COMPREPLY=( $( compgen -W "container daemon image network plugin volume" -- "${cur##*=}" ) ) + COMPREPLY=( $( compgen -W "config container daemon image network plugin secret service volume" -- "${cur##*=}" ) ) return ;; volume) @@ -4659,7 +5172,7 @@ _docker_system_events() { case "$prev" in --filter|-f) - COMPREPLY=( $( compgen -S = -W "container daemon event image label network type volume" -- "$cur" ) ) + COMPREPLY=( $( compgen -S = -W "container daemon event image label network scope type volume" -- "$cur" ) ) __docker_nospace return ;; @@ -4713,9 +5226,9 @@ _docker_tag() { _docker_trust() { local subcommands=" + inspect revoke sign - view " __docker_subcommands "$subcommands" && return @@ -4729,6 +5242,20 @@ _docker_trust() { esac } +_docker_trust_inspect() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help --pretty" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ "$cword" -eq "$counter" ]; then + __docker_complete_images --repo --tag + fi + ;; + esac +} + _docker_trust_revoke() { case "$cur" in -*) @@ -4737,7 +5264,7 @@ _docker_trust_revoke() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --repo --tag fi ;; esac @@ -4751,21 +5278,7 @@ _docker_trust_sign() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_images - fi - ;; - esac -} - -_docker_trust_view() { - case "$cur" in - -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) - ;; - *) - local counter=$(__docker_pos_first_nonflag) - if [ "$cword" -eq "$counter" ]; then - __docker_complete_images + __docker_complete_images --force-tag --id fi ;; esac @@ -4785,6 +5298,8 @@ _docker_top() { } _docker_version() { + __docker_complete_stack_orchestrator_options && return + case "$prev" in --format|-f) return @@ -4793,7 +5308,9 @@ _docker_version() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--format -f --help" -- "$cur" ) ) + local options="--format -f --help" + __docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig" + COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; esac } @@ -4936,8 +5453,11 @@ _docker() { shopt -s extglob local management_commands=( + builder config container + context + engine image network node @@ -4947,6 +5467,7 @@ _docker() { stack swarm system + trust volume ) @@ -4996,10 +5517,13 @@ _docker() { wait ) - local experimental_commands=( + local experimental_client_commands=( + manifest + ) + + local experimental_server_commands=( checkpoint deploy - trust ) local commands=(${management_commands[*]} ${top_level_commands[*]}) @@ -5014,6 +5538,7 @@ _docker() { " local global_options_with_args=" --config + --context -c --host -H --log-level -l --tlscacert @@ -5021,7 +5546,12 @@ _docker() { --tlskey " - local host config daemon_os + # variables to cache server info, populated on demand for performance reasons + local info_fetched server_experimental server_os + # variables to cache client info, populated on demand for performance reasons + local client_experimental stack_orchestrator_is_kubernetes stack_orchestrator_is_swarm + + local host config context COMPREPLY=() local cur prev words cword @@ -5031,6 +5561,9 @@ _docker() { local counter=1 while [ "$counter" -lt "$cword" ]; do case "${words[$counter]}" in + docker) + return 0 + ;; # save host so that completion can use custom daemon --host|-H) (( counter++ )) @@ -5041,6 +5574,11 @@ _docker() { (( counter++ )) config="${words[$counter]}" ;; + # save context so that completion can use custom daemon + --context|-c) + (( counter++ )) + context="${words[$counter]}" + ;; $(__docker_to_extglob "$global_options_with_args") ) (( counter++ )) ;; @@ -5076,4 +5614,4 @@ _docker() { eval "$__docker_previous_extglob_setting" unset __docker_previous_extglob_setting -complete -F _docker docker docker.exe dockerd dockerd.exe +complete -F _docker docker docker.exe dockerd dockerd.exe \ No newline at end of file From 4329da109ecf43f5672617309a081a51d4f9061e Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:45 +0700 Subject: [PATCH 072/107] Update docker compose collection --- .../available/docker-compose.completion.bash | 224 +++++++++++------- 1 file changed, 134 insertions(+), 90 deletions(-) diff --git a/completion/available/docker-compose.completion.bash b/completion/available/docker-compose.completion.bash index 87161d0a..dedd8e31 100644 --- a/completion/available/docker-compose.completion.bash +++ b/completion/available/docker-compose.completion.bash @@ -16,6 +16,8 @@ # below to your .bashrc after bash completion features are loaded # . ~/.docker-compose-completion.sh +__docker_compose_previous_extglob_setting=$(shopt -p extglob) +shopt -s extglob __docker_compose_q() { docker-compose 2>/dev/null "${top_level_options[@]}" "$@" @@ -48,64 +50,56 @@ __docker_compose_has_option() { return 1 } +# Returns `key` if we are currently completing the value of a map option (`key=value`) +# which matches the extglob passed in as an argument. +# This function is needed for key-specific completions. +__docker_compose_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" +} + # 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 + +# Outputs a list of all defined services, regardless of their running state. +# Arguments for `docker-compose ps` may be passed in order to filter the service list, +# e.g. `status=running`. +__docker_compose_services() { + __docker_compose_q ps --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' +# Applies completion of services based on the current value of `$cur`. +# Arguments for `docker-compose ps` may be passed in order to filter the service list, +# see `__docker_compose_services`. +__docker_compose_complete_services() { + COMPREPLY=( $(compgen -W "$(__docker_compose_services "$@")" -- "$cur") ) } # 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_complete_running_services() { + local names=$(__docker_compose_services --filter status=running) + COMPREPLY=( $(compgen -W "$names" -- "$cur") ) } @@ -116,14 +110,17 @@ _docker_compose_build() { __docker_compose_nospace return ;; + --memory|-m) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--build-arg --force-rm --help --memory --no-cache --pull" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--build-arg --compress --force-rm --help --memory -m --no-cache --no-rm --pull --parallel -q --quiet" -- "$cur" ) ) ;; *) - __docker_compose_services_from_build + __docker_compose_complete_services --filter source=build ;; esac } @@ -142,7 +139,18 @@ _docker_compose_bundle() { _docker_compose_config() { - COMPREPLY=( $( compgen -W "--help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) + case "$prev" in + --hash) + if [[ $cur == \\* ]] ; then + COMPREPLY=( '\*' ) + else + COMPREPLY=( $(compgen -W "$(__docker_compose_services) \\\* " -- "$cur") ) + fi + return + ;; + esac + + COMPREPLY=( $( compgen -W "--hash --help --quiet -q --resolve-image-digests --services --volumes" -- "$cur" ) ) } @@ -152,7 +160,7 @@ _docker_compose_create() { COMPREPLY=( $( compgen -W "--build --force-recreate --help --no-build --no-recreate" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -168,18 +176,22 @@ _docker_compose_docker_compose() { _filedir "y?(a)ml" return ;; + --log-level) + COMPREPLY=( $( compgen -W "debug info warning error critical" -- "$cur" ) ) + return + ;; --project-directory) _filedir -d return ;; - $(__docker_compose_to_extglob "$top_level_options_with_args") ) + $(__docker_compose_to_extglob "$daemon_options_with_args") ) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "$top_level_boolean_options $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args $top_level_options_with_args --help -h --no-ansi --verbose --version -v" -- "$cur" ) ) ;; *) COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) @@ -194,11 +206,14 @@ _docker_compose_down() { COMPREPLY=( $( compgen -W "all local" -- "$cur" ) ) return ;; + --timeout|-t) + return + ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --rmi --volumes -v --remove-orphans" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --rmi --timeout -t --volumes -v --remove-orphans" -- "$cur" ) ) ;; esac } @@ -216,7 +231,7 @@ _docker_compose_events() { COMPREPLY=( $( compgen -W "--help --json" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -224,17 +239,17 @@ _docker_compose_events() { _docker_compose_exec() { case "$prev" in - --index|--user|-u) + --index|--user|-u|--workdir|-w) return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "-d --help --index --privileged -T --user -u" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "-d --detach --help --index --privileged -T --user -u --workdir -w" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -247,10 +262,10 @@ _docker_compose_help() { _docker_compose_images() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --quiet -q" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -268,7 +283,7 @@ _docker_compose_kill() { COMPREPLY=( $( compgen -W "--help -s" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -286,7 +301,7 @@ _docker_compose_logs() { COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -298,7 +313,7 @@ _docker_compose_pause() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -320,19 +335,39 @@ _docker_compose_port() { COMPREPLY=( $( compgen -W "--help --index --protocol" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } _docker_compose_ps() { + local key=$(__docker_compose_map_key_of_current_option '--filter') + case "$key" in + source) + COMPREPLY=( $( compgen -W "build image" -- "${cur##*=}" ) ) + return + ;; + status) + COMPREPLY=( $( compgen -W "paused restarting running stopped" -- "${cur##*=}" ) ) + return + ;; + esac + + case "$prev" in + --filter) + COMPREPLY=( $( compgen -W "source status" -S "=" -- "$cur" ) ) + __docker_compose_nospace + return; + ;; + esac + case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--all -a --filter --help --quiet -q --services" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -341,10 +376,10 @@ _docker_compose_ps() { _docker_compose_pull() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --parallel --quiet" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--help --ignore-pull-failures --include-deps --no-parallel --quiet -q" -- "$cur" ) ) ;; *) - __docker_compose_services_from_image + __docker_compose_complete_services --filter source=image ;; esac } @@ -356,7 +391,7 @@ _docker_compose_push() { COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -374,7 +409,7 @@ _docker_compose_restart() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -387,9 +422,9 @@ _docker_compose_rm() { ;; *) if __docker_compose_has_option "--stop|-s" ; then - __docker_compose_services_all + __docker_compose_complete_services else - __docker_compose_services_stopped + __docker_compose_complete_services --filter status=stopped fi ;; esac @@ -410,10 +445,10 @@ _docker_compose_run() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --label -l --name --no-deps --publish -p --rm --service-ports -T --user -u --volume -v --workdir -w" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--detach -d --entrypoint -e --help --label -l --name --no-deps --publish -p --rm --service-ports -T --use-aliases --user -u --volume -v --workdir -w" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -435,7 +470,7 @@ _docker_compose_scale() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) + COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") ) __docker_compose_nospace ;; esac @@ -448,7 +483,7 @@ _docker_compose_start() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_stopped + __docker_compose_complete_services --filter status=stopped ;; esac } @@ -466,7 +501,7 @@ _docker_compose_stop() { COMPREPLY=( $( compgen -W "--help --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -478,7 +513,7 @@ _docker_compose_top() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_running + __docker_compose_complete_running_services ;; esac } @@ -490,7 +525,7 @@ _docker_compose_unpause() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_compose_services_paused + __docker_compose_complete_services --filter status=paused ;; esac } @@ -503,11 +538,11 @@ _docker_compose_up() { return ;; --exit-code-from) - __docker_compose_services_all + __docker_compose_complete_services return ;; --scale) - COMPREPLY=( $(compgen -S "=" -W "$(___docker_compose_all_services_in_compose_file)" -- "$cur") ) + COMPREPLY=( $(compgen -S "=" -W "$(__docker_compose_services)" -- "$cur") ) __docker_compose_nospace return ;; @@ -518,10 +553,10 @@ _docker_compose_up() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --remove-orphans --scale --timeout -t" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--abort-on-container-exit --always-recreate-deps --build -d --detach --exit-code-from --force-recreate --help --no-build --no-color --no-deps --no-recreate --no-start --renew-anon-volumes -V --remove-orphans --scale --timeout -t" -- "$cur" ) ) ;; *) - __docker_compose_services_all + __docker_compose_complete_services ;; esac } @@ -571,14 +606,12 @@ _docker_compose() { # Options for the docker daemon that have to be passed to secondary calls to # docker-compose executed by this script. - # Other global otions that are not relevant for secondary calls are defined in - # `_docker_compose_docker_compose`. - local top_level_boolean_options=" + local daemon_boolean_options=" --skip-hostname-check --tls --tlsverify " - local top_level_options_with_args=" + local daemon_options_with_args=" --file -f --host -H --project-directory @@ -588,6 +621,11 @@ _docker_compose() { --tlskey " + # These options are require special treatment when searching the command. + local top_level_options_with_args=" + --log-level + " + COMPREPLY=() local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword @@ -600,15 +638,18 @@ _docker_compose() { while [ $counter -lt $cword ]; do case "${words[$counter]}" in - $(__docker_compose_to_extglob "$top_level_boolean_options") ) + $(__docker_compose_to_extglob "$daemon_boolean_options") ) local opt=${words[counter]} top_level_options+=($opt) ;; - $(__docker_compose_to_extglob "$top_level_options_with_args") ) + $(__docker_compose_to_extglob "$daemon_options_with_args") ) local opt=${words[counter]} local arg=${words[++counter]} top_level_options+=($opt $arg) ;; + $(__docker_compose_to_extglob "$top_level_options_with_args") ) + (( counter++ )) + ;; -*) ;; *) @@ -626,4 +667,7 @@ _docker_compose() { return 0 } -complete -F _docker_compose docker-compose docker-compose.exe +eval "$__docker_compose_previous_extglob_setting" +unset __docker_compose_previous_extglob_setting + +complete -F _docker_compose docker-compose docker-compose.exe \ No newline at end of file From df011d7ab636239145354b24839d49a5ba0cc84d Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 22 Mar 2019 16:21:55 +0700 Subject: [PATCH 073/107] Update docker machine completion --- .../available/docker-machine.completion.bash | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/completion/available/docker-machine.completion.bash b/completion/available/docker-machine.completion.bash index e92bd4cf..8c692ff6 100644 --- a/completion/available/docker-machine.completion.bash +++ b/completion/available/docker-machine.completion.bash @@ -86,6 +86,40 @@ _docker_machine_map_key_of_current_option() { [[ ${words[$glob_pos]} == $glob ]] && echo "$key" } +# Finds the position of the first word that is neither option nor an option's argument. +# If there are options that require arguments, you need to pass a glob describing +# those options, e.g. "--option1|-o|--option2". +# Use this function to restrict completions to exact positions after the options. +_docker_machine_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 +} # --- completion functions --------------------------------------------------- _docker_machine_active() { @@ -128,7 +162,7 @@ _docker_machine_create() { _docker_machine_env() { case "${prev}" in --shell) - COMPREPLY=($(compgen -W "cmd fish powershell tcsh" -- "${cur}")) + COMPREPLY=($(compgen -W "cmd emacs fish powershell tcsh" -- "${cur}")) return ;; esac @@ -208,6 +242,21 @@ _docker_machine_ls() { fi } +_docker_machine_mount() { + if [[ "${cur}" == -* ]]; then + COMPREPLY=($(compgen -W "--help --unmount -u" -- "${cur}")) + else + local pos=$(_docker_machine_pos_first_nonflag) + if [ "$cword" -eq "$pos" ]; then + # We can't complete remote filesystems. All we can do here is to complete the machine. + COMPREPLY=($(compgen -W "$(_docker_machine_machines --filter state=Running)" -S: -- "${cur}")) + _docker_machine_nospace + elif [ "$cword" -eq "$((pos + 1))" ]; then + _filedir -d + fi + fi +} + _docker_machine_provision() { if [[ "${cur}" == -* ]]; then COMPREPLY=($(compgen -W "--help" -- "${cur}")) @@ -218,7 +267,7 @@ _docker_machine_provision() { _docker_machine_regenerate_certs() { if [[ "${cur}" == -* ]]; then - COMPREPLY=($(compgen -W "--force -f --help" -- "${cur}")) + COMPREPLY=($(compgen -W "--client-certs --force -f --help" -- "${cur}")) else COMPREPLY=($(compgen -W "$(_docker_machine_machines --filter state=Running)" -- "${cur}")) fi @@ -250,7 +299,7 @@ _docker_machine_ssh() { _docker_machine_scp() { if [[ "${cur}" == -* ]]; then - COMPREPLY=($(compgen -W "--delta -d --help --recursive -r" -- "${cur}")) + COMPREPLY=($(compgen -W "--delta -d --help --quiet -q --recursive -r" -- "${cur}")) else _filedir # It would be really nice to ssh to the machine and ls to complete @@ -329,7 +378,7 @@ _docker_machine_docker_machine() { _docker_machine() { COMPREPLY=() - local commands=(active config create env inspect ip kill ls provision regenerate-certs restart rm ssh scp start status stop upgrade url version help) + local commands=(active config create env inspect ip kill ls mount provision 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) @@ -343,7 +392,7 @@ _docker_machine() { local cur prev words cword _get_comp_words_by_ref -n : cur prev words cword local i - local command=docker-machine + local command=docker-machine command_pos=0 for (( i=1; i < ${cword}; ++i)); do local word=${words[i]} @@ -352,6 +401,7 @@ _docker_machine() { (( ++i )) elif [[ " ${commands[*]} " =~ " ${word} " ]]; then command=${word} + command_pos=$i fi done @@ -363,4 +413,4 @@ _docker_machine() { return 0 } -complete -F _docker_machine docker-machine docker-machine.exe +complete -F _docker_machine docker-machine docker-machine.exe \ No newline at end of file From 918ccd25d6b37c17157d749ceebdc13ee9da0e3d Mon Sep 17 00:00:00 2001 From: Brian Phillips Date: Tue, 26 Mar 2019 10:04:19 -0500 Subject: [PATCH 074/107] Add support for helm completion Signed-off-by: Brian Phillips --- completion/available/helm.completion.bash | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 completion/available/helm.completion.bash diff --git a/completion/available/helm.completion.bash b/completion/available/helm.completion.bash new file mode 100644 index 00000000..d0936fab --- /dev/null +++ b/completion/available/helm.completion.bash @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# helm (Kubernetes Package Manager) completion + +if command -v helm &>/dev/null +then + eval "$(helm completion bash)" +fi From 2cadeaab05e47e6f8e87bc88b3b3b0b2eebf422a Mon Sep 17 00:00:00 2001 From: LanikSJ Date: Thu, 28 Mar 2019 15:12:03 -0700 Subject: [PATCH 075/107] Add Alias for Git Stash --- aliases/available/git.aliases.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index 29fae023..d13c14a4 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -76,6 +76,8 @@ alias gnew="git log HEAD@{1}..HEAD@{0}" alias gcaa="git commit -a --amend -C HEAD" alias ggui="git gui" alias gcsam="git commit -S -am" +alias gst="git stash" +alias gstb="git stash branch" alias gstd="git stash drop" alias gstl="git stash list" alias gh='cd "$(git rev-parse --show-toplevel)"' From fae61b3b98dfeeeb49d8362aad3f02a81b9329c9 Mon Sep 17 00:00:00 2001 From: LanikSJ Date: Tue, 2 Apr 2019 07:06:03 -0700 Subject: [PATCH 076/107] Remove gst Alias --- aliases/available/git.aliases.bash | 1 - 1 file changed, 1 deletion(-) diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index d13c14a4..7e6eeb24 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -18,7 +18,6 @@ alias gm="git merge" alias gmv='git mv' alias g='git' alias get='git' -alias gst='git status' alias gs='git status' alias gss='git status -s' alias gsu='git submodule update --init --recursive' From b5c9ecaf27551fcd37fcc8c5ed1eefbbec922e29 Mon Sep 17 00:00:00 2001 From: Joao Pereira Date: Thu, 4 Apr 2019 17:51:32 -0400 Subject: [PATCH 077/107] Add CNB pack cli plugin Adds the plugin that enables autocompletion for pack CLI --- plugins/available/pack.plugin.bash | 621 +++++++++++++++++++++++++++++ 1 file changed, 621 insertions(+) create mode 100644 plugins/available/pack.plugin.bash diff --git a/plugins/available/pack.plugin.bash b/plugins/available/pack.plugin.bash new file mode 100644 index 00000000..a63a8e57 --- /dev/null +++ b/plugins/available/pack.plugin.bash @@ -0,0 +1,621 @@ +# bash completion for pack -*- shell-script -*- + +cite about-plugin +about-plugin 'CNB pack cli aliases' + + +__pack_debug() +{ + if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + echo "$*" >> "${BASH_COMP_DEBUG_FILE}" + fi +} + +# Homebrew on Macs have version 1.3 of bash-completion which doesn't include +# _init_completion. This is a very minimal version of that function. +__pack_init_completion() +{ + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} + +__pack_index_of_word() +{ + local w word=$1 + shift + index=0 + for w in "$@"; do + [[ $w = "$word" ]] && return + index=$((index+1)) + done + index=-1 +} + +__pack_contains_word() +{ + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__pack_handle_reply() +{ + __pack_debug "${FUNCNAME[0]}" + case $cur in + -*) + if [[ $(type -t compopt) = "builtin" ]]; then + compopt -o nospace + fi + local allflags + if [ ${#must_have_one_flag[@]} -ne 0 ]; then + allflags=("${must_have_one_flag[@]}") + else + allflags=("${flags[*]} ${two_word_flags[*]}") + fi + COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) + if [[ $(type -t compopt) = "builtin" ]]; then + [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace + fi + + # complete after --flag=abc + if [[ $cur == *=* ]]; then + if [[ $(type -t compopt) = "builtin" ]]; then + compopt +o nospace + fi + + local index flag + flag="${cur%=*}" + __pack_index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() + if [[ ${index} -ge 0 ]]; then + PREFIX="" + cur="${cur#*=}" + ${flags_completion[${index}]} + if [ -n "${ZSH_VERSION}" ]; then + # zsh completion needs --flag= prefix + eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" + fi + fi + fi + return 0; + ;; + esac + + # check if we are handling a flag with special work handling + local index + __pack_index_of_word "${prev}" "${flags_with_completion[@]}" + if [[ ${index} -ge 0 ]]; then + ${flags_completion[${index}]} + return + fi + + # we are parsing a flag and don't have a special handler, no completion + if [[ ${cur} != "${words[cword]}" ]]; then + return + fi + + local completions + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions=("${must_have_one_noun[@]}") + fi + if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then + completions+=("${must_have_one_flag[@]}") + fi + COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) + + if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then + COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) + fi + + if [[ ${#COMPREPLY[@]} -eq 0 ]]; then + declare -F __custom_func >/dev/null && __custom_func + fi + + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi +} + +# The arguments should be in the form "ext1|ext2|extn" +__pack_handle_filename_extension_flag() +{ + local ext="$1" + _filedir "@(${ext})" +} + +__pack_handle_subdirs_in_dir_flag() +{ + local dir="$1" + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 +} + +__pack_handle_flag() +{ + __pack_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + # if a command required a flag, and we found it, unset must_have_one_flag() + local flagname=${words[c]} + local flagvalue + # if the word contained an = + if [[ ${words[c]} == *"="* ]]; then + flagvalue=${flagname#*=} # take in as flagvalue after the = + flagname=${flagname%=*} # strip everything after the = + flagname="${flagname}=" # but put the = back + fi + __pack_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __pack_contains_word "${flagname}" "${must_have_one_flag[@]}"; then + must_have_one_flag=() + fi + + # if you set a flag which only applies to this command, don't show subcommands + if __pack_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + + # keep flag value with flagname as flaghash + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi + fi + + # skip the argument to a two word flag + if __pack_contains_word "${words[c]}" "${two_word_flags[@]}"; then + c=$((c+1)) + # if we are looking for a flags value, don't show commands + if [[ $c -eq $cword ]]; then + commands=() + fi + fi + + c=$((c+1)) + +} + +__pack_handle_noun() +{ + __pack_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + if __pack_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + must_have_one_noun=() + elif __pack_contains_word "${words[c]}" "${noun_aliases[@]}"; then + must_have_one_noun=() + fi + + nouns+=("${words[c]}") + c=$((c+1)) +} + +__pack_handle_command() +{ + __pack_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + local next_command + if [[ -n ${last_command} ]]; then + next_command="_${last_command}_${words[c]//:/__}" + else + if [[ $c -eq 0 ]]; then + next_command="_pack_root_command" + else + next_command="_${words[c]//:/__}" + fi + fi + c=$((c+1)) + __pack_debug "${FUNCNAME[0]}: looking for ${next_command}" + declare -F "$next_command" >/dev/null && $next_command +} + +__pack_handle_word() +{ + if [[ $c -ge $cword ]]; then + __pack_handle_reply + return + fi + __pack_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + if [[ "${words[c]}" == -* ]]; then + __pack_handle_flag + elif __pack_contains_word "${words[c]}" "${commands[@]}"; then + __pack_handle_command + elif [[ $c -eq 0 ]]; then + __pack_handle_command + elif __pack_contains_word "${words[c]}" "${command_aliases[@]}"; then + # aliashash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + words[c]=${aliashash[${words[c]}]} + __pack_handle_command + else + __pack_handle_noun + fi + else + __pack_handle_noun + fi + __pack_handle_word +} + +_pack_build() +{ + last_command="pack_build" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--builder=") + local_nonpersistent_flags+=("--builder=") + flags+=("--buildpack=") + local_nonpersistent_flags+=("--buildpack=") + flags+=("--clear-cache") + local_nonpersistent_flags+=("--clear-cache") + flags+=("--env=") + two_word_flags+=("-e") + local_nonpersistent_flags+=("--env=") + flags+=("--env-file=") + local_nonpersistent_flags+=("--env-file=") + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-pull") + local_nonpersistent_flags+=("--no-pull") + flags+=("--path=") + two_word_flags+=("-p") + local_nonpersistent_flags+=("--path=") + flags+=("--publish") + local_nonpersistent_flags+=("--publish") + flags+=("--run-image=") + local_nonpersistent_flags+=("--run-image=") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_run() +{ + last_command="pack_run" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--builder=") + local_nonpersistent_flags+=("--builder=") + flags+=("--buildpack=") + local_nonpersistent_flags+=("--buildpack=") + flags+=("--clear-cache") + local_nonpersistent_flags+=("--clear-cache") + flags+=("--env=") + two_word_flags+=("-e") + local_nonpersistent_flags+=("--env=") + flags+=("--env-file=") + local_nonpersistent_flags+=("--env-file=") + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-pull") + local_nonpersistent_flags+=("--no-pull") + flags+=("--path=") + two_word_flags+=("-p") + local_nonpersistent_flags+=("--path=") + flags+=("--port=") + local_nonpersistent_flags+=("--port=") + flags+=("--run-image=") + local_nonpersistent_flags+=("--run-image=") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_rebase() +{ + last_command="pack_rebase" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-pull") + local_nonpersistent_flags+=("--no-pull") + flags+=("--publish") + local_nonpersistent_flags+=("--publish") + flags+=("--run-image=") + local_nonpersistent_flags+=("--run-image=") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_create-builder() +{ + last_command="pack_create-builder" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--builder-config=") + two_word_flags+=("-b") + local_nonpersistent_flags+=("--builder-config=") + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-pull") + local_nonpersistent_flags+=("--no-pull") + flags+=("--publish") + local_nonpersistent_flags+=("--publish") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_flag+=("--builder-config=") + must_have_one_flag+=("-b") + must_have_one_noun=() + noun_aliases=() +} + +_pack_set-run-image-mirrors() +{ + last_command="pack_set-run-image-mirrors" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--mirror=") + two_word_flags+=("-m") + local_nonpersistent_flags+=("--mirror=") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_flag+=("--mirror=") + must_have_one_flag+=("-m") + must_have_one_noun=() + noun_aliases=() +} + +_pack_inspect-builder() +{ + last_command="pack_inspect-builder" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_set-default-builder() +{ + last_command="pack_set-default-builder" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_version() +{ + last_command="pack_version" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_completion() +{ + last_command="pack_completion" + + command_aliases=() + + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_pack_root_command() +{ + last_command="pack" + + command_aliases=() + + commands=() + commands+=("build") + commands+=("run") + commands+=("rebase") + commands+=("create-builder") + commands+=("set-run-image-mirrors") + commands+=("inspect-builder") + commands+=("set-default-builder") + commands+=("version") + commands+=("completion") + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--help") + flags+=("-h") + local_nonpersistent_flags+=("--help") + flags+=("--no-color") + flags+=("--quiet") + flags+=("-q") + flags+=("--timestamps") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +__start_pack() +{ + local cur prev words cword + declare -A flaghash 2>/dev/null || : + declare -A aliashash 2>/dev/null || : + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -s || return + else + __pack_init_completion -n "=" || return + fi + + local c=0 + local flags=() + local two_word_flags=() + local local_nonpersistent_flags=() + local flags_with_completion=() + local flags_completion=() + local commands=("pack") + local must_have_one_flag=() + local must_have_one_noun=() + local last_command + local nouns=() + + __pack_handle_word +} + +if [[ $(type -t compopt) = "builtin" ]]; then + complete -o default -F __start_pack pack +else + complete -o default -o nospace -F __start_pack pack +fi + +# ex: ts=4 sw=4 et filetype=sh From c8b4ffbac1f9722c39ae544cf1603c3a05ae202b Mon Sep 17 00:00:00 2001 From: trmaphi Date: Fri, 5 Apr 2019 16:38:18 +0700 Subject: [PATCH 078/107] Update bash completion for git v2.21.0 --- completion/available/git.completion.bash | 1953 ++++++++++++---------- 1 file changed, 1116 insertions(+), 837 deletions(-) diff --git a/completion/available/git.completion.bash b/completion/available/git.completion.bash index e3918c87..1e3fdcac 100644 --- a/completion/available/git.completion.bash +++ b/completion/available/git.completion.bash @@ -28,27 +28,57 @@ # 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 ; ... '". +# +# Compatible with bash 3.2.57. +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +# GIT_COMPLETION_CHECKOUT_NO_GUESS +# +# When set to "1", do not include "DWIM" suggestions in git-checkout +# completion (e.g., completing "foo" when "origin/foo" exists). case "$COMP_WORDBREAKS" in *:*) : great ;; *) COMP_WORDBREAKS="$COMP_WORDBREAKS:" esac +# Discovers the path to the git repository taking any '--git-dir=' and +# '-C ' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ + if [ -n "$__git_repo_path" ]; then + # we already know where it is + return + fi + + if [ -n "${__git_C_args-}" ]; then + __git_repo_path="$(git "${__git_C_args[@]}" \ + ${__git_dir:+--git-dir="$__git_dir"} \ + rev-parse --absolute-git-dir 2>/dev/null)" + elif [ -n "${__git_dir-}" ]; then + test -d "$__git_dir" && + __git_repo_path="$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" && + __git_repo_path="$GIT_DIR" + elif [ -d .git ]; then + __git_repo_path=.git + else + __git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" + fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead # __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 + __git_find_repo_path || return 1 + echo "$__git_repo_path" elif [ -d "$1/.git" ]; then echo "$1/.git" else @@ -56,6 +86,78 @@ __gitdir () fi } +# Runs git with all the options given as argument, respecting any +# '--git-dir=' and '-C ' options present on the command line +__git () +{ + git ${__git_C_args:+"${__git_C_args[@]}"} \ + ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + +# Removes backslash escaping, single quotes and double quotes from a word, +# stores the result in the variable $dequoted_word. +# 1: The word to dequote. +__git_dequote () +{ + local rest="$1" len ch + + dequoted_word="" + + while test -n "$rest"; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\'\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + $'\n') + ;; + *) + dequoted_word="$dequoted_word$ch" + ;; + esac + rest="${rest:2}" + ;; + \') + rest="${rest:1}" + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%\'*}" + rest="${rest:$((${#dequoted_word}-$len+1))}" + ;; + \") + rest="${rest:1}" + while test -n "$rest" ; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + \"|\\|\$|\`) + dequoted_word="$dequoted_word$ch" + ;; + $'\n') + ;; + *) + dequoted_word="$dequoted_word\\$ch" + ;; + esac + rest="${rest:2}" + ;; + \") + rest="${rest:1}" + break + ;; + esac + done + ;; + esac + done +} + # The following function is based on code from: # # bash_completion - programmable completion functions for bash 3.2+ @@ -75,8 +177,7 @@ __gitdir () # 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. +# along with this program; if not, see . # # The latest version of this software can be obtained here: # @@ -185,6 +286,20 @@ _get_comp_words_by_ref () } fi +# Fills the COMPREPLY array with prefiltered words without any additional +# processing. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +# prefix and suffix. +__gitcomp_direct () +{ + local IFS=$'\n' + + COMPREPLY=($1) +} + __gitcompappend () { local x i=${#COMPREPLY[@]} @@ -215,9 +330,32 @@ __gitcomp () case "$cur_" in --*=) ;; + --no-*) + local c i=0 IFS=$' \t\n' + for c in $1; do + if [[ $c == "--" ]]; then + continue + fi + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; *) local c i=0 IFS=$' \t\n' for c in $1; do + if [[ $c == "--" ]]; then + c="--no-...${4-}" + if [[ $c == "$cur_"* ]]; then + COMPREPLY[i++]="${2-}$c " + fi + break + fi c="$c${4-}" if [[ $c == "$cur_"* ]]; then case $c in @@ -231,6 +369,47 @@ __gitcomp () esac } +# Clear the variables caching builtins' options when (re-)sourcing +# the completion script. +if [[ -n ${ZSH_VERSION-} ]]; then + unset $(set |sed -ne 's/^\(__gitcomp_builtin_[a-zA-Z0-9_][a-zA-Z0-9_]*\)=.*/\1/p') 2>/dev/null +else + unset $(compgen -v __gitcomp_builtin_) +fi + +# This function is equivalent to +# +# __gitcomp "$(git xxx --git-completion-helper) ..." +# +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded +__gitcomp_builtin () +{ + # spaces must be replaced with underscore for multi-word + # commands, e.g. "git remote add" becomes remote_add. + local cmd="$1" + local incl="$2" + local excl="$3" + + local var=__gitcomp_builtin_"${cmd/-/_}" + local options + eval "options=\$$var" + + if [ -z "$options" ]; then + # leading and trailing spaces are significant to make + # option removal work correctly. + options=" $incl $(__git ${cmd/_/ } --git-completion-helper) " + for i in $excl; do + options="${options/ $i / }" + done + eval "$var=\"$options\"" + fi + + __gitcomp "$options" +} + # Variation of __gitcomp_nl () that appends to the existing list of # completion candidates, COMPREPLY. __gitcomp_nl_append () @@ -254,6 +433,24 @@ __gitcomp_nl () __gitcomp_nl_append "$@" } +# Fills the COMPREPLY array with prefiltered paths without any additional +# processing. +# Callers must take care of providing only paths that match the current path +# to be completed and adding any prefix path components, if necessary. +# 1: List of newline-separated matching paths, complete with all prefix +# path components. +__gitcomp_file_direct () +{ + local IFS=$'\n' + + COMPREPLY=($1) + + # 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 || + true +} + # Generates completion reply with compgen from newline-separated possible # completion filenames. # It accepts 1 to 3 arguments: @@ -273,7 +470,8 @@ __gitcomp_file () # 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 + compgen -f /non-existing-dir/ >/dev/null || + true } # Execute 'git ls-files', unless the --committable option is specified, in @@ -283,11 +481,13 @@ __gitcomp_file () __git_ls_files_helper () { if [ "$2" == "--committable" ]; then - git -C "$1" diff-index --name-only --relative HEAD + __git -C "$1" -c core.quotePath=false diff-index \ + --name-only --relative HEAD -- "${3//\\/\\\\}*" 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 -C "$1" -c core.quotePath=false ls-files \ + --exclude-standard $2 -- "${3//\\/\\\\}*" + fi } @@ -297,101 +497,283 @@ __git_ls_files_helper () # If provided, only files within the specified directory are listed. # Sub directories are never recursed. Path must have a trailing # slash. +# 3: List only paths matching this path component (optional). __git_index_files () { - local dir="$(__gitdir)" root="${2-.}" file + local root="$2" match="$3" - 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_ls_files_helper "$root" "$1" "$match" | + awk -F / -v pfx="${2//\\/\\\\}" '{ + paths[$1] = 1 + } + END { + for (p in paths) { + if (substr(p, 1, 1) != "\"") { + # No special characters, easy! + print pfx p + continue + } + + # The path is quoted. + p = dequote(p) + if (p == "") + continue + + # Even when a directory name itself does not contain + # any special characters, it will still be quoted if + # any of its (stripped) trailing path components do. + # Because of this we may have seen the same direcory + # both quoted and unquoted. + if (p in paths) + # We have seen the same directory unquoted, + # skip it. + continue + else + print pfx p + } + } + function dequote(p, bs_idx, out, esc, esc_idx, dec) { + # Skip opening double quote. + p = substr(p, 2) + + # Interpret backslash escape sequences. + while ((bs_idx = index(p, "\\")) != 0) { + out = out substr(p, 1, bs_idx - 1) + esc = substr(p, bs_idx + 1, 1) + p = substr(p, bs_idx + 2) + + if ((esc_idx = index("abtvfr\"\\", esc)) != 0) { + # C-style one-character escape sequence. + out = out substr("\a\b\t\v\f\r\"\\", + esc_idx, 1) + } else if (esc == "n") { + # Uh-oh, a newline character. + # We cant reliably put a pathname + # containing a newline into COMPREPLY, + # and the newline would create a mess. + # Skip this path. + return "" + } else { + # Must be a \nnn octal value, then. + dec = esc * 64 + \ + substr(p, 1, 1) * 8 + \ + substr(p, 2, 1) + out = out sprintf("%c", dec) + p = substr(p, 3) + } + } + # Drop closing double quote, if there is one. + # (There isnt any if this is a directory, as it was + # already stripped with the trailing path components.) + if (substr(p, length(p), 1) == "\"") + out = out substr(p, 1, length(p) - 1) + else + out = out p + + return out + }' } +# __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 dequoted_word pfx="" cur_ + + __git_dequote "$cur" + + case "$dequoted_word" in + ?*/*) + pfx="${dequoted_word%/*}/" + cur_="${dequoted_word##*/}" + ;; + *) + cur_="$dequoted_word" + esac + + __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")" +} + +# Lists branches from the local repository. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). __git_heads () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/heads - return - fi + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/heads/$cur_*" "refs/heads/$cur_*/**" } +# Lists tags from the local repository. +# Accepts the same positional parameters as __git_heads() above. __git_tags () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/tags - return - fi + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/tags/$cur_*" "refs/tags/$cur_*/**" } -# __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 +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +# Can be the name of a configured remote, a path, or a URL. +# 2: In addition to local refs, list unique branches from refs/remotes/ for +# 'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: A prefix to be added to each listed ref (optional). +# 4: List only refs matching this word (optional; list all refs if unset or +# empty). +# 5: A suffix to be appended to each listed ref (optional; ignored, if set +# but empty). +# +# Use __git_complete_refs() instead. __git_refs () { - local i hash dir="$(__gitdir "${1-}")" track="${2-}" + local i hash dir track="${2-}" + local list_refs_from=path remote="${1-}" local format refs - if [ -d "$dir" ]; then - case "$cur" in + local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}" + local match="${4-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + __git_find_repo_path + dir="$__git_repo_path" + + if [ -z "$remote" ]; then + if [ -z "$dir" ]; then + return + fi + else + if __git_is_configured_remote "$remote"; then + # configured remote takes precedence over a + # local directory with the same name + list_refs_from=remote + elif [ -d "$remote/.git" ]; then + dir="$remote/.git" + elif [ -d "$remote" ]; then + dir="$remote" + else + list_refs_from=url + fi + fi + + if [ "$list_refs_from" = path ]; then + if [[ "$cur_" == ^* ]]; then + pfx="$pfx^" + fer_pfx="$fer_pfx^" + cur_=${cur_#^} + match=${match#^} + fi + case "$cur_" in refs|refs/*) format="refname" - refs="${cur%/*}" + refs=("$match*" "$match*/**") track="" ;; *) - for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do - if [ -e "$dir/$i" ]; then echo $i; fi + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD; do + case "$i" in + $match*) + if [ -e "$dir/$i" ]; then + echo "$pfx$i$sfx" + fi + ;; + esac done - format="refname:short" - refs="refs/tags refs/heads refs/remotes" + format="refname:strip=2" + refs=("refs/tags/$match*" "refs/tags/$match*/**" + "refs/heads/$match*" "refs/heads/$match*/**" + "refs/remotes/$match*" "refs/remotes/$match*/**") ;; esac - git --git-dir="$dir" for-each-ref --format="%($format)" \ - $refs + __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \ + "${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 + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + --sort="refname:strip=3" \ + "refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \ + uniq -u fi return fi - case "$cur" in + case "$cur_" in refs|refs/*) - git ls-remote "$dir" "$cur*" 2>/dev/null | \ + __git ls-remote "$remote" "$match*" | \ while read -r hash i; do case "$i" in *^{}) ;; - *) echo "$i" ;; + *) echo "$pfx$i$sfx" ;; esac done ;; *) - echo "HEAD" - git for-each-ref --format="%(refname:short)" -- \ - "refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##" + if [ "$list_refs_from" = remote ]; then + case "HEAD" in + $match*) echo "${pfx}HEAD$sfx" ;; + esac + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + "refs/remotes/$remote/$match*" \ + "refs/remotes/$remote/$match*/**" + else + local query_symref + case "HEAD" in + $match*) query_symref="HEAD" ;; + esac + __git ls-remote "$remote" $query_symref \ + "refs/tags/$match*" "refs/heads/$match*" \ + "refs/remotes/$match*" | + while read -r hash i; do + case "$i" in + *^{}) ;; + refs/*) echo "$pfx${i#refs/*/}$sfx" ;; + *) echo "$pfx$i$sfx" ;; # symbolic refs + esac + done + fi ;; esac } +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [