diff --git a/.editorconfig b/.editorconfig index e1baa432..e35a1b04 100755 --- a/.editorconfig +++ b/.editorconfig @@ -9,13 +9,13 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{md,rst}] +[**.{md,rst}] trim_trailing_whitespace = false [.git*] indent_style = tab -[*.*sh] +[{**.*sh,test/run}] indent_style = tab indent_size = 4 @@ -23,7 +23,7 @@ shell_variant = bash binary_next_line = true # like -bn switch_case_indent = true # like -ci space_redirects = true # like -sr -keep_padding = true # like -kp +keep_padding = false # like -kp end_of_line = lf charset = utf-8 trim_trailing_whitespace = true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03b75882..dcef30aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: bats-test: strategy: matrix: - os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, macos-10.15, macos-11.0] + os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, macos-10.15] runs-on: ${{ matrix.os }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index caed0df9..f80494e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,3 +28,17 @@ repos: # - id: forbid-crlf - id: remove-crlf exclude: ".bat$" + - repo: local + hooks: + - id: dot-sh + name: Check .sh files against bash-it requirements + entry: ./hooks/dot-sh.sh + language: system + files: "\\.sh$" + types: [file] + - id: dot-bash + name: Check .bash files against bash-it requirements + entry: ./hooks/dot-bash.sh + language: system + files: "\\.bash$" + types: [file] diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f156b04a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Bash-it + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/aliases/available/clipboard.aliases.bash b/aliases/available/clipboard.aliases.bash index c6c15519..4c7e6f5b 100644 --- a/aliases/available/clipboard.aliases.bash +++ b/aliases/available/clipboard.aliases.bash @@ -1,20 +1,17 @@ +# shellcheck shell=bash cite 'about-alias' -about-alias 'pbcopy and pbpaste shortcuts to linux' +about-alias 'xclip shortcuts' -case $OSTYPE in - linux*) - XCLIP=$(command -v xclip) - [[ $XCLIP ]] && \ - alias pbcopy="$XCLIP -selection clipboard" && \ - alias pbpaste="$XCLIP -selection clipboard -o" - ;; -esac +alias pbcopy="xclip -selection clipboard" +alias pbpaste="xclip -selection clipboard -o" +alias xcpy="xclip -selection clipboard" +alias xpst="xclip -selection clipboard -o" # to use it just install xclip on your distribution and it would work like: -# $ echo "hello" | pbcopy -# $ pbpaste +# $ echo "hello" | xcpy +# $ xpst # hello # very useful for things like: -# cat ~/.ssh/id_rsa.pub | pbcopy +# cat ~/.ssh/id_rsa.pub | xcpy # have fun! diff --git a/aliases/available/dnf.aliases.bash b/aliases/available/dnf.aliases.bash new file mode 100644 index 00000000..9d9f0267 --- /dev/null +++ b/aliases/available/dnf.aliases.bash @@ -0,0 +1,18 @@ +# shellcheck shell=bash +cite 'about-alias' +about-alias 'dnf aliases for fedora 22+ distros' + +alias dnfl="dnf list" # List packages +alias dnfli="dnf list installed" # List installed packages +alias dnfgl="dnf grouplist" # List package groups +alias dnfmc="dnf makecache" # Generate metadata cache +alias dnfp="dnf info" # Show package information +alias dnfs="dnf search" # Search package + +alias dnfu="sudo dnf upgrade" # Upgrade package +alias dnfi="sudo dnf install" # Install package +alias dnfri='sudo dnf reinstall' # Reinstall package +alias dnfgi="sudo dnf groupinstall" # Install package group +alias dnfr="sudo dnf remove" # Remove package +alias dnfgr="sudo dnf groupremove" # Remove package group +alias dnfc="sudo dnf clean all" # Clean cache diff --git a/aliases/available/git.aliases.bash b/aliases/available/git.aliases.bash index a46b44fa..bcb3887d 100644 --- a/aliases/available/git.aliases.bash +++ b/aliases/available/git.aliases.bash @@ -1,137 +1,197 @@ +# shellcheck shell=bash cite 'about-alias' about-alias 'common git abbreviations' -# Aliases -alias gcl='git clone' -alias ga='git add' -alias grm='git rm' -alias gap='git add -p' -alias gall='git add -A' -alias gf='git fetch --all --prune' -alias gft='git fetch --all --prune --tags' -alias gfv='git fetch --all --prune --verbose' -alias gftv='git fetch --all --prune --tags --verbose' -alias gus='git reset HEAD' -alias gpristine='git reset --hard && git clean -dfx' -alias gclean='git clean -fd' -alias gm="git merge" -alias gmv='git mv' alias g='git' alias get='git' -alias gs='git status' -alias gss='git status -s' -alias gsu='git submodule update --init --recursive' -alias gl='git pull' -alias gpl='git pull' -alias glum='git pull upstream master' -alias gpr='git pull --rebase' -alias gpp='git pull && git push' -alias gup='git fetch && git rebase' -alias gp='git push' -alias gpd='git push --delete' -alias gpo='git push origin HEAD' -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' -alias gra='git remote add' -alias grb='git rebase' -alias grm='git rebase master' -alias grmi='git rebase master -i' + +# add +alias ga='git add' +alias gall='git add -A' +alias gap='git add -p' + +# branch +alias gb='git branch' +alias gbD='git branch -D' +alias gba='git branch -a' +alias gbd='git branch -d' +alias gbm='git branch -m' +alias gbt='git branch --track' +alias gdel='git branch -D' + +# for-each-ref +alias gbc='git for-each-ref --format="%(authorname) %09 %(if)%(HEAD)%(then)*%(else)%(refname:short)%(end) %09 %(creatordate)" refs/remotes/ --sort=authorname DESC' # FROM https://stackoverflow.com/a/58623139/10362396 + +# commit +alias gc='git commit -v' +alias gca='git commit -v -a' +alias gcaa='git commit -a --amend -C HEAD' # Add uncommitted and unstaged changes to the last commit +alias gcam='git commit -v -am' +alias gcamd='git commit --amend' +alias gcm='git commit -v -m' +alias gci='git commit --interactive' +alias gcsam='git commit -S -am' + +# checkout +alias gcb='git checkout -b' +alias gco='git checkout' +alias gcob='git checkout -b' +alias gcobu='git checkout -b ${USER}/' +alias gcom='git checkout master' +alias gcpd='git checkout master; git pull; git branch -D' +alias gct='git checkout --track' + +# clone +alias gcl='git clone' + +# clean +alias gclean='git clean -fd' + +# cherry-pick +alias gcp='git cherry-pick' +alias gcpx='git cherry-pick -x' + +# diff alias gd='git diff' alias gds='git diff --staged' alias gdt='git difftool' -alias gdv='git diff -w "$@" | vim -R -' -alias gc='git commit -v' -alias gca='git commit -v -a' -alias gcm='git commit -v -m' -alias gcam="git commit -v -am" -alias gci='git commit --interactive' -alias gcamd='git commit --amend' -alias gb='git branch' -alias gba='git branch -a' -# FROM https://stackoverflow.com/a/58623139/10362396 -alias gbc='git for-each-ref --format="%(authorname) %09 %(if)%(HEAD)%(then)*%(else)%(refname:short)%(end) %09 %(creatordate)" refs/remotes/ --sort=authorname DESC' -alias gbt='git branch --track' -alias gbm='git branch -m' -alias gbd='git branch -d' -alias gbD='git branch -D' -alias gcount='git shortlog -sn' -alias gcp='git cherry-pick' -alias gcpx='git cherry-pick -x' -alias gco='git checkout' -alias gcom='git checkout master' -alias gcb='git checkout -b' -alias gcob='git checkout -b' -alias gcobu='git checkout -b ${USER}/' -alias gct='git checkout --track' -alias gcpd='git checkout master; git pull; git branch -D' -alias gexport='git archive --format zip --output' -alias gdel='git branch -D' -alias gmu='git fetch origin -v; git fetch upstream -v; git merge upstream/master' -alias gll='git log --graph --pretty=oneline --abbrev-commit' -alias gg="git log --graph --pretty=format:'%C(bold)%h%Creset%C(magenta)%d%Creset %s %C(yellow)<%an> %C(cyan)(%cr)%Creset' --abbrev-commit --date=relative" -alias ggf="git log --graph --date=short --pretty=format:'%C(auto)%h %Cgreen%an%Creset %Cblue%cd%Creset %C(auto)%d %s'" -alias ggs="gg --stat" -alias gsh="git show" -alias gsl="git shortlog -sn" -alias gwc="git whatchanged" -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}" -# Add uncommitted and unstaged changes to the last commit -alias gcaa="git commit -a --amend -C HEAD" -# Rebase with latest remote master -alias gprom="git fetch origin master && git rebase origin/master && git update-ref refs/heads/master origin/master" -alias gpf="git push --force" -alias gpunch="git push --force-with-lease" -alias ggui="git gui" -alias gcsam="git commit -S -am" -# Stash aliases -alias gst="git stash" -alias gstb="git stash branch" -alias gstd="git stash drop" -alias gstl="git stash list" -# Push introduced in git v2.13.2 -alias gstpu="git stash push" -alias gstpum="git stash push -m" -# Save deprecated since git v2.16.0 -# - aliases now resolve to push -alias gsts="git stash push" -alias gstsm="git stash push -m" -# Alias gstpo added for symmetry with gstpu (push) -# - gstp remains as alias for pop due to long-standing usage -alias gstpo="git stash pop" -alias gstp="git stash pop" -# Switch aliases - Requires git v2.23+ -alias gsw="git switch" -alias gswm="git switch master" -alias gswc="git switch --create" -alias gswt="git switch --track" -# Git home -alias ghm='cd "$(git rev-parse --show-toplevel)"' -if ! _command_exists gh; then - alias gh='ghm' -fi -# Show untracked files -alias gu='git ls-files . --exclude-standard --others' -# Git SVN -alias gsr='git svn rebase' +# archive +alias gexport='git archive --format zip --output' + +# fetch +alias gf='git fetch --all --prune' +alias gft='git fetch --all --prune --tags' +alias gftv='git fetch --all --prune --tags --verbose' +alias gfv='git fetch --all --prune --verbose' +alias gmu='git fetch origin -v; git fetch upstream -v; git merge upstream/master' +alias gup='git fetch && git rebase' + +# log +alias gg='git log --graph --pretty=format:'\''%C(bold)%h%Creset%C(magenta)%d%Creset %s %C(yellow)<%an> %C(cyan)(%cr)%Creset'\'' --abbrev-commit --date=relative' +alias ggf='git log --graph --date=short --pretty=format:'\''%C(auto)%h %Cgreen%an%Creset %Cblue%cd%Creset %C(auto)%d %s'\''' +alias ggs='gg --stat' +alias gll='git log --graph --pretty=oneline --abbrev-commit' +alias gnew='git log HEAD@{1}..HEAD@{0}' # Show commits since last pull, see http://blogs.atlassian.com/2014/10/advanced-git-aliases/ +alias gwc='git whatchanged' + +# ls-files +alias gu='git ls-files . --exclude-standard --others' # Show untracked files +alias glsut='gu' +alias glsum='git diff --name-only --diff-filter=U' # Show unmerged (conflicted) files + +# gui +alias ggui='git gui' + +# home +alias ghm='cd '\''$(git rev-parse --show-toplevel)'\''' # Git home +# appendage to ghm +if ! _command_exists gh; then + alias gh='ghm' +fi + +# merge +alias gm='git merge' + +# mv +alias gmv='git mv' + +# patch +alias gpatch='git format-patch -1' + +# push +alias gp='git push' +alias gpd='git push --delete' +alias gpf='git push --force' +alias gpo='git push origin HEAD' +alias gpom='git push origin master' +alias gpu='git push --set-upstream' +alias gpunch='git push --force-with-lease' +alias gpuo='git push --set-upstream origin' +alias gpuoc='git push --set-upstream origin $(git symbolic-ref --short HEAD)' + +# pull +alias gl='git pull' +alias glum='git pull upstream master' +alias gpl='git pull' +alias gpp='git pull && git push' +alias gpr='git pull --rebase' + +# remote +alias gr='git remote' +alias gra='git remote add' +alias grv='git remote -v' + +# rm +alias grm='git rm' + +# rebase +alias grb='git rebase' +alias grm='git rebase master' +alias grmi='git rebase master -i' +alias gprom='git fetch origin master && git rebase origin/master && git update-ref refs/heads/master origin/master' # Rebase with latest remote master + +# reset +alias gus='git reset HEAD' +alias gpristine='git reset --hard && git clean -dfx' + +# status +alias gs='git status' +alias gss='git status -s' + +# shortlog +alias gcount='git shortlog -sn' +alias gsl='git shortlog -sn' + +# show +alias gsh='git show' + +# svn alias gsd='git svn dcommit' +alias gsr='git svn rebase' # Git SVN + +# stash +alias gst='git stash' +alias gstb='git stash branch' +alias gstd='git stash drop' +alias gstl='git stash list' +alias gstp='git stash pop' # kept due to long-standing usage +alias gstpo='git stash pop' # recommended for it's symmetry with gstpu (push) + +## 'stash push' introduced in git v2.13.2 +alias gstpu='git stash push' +alias gstpum='git stash push -m' + +## 'stash save' deprecated since git v2.16.0, alias is now push +alias gsts='git stash push' +alias gstsm='git stash push -m' + +# submodules +alias gsu='git submodule update --init --recursive' + +# switch +# these aliases requires git v2.23+ +alias gsw='git switch' +alias gswc='git switch --create' +alias gswm='git switch master' +alias gswt='git switch --track' + +# tag +alias gt='git tag' +alias gta='git tag -a' +alias gtd='git tag -d' +alias gtl='git tag -l' case $OSTYPE in - darwin*) - alias gtls="git tag -l | gsort -V" - ;; - *) - alias gtls='git tag -l | sort -V' - ;; + darwin*) + alias gtls="git tag -l | gsort -V" + ;; + *) + alias gtls='git tag -l | sort -V' + ;; esac + +# functions +function gdv() { + git diff --ignore-all-space "$@" | vim -R - +} diff --git a/aliases/available/vim.aliases.bash b/aliases/available/vim.aliases.bash index 2ad1e99c..d19057d0 100644 --- a/aliases/available/vim.aliases.bash +++ b/aliases/available/vim.aliases.bash @@ -1,3 +1,4 @@ +# shellcheck shell=bash cite 'about-alias' about-alias 'vim abbreviations' @@ -5,15 +6,20 @@ VIM=$(command -v vim) GVIM=$(command -v gvim) MVIM=$(command -v mvim) -[[ -n $VIM ]] && alias v=$VIM +if [[ -n $VIM ]]; then + alias v='$VIM' + # open the vim help in fullscreen incorporated from + # https://stackoverflow.com/a/4687513 + alias vimh='${VIM} -c ":h | only"' +fi # open vim in new tab is taken from # http://stackoverflow.com/questions/936501/let-gvim-always-run-a-single-instancek case $OSTYPE in - darwin*) - [[ -n $MVIM ]] && function mvimt { command mvim --remote-tab-silent "$@" || command mvim "$@"; } - ;; - *) - [[ -n $GVIM ]] && function gvimt { command gvim --remote-tab-silent "$@" || command gvim "$@"; } - ;; + darwin*) + [[ -n $MVIM ]] && function mvimt { command mvim --remote-tab-silent "$@" || command mvim "$@"; } + ;; + *) + [[ -n $GVIM ]] && function gvimt { command gvim --remote-tab-silent "$@" || command gvim "$@"; } + ;; esac diff --git a/bash_it.sh b/bash_it.sh index 310aae42..a7960c75 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -74,6 +74,9 @@ if [[ ! -z "${BASH_IT_THEME}" ]]; then BASH_IT_LOG_PREFIX="themes: p4helpers: " # shellcheck source=./themes/p4helpers.theme.bash source "${BASH_IT}/themes/p4helpers.theme.bash" + BASH_IT_LOG_PREFIX="themes: command_duration: " + # shellcheck source=./themes/command_duration.theme.bash + source "${BASH_IT}/themes/command_duration.theme.bash" BASH_IT_LOG_PREFIX="themes: base: " # shellcheck source=./themes/base.theme.bash source "${BASH_IT}/themes/base.theme.bash" diff --git a/clean_files.txt b/clean_files.txt index 8c4e5926..f94b2dca 100644 --- a/clean_files.txt +++ b/clean_files.txt @@ -17,20 +17,45 @@ # root directories # docs +hooks # root files # .gitattributes lint_clean_files.sh +# plugins +# +plugins/available/history.plugin.bash +plugins/available/history-search.plugin.bash +plugins/available/history-substring-search.plugin.bash + # themes # +themes/agnoster themes/90210 themes/powerline +themes/barbuk +themes/atomic +themes/axin +themes/base.theme.bash + +# plugins +# +plugins/available/basher.plugin.bash # completions # completion/available/cargo.completion.bash completion/available/knife.completion.bash +completion/available/packer.completion.bash completion/available/pipx.completion.bash completion/available/rustup.completion.bash +completion/available/vault.completion.bash +completion/available/sdkman.completion.bash + +# aliases +# +aliases/available/dnf.aliases.bash +aliases/available/vim.aliases.bash +aliases/available/git.aliases.bash diff --git a/completion/available/apm.completion.bash b/completion/available/apm.completion.bash index a0a4e13c..c9940743 100644 --- a/completion/available/apm.completion.bash +++ b/completion/available/apm.completion.bash @@ -1,6 +1,27 @@ #!/usr/bin/env bash -# apm-bash-completion is written by Ugur Ozyilmazel +# The MIT License (MIT) + +# Copyright (c) 2015 Uğur "vigo" Özyılmazel + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + # repo: https://github.com/vigo/apm-bash-completion __apm(){ diff --git a/completion/available/bundler.completion.bash b/completion/available/bundler.completion.bash index 4ad04bdc..663a26d2 100644 --- a/completion/available/bundler.completion.bash +++ b/completion/available/bundler.completion.bash @@ -1,9 +1,28 @@ #! bash # bash completion for the `bundle` command. # -# Copyright (c) 2011-2017 Daniel Luz . -# Distributed under the MIT license. -# http://mernen.com/projects/completion-ruby +# Copyright (c) 2008 Daniel Luz + +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. # # To use, source this file on bash: # . completion-bundle diff --git a/completion/available/cargo.completion.bash b/completion/available/cargo.completion.bash index 46b399e4..d276ee72 100644 --- a/completion/available/cargo.completion.bash +++ b/completion/available/cargo.completion.bash @@ -1,5 +1,4 @@ -#!/usr/bin/env bash - +# shellcheck shell=bash # cargo (Rust package manager) completion if _binary_exists rustup && _binary_exists cargo; then diff --git a/completion/available/django.completion.bash b/completion/available/django.completion.bash index aca13ce4..cfd1ae9c 100644 --- a/completion/available/django.completion.bash +++ b/completion/available/django.completion.bash @@ -30,6 +30,36 @@ # ============ # # To uninstall, just remove the line from your .bash_profile and .bashrc. +# +# This file is licensed under the following license: +# Copyright (c) Django Software Foundation and individual contributors. +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. + +# 3. Neither the name of Django nor the names of its contributors may be used +# to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + _django_completion() { diff --git a/completion/available/docker-compose.completion.bash b/completion/available/docker-compose.completion.bash index 941f25a3..bf2c13fb 100644 --- a/completion/available/docker-compose.completion.bash +++ b/completion/available/docker-compose.completion.bash @@ -1,5 +1,20 @@ #!/bin/bash # + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) 2014 Docker, Inc + # bash completion for docker-compose # # This work is based on the completion for the docker command. diff --git a/completion/available/docker-machine.completion.bash b/completion/available/docker-machine.completion.bash index 07d39d1e..677412ba 100644 --- a/completion/available/docker-machine.completion.bash +++ b/completion/available/docker-machine.completion.bash @@ -1,5 +1,20 @@ # # bash completion file for docker-machine commands + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) 2014 Docker, Inc + # # This script provides completion of: # - commands and their options diff --git a/completion/available/drush.completion.bash b/completion/available/drush.completion.bash index 4f3f784f..1437dc66 100644 --- a/completion/available/drush.completion.bash +++ b/completion/available/drush.completion.bash @@ -1,37 +1,2 @@ -#!/usr/bin/env bash -# -# bash completion support for Drush: -# https://github.com/drush-ops/drush -# -# Originally from: -# http://github.com/drush-ops/drush/blob/master/drush.complete.sh - -# Ensure drush is available. -which drush &> /dev/null || alias drush &> /dev/null || return - -__drush_ps1() { - f="${TMPDIR:-/tmp/}/drush-env/drush-drupal-site-$$" - if [ -f $f ] - then - __DRUPAL_SITE=$(cat "$f") - else - __DRUPAL_SITE="$DRUPAL_SITE" - fi - - [[ -n "$__DRUPAL_SITE" ]] && printf "${1:- (%s)}" "$__DRUPAL_SITE" -} - -# Completion function, uses the "drush complete" command to retrieve -# completions for a specific command line COMP_WORDS. -_drush_completion() { - # Set IFS to newline (locally), since we only use newline separators, and - # need to retain spaces (or not) after completions. - local IFS=$'\n' - # The '< /dev/null' is a work around for a bug in php libedit stdin handling. - # Note that libedit in place of libreadline in some distributions. See: - # https://bugs.launchpad.net/ubuntu/+source/php5/+bug/322214 - COMPREPLY=( $(drush --early=includes/complete.inc "${COMP_WORDS[@]}" < /dev/null 2> /dev/null) ) -} - -# Register our completion function. We include common short aliases for Drush. -complete -o bashdefault -o default -o nospace -F _drush_completion d dr drush drush5 drush6 drush6 drush.php +_log_error 'Bash completion for "drush" is now deprecated, as it used code with incompatible license. +Please disable this completion and use the instructions from "drush" developers instead.' diff --git a/completion/available/gradle.completion.bash b/completion/available/gradle.completion.bash index d3ce6eb5..2b33383f 100644 --- a/completion/available/gradle.completion.bash +++ b/completion/available/gradle.completion.bash @@ -1,3 +1,23 @@ +# Copyright (c) 2017 Eric Wendelin + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + # Bash breaks words on : by default. Subproject tasks have ':' # Avoid inaccurate completions for subproject tasks COMP_WORDBREAKS=$(echo "$COMP_WORDBREAKS" | sed -e 's/://g') diff --git a/completion/available/grunt.completion.bash b/completion/available/grunt.completion.bash index 99a96b5b..e655c4ee 100644 --- a/completion/available/grunt.completion.bash +++ b/completion/available/grunt.completion.bash @@ -3,9 +3,35 @@ # grunt-cli # http://gruntjs.com/ # -# Copyright (c) 2012 Tyler Kellen, contributors -# Licensed under the MIT license. -# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT +# Copyright jQuery Foundation and other contributors, https://jquery.org/ + +# This software consists of voluntary contributions made by many +# individuals. For exact contribution history, see the revision history +# available at https://github.com/gruntjs/grunt . + +# The following license applies to all parts of this software except as +# documented below: + +# ==== + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Usage: # diff --git a/completion/available/gulp.completion.bash b/completion/available/gulp.completion.bash index 17e91765..91e28764 100644 --- a/completion/available/gulp.completion.bash +++ b/completion/available/gulp.completion.bash @@ -2,9 +2,36 @@ # Borrowed from grunt-cli # http://gruntjs.com/ # -# Copyright (c) 2012 Tyler Kellen, contributors -# Licensed under the MIT license. -# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT +# Copyright jQuery Foundation and other contributors, https://jquery.org/ + +# This software consists of voluntary contributions made by many +# individuals. For exact contribution history, see the revision history +# available at https://github.com/gruntjs/grunt . + +# The following license applies to all parts of this software except as +# documented below: + +# ==== + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + # Usage: # # To enable bash completion for gulp, add the following line (minus the diff --git a/completion/available/homesick.completion.bash b/completion/available/homesick.completion.bash index 31104f5b..49ff4d37 100644 --- a/completion/available/homesick.completion.bash +++ b/completion/available/homesick.completion.bash @@ -1,59 +1,2 @@ -# Bash completion script for homesick -# -# The homebrew bash completion script was used as inspiration. -# Originally from https://github.com/liborw/homesick-completion - -_homesick_complete() -{ - local cur="${COMP_WORDS[COMP_CWORD]}" - local options="--skip --force --pretend --quiet" - local actions="cd clone commit destroy diff generate help list open pull push rc show_path status symlink track unlink version" - local repos=$(\ls ~/.homesick/repos) - - # Subcommand list - [[ ${COMP_CWORD} -eq 1 ]] && { - COMPREPLY=( $(compgen -W "${options} ${actions}" -- ${cur}) ) - return - } - - # Find the first non-switch word - local prev_index=1 - local prev="${COMP_WORDS[prev_index]}" - while [[ $prev == -* ]]; do - prev_index=$((++prev_index)) - prev="${COMP_WORDS[prev_index]}" - done - - # Find the number of non-"--" commands - local num=0 - for word in ${COMP_WORDS[@]} - do - if [[ $word != -* ]]; then - num=$((++num)) - fi - done - - case "$prev" in - # Commands that take a castle - cd|commit|destroy|diff|open|pull|push|rc|show_path|status|symlink|unlink) - COMPREPLY=( $(compgen -W "${repos}" -- ${cur}) ) - return - ;; - # Commands that take command - help) - COMPREPLY=( $(compgen -W "${actions}" -- ${cur}) ) - return - ;; - # Track command take file and repo - track) - if [[ "$num" -eq 2 ]]; then - COMPREPLY=( $(compgen -X -f ${cur}) ) - elif [[ "$num" -ge 3 ]]; then - COMPREPLY=( $(compgen -W "${repos}" -- ${cur}) ) - fi - return - ;; - esac -} - -complete -o bashdefault -o default -F _homesick_complete homesick +_log_error 'Bash completion for "homesick" is now deprecated, as it used unlicensed code. +Please disable this completion and use the instructions from "homesick" bash completion developers instead.' diff --git a/completion/available/hub.completion.bash b/completion/available/hub.completion.bash index 8653084c..79d76bf0 100644 --- a/completion/available/hub.completion.bash +++ b/completion/available/hub.completion.bash @@ -1,6 +1,27 @@ # hub tab-completion script for bash. # This script complements the completion script that ships with git. +# Copyright (c) 2009 Chris Wanstrath + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + # If there is no git tab completion, but we have the _completion loader try to load it if ! declare -F _git > /dev/null && declare -F _completion_loader > /dev/null; then _completion_loader git diff --git a/completion/available/invoke.completion.bash b/completion/available/invoke.completion.bash index f90097f2..708596b4 100644 --- a/completion/available/invoke.completion.bash +++ b/completion/available/invoke.completion.bash @@ -1,4 +1,28 @@ # Invoke (pyinvoke.org) tab-completion script to be sourced with Bash shell. + +# Copyright (c) 2020 Jeff Forcier. +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # https://github.com/pyinvoke/invoke/blob/master/completion/bash _complete_invoke() { diff --git a/completion/available/jboss7.completion.bash b/completion/available/jboss7.completion.bash index 0bb44f15..4479b45a 100644 --- a/completion/available/jboss7.completion.bash +++ b/completion/available/jboss7.completion.bash @@ -3,8 +3,27 @@ # DATE: 2012-10-30 # rparree-at-edc4it-dot-com +# MIT License +# Copyright (c) 2020 Raphael Parree +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. _serverProfiles(){ if [[ $COMP_WORDS == *standalone.sh* ]] diff --git a/completion/available/knife.completion.bash b/completion/available/knife.completion.bash index cf050e36..83b332f9 100644 --- a/completion/available/knife.completion.bash +++ b/completion/available/knife.completion.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # Published originally as public domain code at https://github.com/wk8/knife-bash-autocomplete diff --git a/completion/available/packer.completion.bash b/completion/available/packer.completion.bash index fb940c9b..2301f0f2 100644 --- a/completion/available/packer.completion.bash +++ b/completion/available/packer.completion.bash @@ -1,163 +1,7 @@ -#!/usr/bin/env bash +# shellcheck shell=bash +cite "about-completion" +about-completion "packer completion" -# Packer (http://www.packer.io) bash completion -# -# This script provides bash completion for packer and supports: -# -# - template filename completion (*.json) in cwd -# - support for basic options (i.e.. -debug) -# - support for complex options (i.e. -parallel=[true|false] -# -# The scirpt has been successfully tested with packer-0.6.0 and the -# following OS: -# -# - OS X 10.9 -# - CentOS-6.5 -# - Ubuntu 12.04 Server -# -# The script technically is heavily inspired by the git-completion.bash -# script. Kudos to Shawn O. Pearce and all other -# contributors for the inspiration and especially to the bash-completion -# team in general. -# -# Copyright (c) 2014 IT Services Department, University of Bern -# -# This script is licensed under the MIT License (MIT) -# For licsense details see the LICENSE file included in the repository -# or read the license text at http://opensource.org/licenses/MIT. -# - -# Generates completion reply, appending a space to possible completion words, -# if necessary. -# It accepts 2 arguments though the second is optional: -# 1: List of possible completion words. -# 2: Generate possible completion matches for this word (optional). -__packercomp () -{ - local cur_="${2-$cur}" - - case "$cur_" in - -*=) - ;; - *) - local c i=0 IFS=$' \t\n' - for c in $1; do - if [[ $c == "$cur_"* ]]; then - case $c in - -*=*|*.) ;; - *) c="$c " ;; - esac - COMPREPLY[i++]="$c" - fi - done - ;; - esac -} - -# Generates completion reply for template files in cwd. -__packercomp_template_file () -{ - local IFS=$'\n' - - COMPREPLY=($(compgen -S " " -A file -X '!*.json' -- "${cur}")) -} - -# Generates completion for the build command. -__packer_build () -{ - local builders=" - amazon-ebs amazon-instance amazon-chroot digitalocean docker - googlecompute openstack parallels-iso parallels-pvm qemu - virtualbox-iso virtualbox-ovf vmware-iso vmware-vmx" - - case "$cur" in - -parallel=*) - __packercomp "false true" "${cur##-parallel=}" - return - ;; - -except=*) - __packercomp "$builders" "${cur##-except=}" - return - ;; - -only=*) - __packercomp "$builders" "${cur##-only=}" - return - ;; - -*) - __packercomp "-debug -force -machine-readable -except= -only= -parallel= -var -var-file" - return - ;; - *) - esac - - __packercomp_template_file -} - -# Generates completion for the fix command. -__packer_fix () -{ - __packercomp_template_file -} - -# Generates completion for the inspect command. -__packer_inspect () -{ - case "$cur" in - -*) - __packercomp "-machine-readable" - return - ;; - *) - esac - - __packercomp_template_file -} - -# Generates completion for the validate command. -__packer_validate () -{ - __packercomp_template_file -} - -# Main function for packer completion. -# -# Searches for a command in $COMP_WORDS. If one is found -# the appropriate function from above is called, if not -# completion for global options is done. -_packer_completion () -{ - cur=${COMP_WORDS[COMP_CWORD]} - # Words containing an equal sign get split into tokens in bash > 4, which - # doesn't come in handy here. - # This is handled here. bash < 4 does not split. - declare -f _get_comp_words_by_ref >/dev/null && _get_comp_words_by_ref -n = cur - - COMPREPLY=() - local i c=1 command - - while [ $c -lt $COMP_CWORD ]; do - i="${COMP_WORDS[c]}" - case "$i" in - -*) ;; - *) command="$i"; break ;; - esac - ((c++)) - done - - if [ -z $command ]; then - case "$cur" in - '-'*) - __packercomp "-machine-readable --help --version" - ;; - *) - __packercomp "build fix inspect validate" - ;; - esac - return - fi - - local completion_func="__packer_${command}" - declare -f $completion_func >/dev/null && $completion_func -} - -complete -o nospace -F _packer_completion packer +if _binary_exists packer; then + complete -C packer packer +fi diff --git a/completion/available/pipx.completion.bash b/completion/available/pipx.completion.bash index 9e34f076..16fd844d 100644 --- a/completion/available/pipx.completion.bash +++ b/completion/available/pipx.completion.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # pipx completion if _command_exists register-python-argcomplete && _command_exists pipx; then diff --git a/completion/available/rustup.completion.bash b/completion/available/rustup.completion.bash index 96822031..1cf8bc95 100644 --- a/completion/available/rustup.completion.bash +++ b/completion/available/rustup.completion.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # rustup (Rust toolchain installer) completion diff --git a/completion/available/salt.completion.bash b/completion/available/salt.completion.bash index de493af9..03595f9f 100644 --- a/completion/available/salt.completion.bash +++ b/completion/available/salt.completion.bash @@ -1,3 +1,18 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) 2020 SaltStack Team + +# Original Author: # written by David Pravec # - feel free to /msg alekibango on IRC if you want to talk about this file diff --git a/completion/available/sdkman.completion.bash b/completion/available/sdkman.completion.bash index b4d62da1..7f0157f3 100644 --- a/completion/available/sdkman.completion.bash +++ b/completion/available/sdkman.completion.bash @@ -1,71 +1,83 @@ -_sdkman_complete() -{ - local CANDIDATES - local CANDIDATE_VERSIONS +# shellcheck shell=bash +_sdkman_complete() { + local CANDIDATES + local CANDIDATE_VERSIONS - COMPREPLY=() + COMPREPLY=() - if [ $COMP_CWORD -eq 1 ]; then - COMPREPLY=( $(compgen -W "install uninstall rm list ls use current outdated version default selfupdate broadcast offline help flush" -- ${COMP_WORDS[COMP_CWORD]}) ) - elif [ $COMP_CWORD -eq 2 ]; then - case "${COMP_WORDS[COMP_CWORD-1]}" in - "install" | "uninstall" | "rm" | "list" | "ls" | "use" | "current" | "outdated" ) - CANDIDATES=$(echo "${SDKMAN_CANDIDATES_CSV}" | tr ',' ' ') - COMPREPLY=( $(compgen -W "$CANDIDATES" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - "offline" ) - COMPREPLY=( $(compgen -W "enable disable" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - "selfupdate" ) - COMPREPLY=( $(compgen -W "force" -P "[" -S "]" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - "flush" ) - COMPREPLY=( $(compgen -W "candidates broadcast archives temp" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - *) - ;; - esac - elif [ $COMP_CWORD -eq 3 ]; then - case "${COMP_WORDS[COMP_CWORD-2]}" in - "uninstall" | "rm" | "use" | "default" ) - _sdkman_candidate_versions ${COMP_WORDS[COMP_CWORD-1]} - COMPREPLY=( $(compgen -W "$CANDIDATE_VERSIONS" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - "install") - _sdkman_candidate_not_installed_versions ${COMP_WORDS[COMP_CWORD-1]} - COMPREPLY=( $(compgen -W "$CANDIDATE_VERSIONS" -- ${COMP_WORDS[COMP_CWORD]}) ) - ;; - *) - ;; - esac - fi + if [ "$COMP_CWORD" -eq 1 ]; then + mapfile -t COMPREPLY < <(compgen -W "install uninstall rm list ls use default home env current upgrade ug version broadcast help offline selfupdate update flush" -- "${COMP_WORDS[COMP_CWORD]}") + elif [ "$COMP_CWORD" -eq 2 ]; then + case "${COMP_WORDS[COMP_CWORD - 1]}" in + "install" | "i" | "uninstall" | "rm" | "list" | "ls" | "use" | "u" | "default" | "d" | "home" | "h" | "current" | "c" | "upgrade" | "ug") + CANDIDATES=$(echo "${SDKMAN_CANDIDATES_CSV}" | tr ',' ' ') + mapfile -t COMPREPLY < <(compgen -W "$CANDIDATES" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + "env") + mapfile -t COMPREPLY < <(compgen -W "init" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + "offline") + mapfile -t COMPREPLY < <(compgen -W "enable disable" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + "selfupdate") + mapfile -t COMPREPLY < <(compgen -W "force" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + "flush") + mapfile -t COMPREPLY < <(compgen -W "archives tmp broadcast version" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + *) ;; - return 0 + esac + elif [ "$COMP_CWORD" -eq 3 ]; then + case "${COMP_WORDS[COMP_CWORD - 2]}" in + "uninstall" | "rm" | "use" | "u" | "default" | "d" | "home" | "h") + _sdkman_candidate_local_versions "${COMP_WORDS[COMP_CWORD - 1]}" + mapfile -t COMPREPLY < <(compgen -W "$CANDIDATE_VERSIONS" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + "install" | "i") + _sdkman_candidate_all_versions "${COMP_WORDS[COMP_CWORD - 1]}" + mapfile -t COMPREPLY < <(compgen -W "$CANDIDATE_VERSIONS" -- "${COMP_WORDS[COMP_CWORD]}") + ;; + *) ;; + + esac + fi + + return 0 } -_sdkman_candidate_versions(){ +_sdkman_candidate_local_versions() { - CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions $1) - if [ "$SDKMAN_OFFLINE_MODE" = "true" ]; then - CANDIDATE_VERSIONS=$CANDIDATE_LOCAL_VERSIONS - else - CANDIDATE_ONLINE_VERSIONS="$(curl -s "${SDKMAN_SERVICE}/candidates/$1" | tr ',' ' ')" - CANDIDATE_VERSIONS="$(echo $CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS |sort | uniq ) " - fi + CANDIDATE_VERSIONS=$(__sdkman_cleanup_local_versions "$1") } -_sdkman_candidate_not_installed_versions(){ - CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions $1) - if [ "$SDKMAN_OFFLINE_MODE" = "false" ]; then - CANDIDATE_ONLINE_VERSIONS="$(__sdkman_list_versions $1 | grep " " | grep "\." | cut -c 6-)" - CANDIDATE_VERSIONS="$(echo $CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS | tr ' ' '\n' | sort | uniq -u) " - fi +_sdkman_candidate_all_versions() { + + candidate="$1" + CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions "$candidate") + if [ "$SDKMAN_OFFLINE_MODE" = "true" ]; then + CANDIDATE_VERSIONS=$CANDIDATE_LOCAL_VERSIONS + else + # sdkman has a specific output format for Java candidate since + # there are multiple vendors and builds. + if [ "$candidate" = "java" ]; then + CANDIDATE_ONLINE_VERSIONS="$(__sdkman_list_versions "$candidate" | grep " " | grep "\." | cut -c 62-)" + else + CANDIDATE_ONLINE_VERSIONS="$(__sdkman_list_versions "$candidate" | grep " " | grep "\." | cut -c 6-)" + fi + # the last grep is used to filter out sdkman flags, such as: + # "+" - local version + # "*" - installed + # ">" - currently in use + CANDIDATE_VERSIONS="$(echo "$CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS" | tr ' ' '\n' | grep -v -e '^[[:space:]|\*|\>|\+]*$' | sort | uniq -u) " + fi + } -__sdkman_cleanup_local_versions(){ +__sdkman_cleanup_local_versions() { - __sdkman_build_version_csv $1 | tr ',' ' ' + __sdkman_build_version_csv "$1" | tr ',' ' ' } diff --git a/completion/available/tmux.completion.bash b/completion/available/tmux.completion.bash index 6bb8293f..7992ccb4 100644 --- a/completion/available/tmux.completion.bash +++ b/completion/available/tmux.completion.bash @@ -3,7 +3,6 @@ # tmux completion # See: http://www.debian-administration.org/articles/317 for how to write more. # Usage: Put "source bash_completion_tmux.sh" into your .bashrc -# Based upon the example at http://paste-it.appspot.com/Pj4mLycDE _tmux_expand () { diff --git a/completion/available/todo.completion.bash b/completion/available/todo.completion.bash index 6e38c6f5..c2ec1b1f 100644 --- a/completion/available/todo.completion.bash +++ b/completion/available/todo.completion.bash @@ -1,70 +1,2 @@ -# link: https://github.com/ginatrapani/todo.txt-cli/blob/master/todo_completion - -_todo() -{ - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - local -r OPTS="-@ -@@ -+ -++ -d -f -h -p -P -PP -a -n -t -v -vv -V -x" - local -r COMMANDS="\ - add a addto addm append app archive command del \ - rm depri dp do help list ls listaddons listall lsa listcon \ - lsc listfile lf listpri lsp listproj lsprj move \ - mv prepend prep pri p replace report shorthelp" - local -r MOVE_COMMAND_PATTERN='^(move|mv)$' - - local _todo_sh=${_todo_sh:-todo.sh} - local completions - if [ $COMP_CWORD -eq 1 ]; then - completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons) $OPTS" - elif [[ $COMP_CWORD -gt 2 && ( \ - "${COMP_WORDS[COMP_CWORD-2]}" =~ $MOVE_COMMAND_PATTERN || \ - "${COMP_WORDS[COMP_CWORD-3]}" =~ $MOVE_COMMAND_PATTERN ) ]]; then - completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile) - else - case "$prev" in - command) - completions=$COMMANDS;; - help) - completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons)";; - addto|listfile|lf) - completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile);; - -*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons) $OPTS";; - *) case "$cur" in - +*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listproj) - COMPREPLY=( $( compgen -W "$completions" -- $cur )) - [ ${#COMPREPLY[@]} -gt 0 ] && return 0 - completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listproj) - ;; - @*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listcon) - COMPREPLY=( $( compgen -W "$completions" -- $cur )) - [ ${#COMPREPLY[@]} -gt 0 ] && return 0 - completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listcon) - ;; - *) if [[ "$cur" =~ ^[0-9]+$ ]]; then - local todo=$( \ - eval TODOTXT_VERBOSE=0 $_todo_sh '-@ -+ -p -x command ls "^ *${cur} "' | \ - sed -e 's/^ *[0-9]\{1,\} //' -e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/' \ - -e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/' \ - -e 's/[[:space:]]*$//' \ - -e '1q' \ - ) - [ "$todo" ] && COMPREPLY[0]="$cur # $todo" - return 0 - else - return 0 - fi - ;; - esac - ;; - esac - fi - - COMPREPLY=( $( compgen -W "$completions" -- $cur )) - return 0 -} - -complete -F _todo todo.sh -complete -F _todo t +_log_error 'Bash completion for "todo.txt-cli" is now deprecated, as it used code with incompatible license. +Please disable this completion and use the instructions from "todo.txt-cli" developers instead.' diff --git a/completion/available/vault.completion.bash b/completion/available/vault.completion.bash index f0c747c1..9520f166 100644 --- a/completion/available/vault.completion.bash +++ b/completion/available/vault.completion.bash @@ -1,51 +1,7 @@ -# --------------------------------------------------------------------------- -# vault-bash-completion -# -# This adds bash completions for [HashiCorp Vault](https://www.vaultproject.io/) -# -# see https://github.com/iljaweis/vault-bash-completion -# --------------------------------------------------------------------------- +# shellcheck shell=bash +cite "about-completion" +about-completion "vault completion" -function _vault_mounts() { - ( - set -euo pipefail - if ! vault mounts 2> /dev/null | awk 'NR > 1 {print $1}'; then - echo "secret" - fi - ) -} - -function _vault() { - local VAULT_COMMANDS=$(vault 2>&1 | egrep '^ +' | awk '{print $1}') - - local cur - local prev - - if [ $COMP_CWORD -gt 0 ]; then - cur=${COMP_WORDS[COMP_CWORD]} - prev=${COMP_WORDS[COMP_CWORD-1]} - fi - - local line=${COMP_LINE} - - if [[ $prev =~ ^(policies|policy-write|policy-delete) ]]; then - local policies=$(vault policies 2> /dev/null) - COMPREPLY=($(compgen -W "$policies" -- $cur)) - elif [ "$(echo $line | wc -w)" -le 2 ]; then - if [[ "$line" =~ ^vault\ (read|write|delete|list)\ $ ]]; then - COMPREPLY=($(compgen -W "$(_vault_mounts)" -- '')) - else - COMPREPLY=($(compgen -W "$VAULT_COMMANDS" -- $cur)) - fi - elif [[ "$line" =~ ^vault\ (read|write|delete|list)\ (.*)$ ]]; then - path=${BASH_REMATCH[2]} - if [[ "$path" =~ ^([^ ]+)/([^ /]*)$ ]]; then - list=$(vault list -format=yaml ${BASH_REMATCH[1]} 2> /dev/null | awk '{ print $2 }') - COMPREPLY=($(compgen -W "$list" -P "${BASH_REMATCH[1]}/" -- ${BASH_REMATCH[2]})) - else - COMPREPLY=($(compgen -W "$(_vault_mounts)" -- $path)) - fi - fi -} - -complete -o default -o nospace -F _vault vault +if _binary_exists vault; then + complete -C vault vault +fi diff --git a/completion/available/virsh.completion.bash b/completion/available/virsh.completion.bash index 4090a24a..f73f4b99 100644 --- a/completion/available/virsh.completion.bash +++ b/completion/available/virsh.completion.bash @@ -1,148 +1,2 @@ -#!/usr/bin/env bash -# bash completion for virsh - main CLI of libvirt - -# This script provides bash completion for virsh, -# borrowed from https://github.com/LuyaoHuang/virsh-bash-completion - - - -_contain_cmd() -{ - local e f - local array1=($1) array2=($2) - - for e in "${array1[@]}" - do - for f in "${array2[@]}" - do - if [[ "$e" == "$f" ]] ; then - echo $e - return - fi - done - done - - echo "notfound" - return -} - -_virsh_list_networks() -{ - local flag_all=$1 flags - - if [ "$flag_all" -eq 1 ]; then - flags="--all" - else - flags="--inactive" - fi - virsh -q net-list $flags | cut -d\ -f2 | awk '{print $1}' -} - -_virsh_list_domains() -{ - local flag_all=$1 flags - - if [ "$flag_all" -eq 1 ]; then - flags="--all" - else - flags="--inactive" - fi - virsh -q list $flags | cut -d\ -f7 | awk '{print $1}' -} - -_virsh_list_pools() -{ - local flag_all=$1 flags - - if [ "$flag_all" -eq 1 ]; then - flags="--all" - else - flags="--inactive" - fi - virsh -q pool-list $flags | cut -d\ -f2 | awk '{print $1}' -} - -_virsh_list_ifaces() -{ - local flag_all=$1 flags - - if [ "$flag_all" -eq 1 ]; then - flags="--all" - else - flags="--inactive" - fi - virsh -q iface-list $flags | cut -d\ -f2 | awk '{print $1}' -} - -_virsh_list_nwfilters() -{ - - virsh -q nwfilter-list | cut -d\ -f4 | awk '{print $1}' -} - -_virsh() -{ - local cur prev cmds doms options nets pools cmds_help - local flag_all=1 array ret a b ifaces nwfilters files - -# not must use bash-completion now :) -# _init_completion -s || return - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - cmds=$( echo "$(virsh -h| grep '^ ' | cut -d\ -f5)" \ - "$(virsh -h| grep '\--' | cut -d\ -f7 | cut -d= -f1)") - cmds_help=$(virsh help| grep '^ ' | cut -d\ -f5) - case "$prev" in - --domain) - doms=$(_virsh_list_domains "$flag_all") - COMPREPLY=( $(compgen -W "$doms" -- "$cur") ) - return 0 - ;; - --network) - nets=$(_virsh_list_networks "$flag_all") - COMPREPLY=( $(compgen -W "$nets" -- "$cur") ) - return 0 - ;; - --pool) - pools=$(_virsh_list_pools "$flag_all") - COMPREPLY=( $(compgen -W "$pools" -- "$cur") ) - return 0 - ;; - --interface) - ifaces=$(_virsh_list_ifaces "$flag_all") - COMPREPLY=( $(compgen -W "$ifaces" -- "$cur") ) - return 0 - ;; - --nwfilter) - nwfilters=$(_virsh_list_nwfilters) - COMPREPLY=( $(compgen -W "$nwfilters" -- "$cur") ) - return 0 - ;; - --file|--xml) - files=$(ls) - COMPREPLY=( $(compgen -W "$files" -- "$cur") ) - return 0 - ;; - esac - - array=$(IFS=$'\n'; echo "${COMP_WORDS[*]}") - ret=$(_contain_cmd "$array" "$cmds_help") - - if [[ "$ret" != "notfound" && "$ret" != "$cur" ]]; then - a=$(virsh help "$ret" |grep '^ --'|cut -d\ -f5) - b=$(virsh help "$ret" |grep '^ \[--'|cut -d\ -f5|cut -d[ -f2|cut -d] -f1) - options=$( echo $a $b ) - COMPREPLY=( $(compgen -W "$options" -- "$cur") ) - return 0 - fi - - case "$cur" in - *) - COMPREPLY=( $(compgen -W "$cmds" -- "$cur") ) - return 0 - ;; - esac -} && -complete -o default -F _virsh virsh +_log_error 'Bash completion for "virsh" is now deprecated, as it used code with incompatible license. +Please disable this completion and use the instructions from "virsh" developers instead.' diff --git a/completion/available/vuejs.completion.bash b/completion/available/vuejs.completion.bash index 69794785..78c277db 100644 --- a/completion/available/vuejs.completion.bash +++ b/completion/available/vuejs.completion.bash @@ -1,14 +1,48 @@ #!/usr/bin/bash -if command -v vue > /dev/null; then +if _command_exists vue; 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 + local prev=$(_get_pword) + local curr=$(_get_cword) + + case $prev in + create) + COMPREPLY=($(compgen -W "-p -d -i -m -r -g -n -f -c -x -b -h --help --preset --default --inilinePreset --packageManager --registry --git --no-git --force --merge --clone --proxy --bare --skipGetStarted" -- "$curr")) + ;; + add|invoke) + COMPREPLY=($(compgen -W "--registry -h --help" -- "$curr")) + ;; + inspect) + COMPREPLY=($(compgen -W "-v --help --verbose --mode --rule --plugin --plugins --rules" -- "$curr")) + ;; + serve) + COMPREPLY=($(compgen -W "-o -h --help --open -c --copy -p --port" -- "$curr")) + ;; + build) + COMPREPLY=($(compgen -W "-t --target -n --name -d --dest -h --help" -- "$curr")) + ;; + ui) + COMPREPLY=($(compgen -W "-H --host -p --port -D --dev --quiet --headless -h --help" -- "$curr")) + ;; + init) + COMPREPLY=($(compgen -W "-c --clone --offline -h --help" -- "$curr")) + ;; + config) + COMPREPLY=($(compgen -W "-g --get -s --set -d --delete -e --edit --json -h --help" -- "$curr")) + ;; + outdated) + COMPREPLY=($(compgen -W "--next -h --help" -- "$curr")) + ;; + upgrade) + COMPREPLY=($(compgen -W "-t --to -f --from -r --registry --all --next -h --help" -- "$curr")) + ;; + migrate) + COMPREPLY=($(compgen -W "-f --from -h --help" -- "$curr")) + ;; + *) + COMPREPLY=($(compgen -W "-h --help -v --version create add invoke inspect serve build ui init config outdated upgrade migrate info" -- "$curr")) + ;; + esac } complete -F __vuejs_completion vue diff --git a/docs/contributing.rst b/docs/contributing.rst index 0f0d1299..79d8ed1c 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -10,11 +10,6 @@ Issues ------ -* When opening a new issue in the issue tracker, please include information about which *Operating System* you're using, and which version of *Bash*. -* In many cases, it also makes sense to show which Bash-it plugins you are using. - This information can be obtained using ``bash-it show plugins``. -* If the issue happens while loading Bash-it, please also include your ``~/.bash_profile`` or ``~/.bashrc`` file, - as well as the install location of Bash-it (default should be ``~/.bash_it``\ ). * When reporting a bug or requesting a new feature, consider providing a Pull Request that fixes the issue or can be used as a starting point for the new feature. Don't be afraid, most things aren't that complex... @@ -42,6 +37,8 @@ Code Style * When changing existing files, consider also adding them into `clean_files.txt` and fixing the linting errors that arise. See :ref:`linting_your_changes` for more information. * Indentation is using tabs, not spaces. Most of the code is indented with 2 spaces, some with 4 spaced tabs. Please try to stick to tabs. If you're using an editor that supports `EditorConfig `_\ , the editor should automatically use the settings defined in Bash-it's `.editorconfig file <.editorconfig>`_. +* Prefer to invoke commands directly using the ``command`` shell builtin. This way, your code + will always execute the command you wanted and not an alias/function that overrides the name of the command. (For example, use ``command rm`` instead of ``rm``) * When creating new functions, please use a dash ("-") to separate the words of the function's name, e.g. ``my-new-function``. Don't use underscores, e.g. ``my_new_function``. * Internal functions that aren't to be used by the end user should start with an underscore, e.g. ``_my-new-internal-function``. @@ -59,8 +56,8 @@ Unit Tests When adding features or making changes/fixes, please run our growing unit test suite to ensure that you did not break existing functionality. The test suite does not cover all aspects of Bash-it, but please run it anyway to verify that you did not introduce any regression issues. -Any code pushed to GitHub as part of a Pull Request will automatically trigger a continuous integration build on `Travis CI `_\ , where the test suite is run on both Linux and macOS. -The Pull Request will then show the result of the Travis build, indicating whether all tests ran fine, or whether there were issues. +Any code pushed to GitHub as part of a Pull Request will automatically trigger a continuous integration build on `GitHub Actions `_\ , where the test suite is run on both Linux and macOS. +The Pull Request will then show the result of the CI build, indicating whether all tests ran fine, or whether there were issues. Please pay attention to this, Pull Requests with build issues will not be merged. Adding new functionality or changing existing functionality is a good opportunity to increase Bash-it's test coverage. diff --git a/docs/themes-list/barbuk.rst b/docs/themes-list/barbuk.rst index 5fe49048..15fb0ef5 100644 --- a/docs/themes-list/barbuk.rst +++ b/docs/themes-list/barbuk.rst @@ -38,6 +38,7 @@ Default theme glyphs BARBUK_SVN_CHAR='⑆ ' BARBUK_EXIT_CODE_ICON=' ' BARBUK_PYTHON_VENV_CHAR=' ' + BARBUK_COMMAND_DURATION_ICON='  ' Customize glyphs ^^^^^^^^^^^^^^^^ @@ -92,6 +93,11 @@ Please refer to the following documentation for more information: EOF chmod 400 /etc/sudoers.d/keepenv +Command duration +---------------- + +See :ref:`Command duration `. + Examples -------- @@ -122,3 +128,11 @@ Python venv .. code-block:: bash   flask ~/test on  master ✓ ❯ + +Command duration +^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + # sleep 3s + user@hostname in  ~/bash-it on  master ✓  3.2s ❯ diff --git a/docs/themes.rst b/docs/themes.rst index aa21a7e3..5b796389 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -37,6 +37,29 @@ See :ref:`here `. Theme Switches & Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _command_duration: + +Command duration +================ + +Prints last command duration + +Usage +##### + +Command duration can be enabled by exporting ``BASH_IT_COMMAND_DURATION``: + +.. code-block:: bash + + export BASH_IT_COMMAND_DURATION=true + +The default configuration display last command duration for command lasting one second or more. +You can customize the minimum time in seconds before command duration is displayed in your ``.bashrc``: + +.. code-block:: bash + + export COMMAND_DURATION_MIN_SECONDS=5 + Clock Related ============= diff --git a/hooks/dot-bash.sh b/hooks/dot-bash.sh new file mode 100755 index 00000000..7a9dc8bc --- /dev/null +++ b/hooks/dot-bash.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +exit_code=0 +for file in "$@"; do + # Confirm file is not executable + # + if [[ -x "${file}" ]]; then + echo "Bash include file \`${file}\` should not be executable" + exit_code=1 + fi + + # Confirm expected schellcheck header + # + LINE1="$(head -n 1 "${file}")" + if [[ "${LINE1}" != "# shellcheck shell=bash" ]]; then + echo "Bash include file \`${file}\` has bad/missing shellcheck header" + exit_code=1 + fi +done + +exit $exit_code diff --git a/hooks/dot-sh.sh b/hooks/dot-sh.sh new file mode 100755 index 00000000..3fa63216 --- /dev/null +++ b/hooks/dot-sh.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +exit_code=0 +for file in "$@"; do + # Confirm file is executable + # + if [[ ! -x "${file}" ]]; then + echo "Bash file \`${file}\` is not executable" + exit_code=1 + fi + + # Confirm expected #! header + # + LINE1="$(head -n 1 "${file}")" + if [[ "${LINE1}" != "#!/usr/bin/env bash" ]]; then + echo "Bash file \`${file}\` has bad/missing #! header" + exit_code=1 + fi +done + +exit $exit_code diff --git a/lib/helpers.bash b/lib/helpers.bash index 270a31b9..436fc59e 100644 --- a/lib/helpers.bash +++ b/lib/helpers.bash @@ -346,6 +346,11 @@ _bash-it-version() { BASH_IT_GIT_REMOTE=$(git remote get-url $BASH_IT_REMOTE) BASH_IT_GIT_URL=${BASH_IT_GIT_REMOTE%.git} + if [[ "$BASH_IT_GIT_URL" == *"git@"* ]]; then + # Fix URL in case it is ssh based URL + BASH_IT_GIT_URL=${BASH_IT_GIT_URL/://} + BASH_IT_GIT_URL=${BASH_IT_GIT_URL/git@/https://} + fi current_tag=$(git describe --exact-match --tags 2> /dev/null) diff --git a/lib/history.bash b/lib/history.bash deleted file mode 100644 index a1a7cb04..00000000 --- a/lib/history.bash +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# Bash History Handling - -shopt -s histappend # append to bash_history if Terminal.app quits -export HISTCONTROL=${HISTCONTROL:-ignorespace:erasedups} # erase duplicates; alternative option: export HISTCONTROL=ignoredups -export HISTSIZE=${HISTSIZE:-5000} # resize history size -export AUTOFEATURE=${AUTOFEATURE:-true autotest} # Cucumber / Autotest integration - -function rh { - history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head -} diff --git a/plugins/available/alias-completion.plugin.bash b/plugins/available/alias-completion.plugin.bash index 5e0ea7fe..b1f7c3cf 100644 --- a/plugins/available/alias-completion.plugin.bash +++ b/plugins/available/alias-completion.plugin.bash @@ -91,5 +91,5 @@ function alias_completion { echo "$new_completion" >> "$tmp_file" fi done < <(alias -p | sed -Ene "s/$alias_regex/\2 '\3' '\4'/p") - source "$tmp_file" && rm -f "$tmp_file" + source "$tmp_file" && command rm -f "$tmp_file" }; alias_completion diff --git a/plugins/available/basher.plugin.bash b/plugins/available/basher.plugin.bash new file mode 100644 index 00000000..2c77cbfa --- /dev/null +++ b/plugins/available/basher.plugin.bash @@ -0,0 +1,16 @@ +# shellcheck shell=bash +cite about-plugin +about-plugin 'initializes basher, the shell package manager' + +# https://github.com/basherpm/basher + +if ! _command_exists basher; then + if [[ -x "$HOME/.basher/bin/basher" ]]; then + pathmunge "$HOME/.basher/bin" + else + _log_warning 'basher not found' + return 0 + fi +fi + +eval "$(basher init - bash)" diff --git a/plugins/available/history-search.plugin.bash b/plugins/available/history-search.plugin.bash new file mode 100644 index 00000000..ea02eb74 --- /dev/null +++ b/plugins/available/history-search.plugin.bash @@ -0,0 +1,10 @@ +# shellcheck shell=bash +cite about-plugin +about-plugin 'search history using the prefix already entered' + +# enter a few characters and press UpArrow/DownArrow +# to search backwards/forwards through the history +if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then + bind '"\e[A":history-search-backward' + bind '"\e[B":history-search-forward' +fi diff --git a/plugins/available/history-substring-search.plugin.bash b/plugins/available/history-substring-search.plugin.bash new file mode 100644 index 00000000..e0e37f43 --- /dev/null +++ b/plugins/available/history-substring-search.plugin.bash @@ -0,0 +1,10 @@ +# shellcheck shell=bash +cite about-plugin +about-plugin 'search history using the substring already entered' + +# enter a few characters and press UpArrow/DownArrow +# to search backwards/forwards through the history +if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then + bind '"\e[A":history-substring-search-backward' + bind '"\e[B":history-substring-search-forward' +fi diff --git a/plugins/available/history.plugin.bash b/plugins/available/history.plugin.bash index 528548ef..08ca8de6 100644 --- a/plugins/available/history.plugin.bash +++ b/plugins/available/history.plugin.bash @@ -1,9 +1,39 @@ +# shellcheck shell=bash cite about-plugin -about-plugin 'history manipulation' -# enter a few characters and press UpArrow/DownArrow -# to search backwards/forwards through the history -if [[ ${SHELLOPTS} =~ (vi|emacs) ]] -then - bind '"":history-search-backward' - bind '"":history-search-forward' -fi +about-plugin 'improve history handling with sane defaults' + +# append to bash_history if Terminal.app quits +shopt -s histappend + +# erase duplicates; alternative option: export HISTCONTROL=ignoredups +export HISTCONTROL=${HISTCONTROL:-ignorespace:erasedups} + +# resize history to 100x the default (500) +export HISTSIZE=${HISTSIZE:-50000} + +top-history() { + about 'print the name and count of the most commonly run tools' + + if [[ -n $HISTTIMEFORMAT ]]; then + # To parse history we need a predictable format, which HISTTIMEFORMAT + # gets in the way of. So we unset it and set a trap to guarantee the + # user's environment returns to normal even if the pipeline below fails. + # shellcheck disable=SC2064 + trap "export HISTTIMEFORMAT='$HISTTIMEFORMAT'" RETURN + unset HISTTIMEFORMAT + fi + + history \ + | awk '{ + a[$2]++ + }END{ + for(i in a) + printf("%s\t%s\n", a[i], i) + }' \ + | sort --reverse --numeric-sort \ + | head \ + | column \ + --table \ + --table-columns 'Command Count,Command Name' \ + --output-separator ' | ' +} diff --git a/template/bash_profile.template.bash b/template/bash_profile.template.bash index 4a840df3..75febdab 100755 --- a/template/bash_profile.template.bash +++ b/template/bash_profile.template.bash @@ -51,6 +51,13 @@ export SCM_CHECK=true # Will otherwise fall back on $USER. #export SHORT_USER=${USER:0:8} +# If your theme use command duration, uncomment this to +# enable display of last command duration. +#export BASH_IT_COMMAND_DURATION=true +# You can choose the minimum time in seconds before +# command duration is displayed. +#export COMMAND_DURATION_MIN_SECONDS=1 + # Set Xterm/screen/Tmux title with shortened command and directory. # Uncomment this to set. #export SHORT_TERM_LINE=true diff --git a/test/plugins/alias-completion.plugin.bats b/test/plugins/alias-completion.plugin.bats index 76d4ed04..1a78e462 100644 --- a/test/plugins/alias-completion.plugin.bats +++ b/test/plugins/alias-completion.plugin.bats @@ -7,7 +7,7 @@ load ../../lib/helpers cite _about _param _example _group _author _version -load ../../completion/available/git.completion +load ../../completion/available/capistrano.completion @test "alias-completion: See that aliases with double quotes and brackets do not break the plugin" { alias gtest="git log --graph --pretty=format:'%C(bold)%h%Creset%C(magenta)%d%Creset %s %C(yellow)<%an> %C(cyan)(%cr)%Creset' --abbrev-commit --date=relative" @@ -22,3 +22,10 @@ load ../../completion/available/git.completion assert_success } + +@test "alias-completion: See that having aliased rm command does not output unnecessary output" { + alias rm='rm -v' + load ../../plugins/available/alias-completion.plugin + + refute_output +} diff --git a/themes/90210/90210.theme.bash b/themes/90210/90210.theme.bash index 97c23f0e..180764c8 100644 --- a/themes/90210/90210.theme.bash +++ b/themes/90210/90210.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash SCM_THEME_PROMPT_DIRTY=" ${red}✗" SCM_THEME_PROMPT_CLEAN=" ${bold_green}✓" SCM_THEME_PROMPT_PREFIX=" |" diff --git a/themes/agnoster/agnoster.theme.bash b/themes/agnoster/agnoster.theme.bash index 06f73c02..ba3e2c9a 100644 --- a/themes/agnoster/agnoster.theme.bash +++ b/themes/agnoster/agnoster.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # vim: ft=bash ts=2 sw=2 sts=2 # # agnoster's Theme - https://gist.github.com/3712874 @@ -70,9 +70,9 @@ PROMPT_DIRTRIM=2 # bash4 and above ###################################################################### DEBUG=0 debug() { - if [[ ${DEBUG} -ne 0 ]]; then - >&2 echo -e $* - fi + if [[ ${DEBUG} -ne 0 ]]; then + echo >&2 -e "$@" + fi } ###################################################################### @@ -87,178 +87,176 @@ LEFT_SUBSEG='' RIGHT_SUBSEG='' text_effect() { - case "$1" in - reset) echo 0;; - bold) echo 1;; - underline) echo 4;; - esac + case "$1" in + reset) echo 0 ;; + bold) echo 1 ;; + underline) echo 4 ;; + esac } # to add colors, see # http://bitmote.com/index.php?post/2012/11/19/Using-ANSI-Color-Codes-to-Colorize-Your-Bash-Prompt-on-Linux # under the "256 (8-bit) Colors" section, and follow the example for orange below fg_color() { - case "$1" in - black) echo 30;; - red) echo 31;; - green) echo 32;; - yellow) echo 33;; - blue) echo 34;; - magenta) echo 35;; - cyan) echo 36;; - white) echo 37;; - orange) echo 38\;5\;166;; - esac + case "$1" in + black) echo 30 ;; + red) echo 31 ;; + green) echo 32 ;; + yellow) echo 33 ;; + blue) echo 34 ;; + magenta) echo 35 ;; + cyan) echo 36 ;; + white) echo 37 ;; + orange) echo 38\;5\;166 ;; + esac } bg_color() { - case "$1" in - black) echo 40;; - red) echo 41;; - green) echo 42;; - yellow) echo 43;; - blue) echo 44;; - magenta) echo 45;; - cyan) echo 46;; - white) echo 47;; - orange) echo 48\;5\;166;; - esac; + case "$1" in + black) echo 40 ;; + red) echo 41 ;; + green) echo 42 ;; + yellow) echo 43 ;; + blue) echo 44 ;; + magenta) echo 45 ;; + cyan) echo 46 ;; + white) echo 47 ;; + orange) echo 48\;5\;166 ;; + esac } # TIL: declare is global not local, so best use a different name # for codes (mycodes) as otherwise it'll clobber the original. # this changes from BASH v3 to BASH v4. ansi() { - local seq - declare -a mycodes=("${!1}") + local seq + declare -a mycodes=("${!1}") - debug "ansi: ${!1} all: $* aka ${mycodes[@]}" + debug "ansi: ${!1} all: $* aka " "${mycodes[@]}" - seq="" - for ((i = 0; i < ${#mycodes[@]}; i++)); do - if [[ -n $seq ]]; then - seq="${seq};" - fi - seq="${seq}${mycodes[$i]}" - done - debug "ansi debug:" '\\[\\033['${seq}'m\\]' - echo -ne '\[\033['${seq}'m\]' - # PR="$PR\[\033[${seq}m\]" + seq="" + for ((i = 0; i < ${#mycodes[@]}; i++)); do + if [[ -n $seq ]]; then + seq="${seq};" + fi + seq="${seq}${mycodes[$i]}" + done + debug "ansi debug:" '\\[\\033['"${seq}"'m\\]' + echo -ne '\[\033['"${seq}"'m\]' + # PR="$PR\[\033[${seq}m\]" } ansi_single() { - echo -ne '\[\033['$1'm\]' + echo -ne '\[\033['"$1"'m\]' } # Begin a segment # Takes two arguments, background and foreground. Both can be omitted, # rendering default background/foreground. prompt_segment() { - local bg fg - declare -a codes + local bg fg + declare -a codes - debug "Prompting $1 $2 $3" + debug "Prompting $1 $2 $3" - # if commented out from kruton's original... I'm not clear - # if it did anything, but it messed up things like - # prompt_status - Erik 1/14/17 + # if commented out from kruton's original... I'm not clear + # if it did anything, but it messed up things like + # prompt_status - Erik 1/14/17 - # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then - codes=("${codes[@]}" $(text_effect reset)) - # fi - if [[ -n $1 ]]; then - bg=$(bg_color $1) - codes=("${codes[@]}" $bg) - debug "Added $bg as background to codes" - fi - if [[ -n $2 ]]; then - fg=$(fg_color $2) - codes=("${codes[@]}" $fg) - debug "Added $fg as foreground to codes" - fi + # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then + codes=("${codes[@]}" "$(text_effect reset)") + # fi + if [[ -n $1 ]]; then + bg=$(bg_color "$1") + codes=("${codes[@]}" "$bg") + debug "Added $bg as background to codes" + fi + if [[ -n $2 ]]; then + fg=$(fg_color "$2") + codes=("${codes[@]}" "$fg") + debug "Added $fg as foreground to codes" + fi - debug "Codes: " - # declare -p codes + debug "Codes: " + # declare -p codes - if [[ $CURRENT_BG != NONE && $1 != $CURRENT_BG ]]; then - declare -a intermediate=($(fg_color $CURRENT_BG) $(bg_color $1)) - debug "pre prompt " $(ansi intermediate[@]) - PR="$PR $(ansi intermediate[@])$SEGMENT_SEPARATOR" - debug "post prompt " $(ansi codes[@]) - PR="$PR$(ansi codes[@]) " - else - debug "no current BG, codes is $codes[@]" - PR="$PR$(ansi codes[@]) " - fi - CURRENT_BG=$1 - [[ -n $3 ]] && PR="$PR$3" + if [[ $CURRENT_BG != NONE && $1 != "$CURRENT_BG" ]]; then + declare -a intermediate=("$(fg_color $CURRENT_BG)" "$(bg_color "$1")") + debug "pre prompt " "$(ansi intermediate[@])" + PR="$PR $(ansi intermediate[@])$SEGMENT_SEPARATOR" + debug "post prompt " "$(ansi codes[@])" + PR="$PR$(ansi codes[@]) " + else + debug "no current BG, codes is " "${codes[@]}" + PR="$PR$(ansi codes[@]) " + fi + CURRENT_BG=$1 + [[ -n $3 ]] && PR="$PR$3" } # End the prompt, closing any open segments prompt_end() { - if [[ -n $CURRENT_BG ]]; then - declare -a codes=($(text_effect reset) $(fg_color $CURRENT_BG)) - PR="$PR $(ansi codes[@])$SEGMENT_SEPARATOR" - fi - declare -a reset=($(text_effect reset)) - PR="$PR $(ansi reset[@])" - CURRENT_BG='' + if [[ -n $CURRENT_BG ]]; then + declare -a codes=("$(text_effect reset)" "$(fg_color "$CURRENT_BG")") + PR="$PR $(ansi codes[@])$SEGMENT_SEPARATOR" + fi + declare -a reset=("$(text_effect reset)") + PR="$PR $(ansi reset[@])" + CURRENT_BG='' } ### virtualenv prompt prompt_virtualenv() { - if [[ -n $VIRTUAL_ENV ]]; then - color=cyan - prompt_segment $color $PRIMARY_FG - ve=`basename "$VIRTUAL_ENV"` - prompt_segment $color white "$ve" - fi + if [[ -n $VIRTUAL_ENV ]]; then + color=cyan + prompt_segment $color "$PRIMARY_FG" + ve=$(basename "$VIRTUAL_ENV") + prompt_segment $color white "$ve" + fi } - ### Prompt components # Each component will draw itself, and hide itself if no information needs to be shown # Context: user@hostname (who am I and where am I) prompt_context() { - local user=`whoami` + local user=$(whoami) - if [[ $user != $DEFAULT_USER || -n $SSH_CLIENT ]]; then - prompt_segment black default "$user@\h" - fi + if [[ $user != "$DEFAULT_USER" || -n $SSH_CLIENT ]]; then + prompt_segment black default "$user@\h" + fi } # prints history followed by HH:MM, useful for remembering what # we did previously prompt_histdt() { - prompt_segment black default "\! [\A]" + prompt_segment black default "\! [\A]" } - git_status_dirty() { - dirty=$(git status -s 2> /dev/null | tail -n 1) - [[ -n $dirty ]] && echo " ●" + dirty=$(git status -s 2> /dev/null | tail -n 1) + [[ -n $dirty ]] && echo " ●" } # Git: branch/detached head, dirty status prompt_git() { - local ref dirty - if $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then - ZSH_THEME_GIT_PROMPT_DIRTY='±' - dirty=$(git_status_dirty) - ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="➦ $(git show-ref --head -s --abbrev |head -n1 2> /dev/null)" - if [[ -n $dirty ]]; then - prompt_segment yellow black - else - prompt_segment green black - fi - PR="$PR${ref/refs\/heads\// }$dirty" - fi + local ref dirty + if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then + ZSH_THEME_GIT_PROMPT_DIRTY='±' + dirty=$(git_status_dirty) + ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="➦ $(git show-ref --head -s --abbrev | head -n1 2> /dev/null)" + if [[ -n $dirty ]]; then + prompt_segment yellow black + else + prompt_segment green black + fi + PR="$PR${ref/refs\/heads\// }$dirty" + fi } # Dir: current working directory prompt_dir() { - prompt_segment blue black '\w' + prompt_segment blue black '\w' } # Status: @@ -266,13 +264,13 @@ prompt_dir() { # - am I root # - are there background jobs? prompt_status() { - local symbols - symbols=() - [[ $RETVAL -ne 0 ]] && symbols+="$(ansi_single $(fg_color red))✘" - [[ $UID -eq 0 ]] && symbols+="$(ansi_single $(fg_color yellow))⚡" - [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="$(ansi_single $(fg_color cyan))⚙" + local symbols + symbols=() + [[ $RETVAL -ne 0 ]] && symbols+=("$(ansi_single "$(fg_color red)")✘") + [[ $UID -eq 0 ]] && symbols+=("$(ansi_single "$(fg_color yellow)")⚡") + [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+=("$(ansi_single "$(fg_color cyan)")⚙") - [[ -n "$symbols" ]] && prompt_segment black default "$symbols" + [[ -n "${symbols[*]}" ]] && prompt_segment black default "${symbols[@]}" } ###################################################################### @@ -282,89 +280,89 @@ prompt_status() { # doesn't quite work per above rightprompt() { - printf "%*s" $COLUMNS "$PRIGHT" + printf "%*s" $COLUMNS "$PRIGHT" } # quick right prompt I grabbed to test things. __command_rprompt() { - local times= n=$COLUMNS tz - for tz in ZRH:Europe/Zurich PIT:US/Eastern \ - MTV:US/Pacific TOK:Asia/Tokyo; do - [ $n -gt 40 ] || break - times="$times ${tz%%:*}\e[30;1m:\e[0;36;1m" - times="$times$(TZ=${tz#*:} date +%H:%M)\e[0m" - n=$(( $n - 10 )) - done - [ -z "$times" ] || printf "%${n}s$times\\r" '' + local times=n=$COLUMNS tz + for tz in ZRH:Europe/Zurich PIT:US/Eastern \ + MTV:US/Pacific TOK:Asia/Tokyo; do + [ "$n" -gt 40 ] || break + times="$times ${tz%%:*}\e[30;1m:\e[0;36;1m" + times="$times$(TZ=${tz#*:} date +%H:%M)\e[0m" + n=$(("$n" - 10)) + done + [ -z "$times" ] || printf "%${n}s$times\\r" '' } # PROMPT_COMMAND=__command_rprompt # this doens't wrap code in \[ \] ansi_r() { - local seq - declare -a mycodes2=("${!1}") + local seq + declare -a mycodes2=("${!1}") - debug "ansi: ${!1} all: $* aka ${mycodes2[@]}" + debug "ansi: ${!1} all: $* aka " "${mycodes2[@]}" - seq="" - for ((i = 0; i < ${#mycodes2[@]}; i++)); do - if [[ -n $seq ]]; then - seq="${seq};" - fi - seq="${seq}${mycodes2[$i]}" - done - debug "ansi debug:" '\\[\\033['${seq}'m\\]' - echo -ne '\033['${seq}'m' - # PR="$PR\[\033[${seq}m\]" + seq="" + for ((i = 0; i < ${#mycodes2[@]}; i++)); do + if [[ -n $seq ]]; then + seq="${seq};" + fi + seq="${seq}${mycodes2[$i]}" + done + debug "ansi debug:" '\\[\\033['"${seq}"'m\\]' + echo -ne '\033['"${seq}"'m' + # PR="$PR\[\033[${seq}m\]" } # Begin a segment on the right # Takes two arguments, background and foreground. Both can be omitted, # rendering default background/foreground. prompt_right_segment() { - local bg fg - declare -a codes + local bg fg + declare -a codes - debug "Prompt right" - debug "Prompting $1 $2 $3" + debug "Prompt right" + debug "Prompting $1 $2 $3" - # if commented out from kruton's original... I'm not clear - # if it did anything, but it messed up things like - # prompt_status - Erik 1/14/17 + # if commented out from kruton's original... I'm not clear + # if it did anything, but it messed up things like + # prompt_status - Erik 1/14/17 - # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then - codes=("${codes[@]}" $(text_effect reset)) - # fi - if [[ -n $1 ]]; then - bg=$(bg_color $1) - codes=("${codes[@]}" $bg) - debug "Added $bg as background to codes" - fi - if [[ -n $2 ]]; then - fg=$(fg_color $2) - codes=("${codes[@]}" $fg) - debug "Added $fg as foreground to codes" - fi + # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then + codes=("${codes[@]}" "$(text_effect reset)") + # fi + if [[ -n $1 ]]; then + bg=$(bg_color "$1") + codes=("${codes[@]}" "$bg") + debug "Added $bg as background to codes" + fi + if [[ -n $2 ]]; then + fg=$(fg_color "$2") + codes=("${codes[@]}" "$fg") + debug "Added $fg as foreground to codes" + fi - debug "Right Codes: " - # declare -p codes + debug "Right Codes: " + # declare -p codes - # right always has a separator - # if [[ $CURRENT_RBG != NONE && $1 != $CURRENT_RBG ]]; then - # $CURRENT_RBG= - # fi - declare -a intermediate2=($(fg_color $1) $(bg_color $CURRENT_RBG) ) - # PRIGHT="$PRIGHT---" - debug "pre prompt " $(ansi_r intermediate2[@]) - PRIGHT="$PRIGHT$(ansi_r intermediate2[@])$RIGHT_SEPARATOR" - debug "post prompt " $(ansi_r codes[@]) - PRIGHT="$PRIGHT$(ansi_r codes[@]) " - # else - # debug "no current BG, codes is $codes[@]" - # PRIGHT="$PRIGHT$(ansi codes[@]) " - # fi - CURRENT_RBG=$1 - [[ -n $3 ]] && PRIGHT="$PRIGHT$3" + # right always has a separator + # if [[ $CURRENT_RBG != NONE && $1 != $CURRENT_RBG ]]; then + # $CURRENT_RBG= + # fi + declare -a intermediate2=("$(fg_color "$1")" "$(bg_color $CURRENT_RBG)") + # PRIGHT="$PRIGHT---" + debug "pre prompt " "$(ansi_r intermediate2[@])" + PRIGHT="$PRIGHT$(ansi_r intermediate2[@])$RIGHT_SEPARATOR" + debug "post prompt " "$(ansi_r codes[@])" + PRIGHT="$PRIGHT$(ansi_r codes[@]) " + # else + # debug "no current BG, codes is $codes[@]" + # PRIGHT="$PRIGHT$(ansi codes[@]) " + # fi + CURRENT_RBG=$1 + [[ -n $3 ]] && PRIGHT="$PRIGHT$3" } ###################################################################### @@ -385,22 +383,22 @@ prompt_right_segment() { # 'dirtrack-filter-out-pwd-prompt t t))) prompt_emacsdir() { - # no color or other setting... this will be deleted per above - PR="DIR \w DIR$PR" + # no color or other setting... this will be deleted per above + PR="DIR \w DIR$PR" } ###################################################################### ## Main prompt build_prompt() { - [[ ! -z ${AG_EMACS_DIR+x} ]] && prompt_emacsdir - prompt_status - #[[ -z ${AG_NO_HIST+x} ]] && prompt_histdt - [[ -z ${AG_NO_CONTEXT+x} ]] && prompt_context - prompt_virtualenv - prompt_dir - prompt_git - prompt_end + [[ -n ${AG_EMACS_DIR+x} ]] && prompt_emacsdir + prompt_status + #[[ -z ${AG_NO_HIST+x} ]] && prompt_histdt + [[ -z ${AG_NO_CONTEXT+x} ]] && prompt_context + prompt_virtualenv + prompt_dir + prompt_git + prompt_end } # from orig... @@ -409,16 +407,16 @@ build_prompt() { # use that. set_bash_prompt() { - RETVAL=$? - PR="" - PRIGHT="" - CURRENT_BG=NONE - PR="$(ansi_single $(text_effect reset))" - build_prompt + RETVAL=$? + PR="" + PRIGHT="" + CURRENT_BG=NONE + PR="$(ansi_single "$(text_effect reset)")" + build_prompt - # uncomment below to use right prompt - # PS1='\[$(tput sc; printf "%*s" $COLUMNS "$PRIGHT"; tput rc)\]'$PR - PS1=$PR + # uncomment below to use right prompt + # PS1='\[$(tput sc; printf "%*s" $COLUMNS "$PRIGHT"; tput rc)\]'$PR + PS1=$PR } PROMPT_COMMAND=set_bash_prompt diff --git a/themes/atomic/atomic.theme.bash b/themes/atomic/atomic.theme.bash index 129bcbb6..fb4e15af 100644 --- a/themes/atomic/atomic.theme.bash +++ b/themes/atomic/atomic.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # Atomic Bash Prompt for Bash-it # By lfelipe base on the theme brainy of MunifTanjim @@ -28,79 +28,79 @@ Face="\342\230\273" ############# ____atomic_top_left_parse() { - ifs_old="${IFS}" - IFS="|" - args=( $1 ) - IFS="${ifs_old}" - if [ -n "${args[3]}" ]; then - _TOP_LEFT+="${args[2]}${args[3]}" - fi - _TOP_LEFT+="${args[0]}${args[1]}" - if [ -n "${args[4]}" ]; then - _TOP_LEFT+="${args[2]}${args[4]}" - fi - _TOP_LEFT+="" + ifs_old="${IFS}" + IFS="|" + read -r -a args <<< "$@" + IFS="${ifs_old}" + if [ -n "${args[3]}" ]; then + _TOP_LEFT+="${args[2]}${args[3]}" + fi + _TOP_LEFT+="${args[0]}${args[1]}" + if [ -n "${args[4]}" ]; then + _TOP_LEFT+="${args[2]}${args[4]}" + fi + _TOP_LEFT+="" } ____atomic_top_right_parse() { - ifs_old="${IFS}" - IFS="|" - args=( $1 ) - IFS="${ifs_old}" - _TOP_RIGHT+=" " - if [ -n "${args[3]}" ]; then - _TOP_RIGHT+="${args[2]}${args[3]}" - fi - _TOP_RIGHT+="${args[0]}${args[1]}" - if [ -n "${args[4]}" ]; then - _TOP_RIGHT+="${args[2]}${args[4]}" - fi - __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1 )) - (( __SEG_AT_RIGHT += 1 )) + ifs_old="${IFS}" + IFS="|" + read -r -a args <<< "$@" + IFS="${ifs_old}" + _TOP_RIGHT+=" " + if [ -n "${args[3]}" ]; then + _TOP_RIGHT+="${args[2]}${args[3]}" + fi + _TOP_RIGHT+="${args[0]}${args[1]}" + if [ -n "${args[4]}" ]; then + _TOP_RIGHT+="${args[2]}${args[4]}" + fi + __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1)) + ((__SEG_AT_RIGHT += 1)) } ____atomic_bottom_parse() { - ifs_old="${IFS}" - IFS="|" - args=( $1 ) - IFS="${ifs_old}" - _BOTTOM+="${args[0]}${args[1]}" - [ ${#args[1]} -gt 0 ] && _BOTTOM+=" " + ifs_old="${IFS}" + IFS="|" + read -r -a args <<< "$@" + IFS="${ifs_old}" + _BOTTOM+="${args[0]}${args[1]}" + [ ${#args[1]} -gt 0 ] && _BOTTOM+=" " } ____atomic_top() { - _TOP_LEFT="" - _TOP_RIGHT="" - __TOP_RIGHT_LEN=0 - __SEG_AT_RIGHT=0 + _TOP_LEFT="" + _TOP_RIGHT="" + __TOP_RIGHT_LEN=0 + __SEG_AT_RIGHT=0 - for seg in ${___ATOMIC_TOP_LEFT}; do - info="$(___atomic_prompt_"${seg}")" - [ -n "${info}" ] && ____atomic_top_left_parse "${info}" - done + for seg in ${___ATOMIC_TOP_LEFT}; do + info="$(___atomic_prompt_"${seg}")" + [ -n "${info}" ] && ____atomic_top_left_parse "${info}" + done - ___cursor_right="\e[500C" - _TOP_LEFT+="${___cursor_right}" + ___cursor_right="\e[500C" + _TOP_LEFT+="${___cursor_right}" - for seg in ${___ATOMIC_TOP_RIGHT}; do - info="$(___atomic_prompt_"${seg}")" - [ -n "${info}" ] && ____atomic_top_right_parse "${info}" - done + for seg in ${___ATOMIC_TOP_RIGHT}; do + info="$(___atomic_prompt_"${seg}")" + [ -n "${info}" ] && ____atomic_top_right_parse "${info}" + done - [ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN - 0 )) - ___cursor_adjust="\e[${__TOP_RIGHT_LEN}D" - _TOP_LEFT+="${___cursor_adjust}" + [ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN - 0)) + ___cursor_adjust="\e[${__TOP_RIGHT_LEN}D" + _TOP_LEFT+="${___cursor_adjust}" - printf "%s%s" "${_TOP_LEFT}" "${_TOP_RIGHT}" + printf "%s%s" "${_TOP_LEFT}" "${_TOP_RIGHT}" } ____atomic_bottom() { - _BOTTOM="" - for seg in $___ATOMIC_BOTTOM; do - info="$(___atomic_prompt_"${seg}")" - [ -n "${info}" ] && ____atomic_bottom_parse "${info}" - done - printf "\n%s" "${_BOTTOM}" + _BOTTOM="" + for seg in $___ATOMIC_BOTTOM; do + info="$(___atomic_prompt_"${seg}")" + [ -n "${info}" ] && ____atomic_bottom_parse "${info}" + done + printf "\n%s" "${_BOTTOM}" } ############## @@ -108,97 +108,97 @@ ____atomic_bottom() { ############## ___atomic_prompt_user_info() { - color=$white - box="${normal}${LineA}\$([[ \$? != 0 ]] && echo \"${BIWhite}[${IRed}${SX}${BIWhite}]${normal}${Line}\")${Line}${BIWhite}[|${BIWhite}]${normal}${Line}" - info="${IYellow}\u${IRed}@${IGreen}\h" + color=$white + box="${normal}${LineA}\$([[ \$? != 0 ]] && echo \"${BIWhite}[${IRed}${SX}${BIWhite}]${normal}${Line}\")${Line}${BIWhite}[|${BIWhite}]${normal}${Line}" + info="${IYellow}\u${IRed}@${IGreen}\h" - printf "%s|%s|%s|%s" "${color}" "${info}" "${white}" "${box}" + printf "%s|%s|%s|%s" "${color}" "${info}" "${white}" "${box}" } ___atomic_prompt_dir() { - color=${IRed} - box="[|]${normal}" - info="\w" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" + color=${IRed} + box="[|]${normal}" + info="\w" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" } ___atomic_prompt_scm() { - [ "${THEME_SHOW_SCM}" != "true" ] && return - color=$bold_green - box="${Line}[${IWhite}$(scm_char)] " - info="$(scm_prompt_info)" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" + [ "${THEME_SHOW_SCM}" != "true" ] && return + color=$bold_green + box="${Line}[${IWhite}$(scm_char)] " + info="$(scm_prompt_info)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" } ___atomic_prompt_python() { - [ "${THEME_SHOW_PYTHON}" != "true" ] && return - color=$bold_yellow - box="[|]" - info="$(python_version_prompt)" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_blue}" "${box}" + [ "${THEME_SHOW_PYTHON}" != "true" ] && return + color=$bold_yellow + box="[|]" + info="$(python_version_prompt)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_blue}" "${box}" } ___atomic_prompt_ruby() { - [ "${THEME_SHOW_RUBY}" != "true" ] && return - color=$bold_white - box="[|]" - info="rb-$(ruby_version_prompt)" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_red}" "${box}" + [ "${THEME_SHOW_RUBY}" != "true" ] && return + color=$bold_white + box="[|]" + info="rb-$(ruby_version_prompt)" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_red}" "${box}" } ___atomic_prompt_todo() { - [ "${THEME_SHOW_TODO}" != "true" ] || - [ -z "$(which todo.sh)" ] && return - color=$bold_white - box="[|]" - info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }' )" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}" + [ "${THEME_SHOW_TODO}" != "true" ] \ + || [ -z "$(which todo.sh)" ] && return + color=$bold_white + box="[|]" + info="t:$(todo.sh ls | grep -E "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }')" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}" } ___atomic_prompt_clock() { - [ "${THEME_SHOW_CLOCK}" != "true" ] && return - color=$THEME_CLOCK_COLOR - box="[|]" - info="$(date +"${THEME_CLOCK_FORMAT}")" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" + [ "${THEME_SHOW_CLOCK}" != "true" ] && return + color=$THEME_CLOCK_COLOR + box="[|]" + info="$(date +"${THEME_CLOCK_FORMAT}")" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" } ___atomic_prompt_battery() { - ! _command_exists battery_percentage || - [ "${THEME_SHOW_BATTERY}" != "true" ] || - [ "$(battery_percentage)" = "no" ] && return + ! _command_exists battery_percentage \ + || [ "${THEME_SHOW_BATTERY}" != "true" ] \ + || [ "$(battery_percentage)" = "no" ] && return - batp=$(battery_percentage) - if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then - color=$bold_green - elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then - color=$bold_yellow - elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then - color=$IRed - fi - box="[|]" - ac_adapter_connected && info="+" - ac_adapter_disconnected && info="-" - info+=$batp - [ "$batp" -eq 100 ] || [ "$batp" -gt 100 ] && info="AC" - printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" + batp=$(battery_percentage) + if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then + color=$bold_green + elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then + color=$bold_yellow + elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then + color=$IRed + fi + box="[|]" + ac_adapter_connected && info="+" + ac_adapter_disconnected && info="-" + info+=$batp + [ "$batp" -eq 100 ] || [ "$batp" -gt 100 ] && info="AC" + printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" } ___atomic_prompt_exitcode() { - [ "${THEME_SHOW_EXITCODE}" != "true" ] && return - color=$bold_purple - [ "$exitcode" -ne 0 ] && printf "%s|%s" "${color}" "${exitcode}" + [ "${THEME_SHOW_EXITCODE}" != "true" ] && return + color=$bold_purple + [ "$exitcode" -ne 0 ] && printf "%s|%s" "${color}" "${exitcode}" } ___atomic_prompt_char() { - color=$white - prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}" - if [ "${THEME_SHOW_SUDO}" == "true" ]; then - if sudo -vn 1>/dev/null 2>&1; then - prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}" - fi - fi - printf "%s|%s" "${color}" "${prompt_char}" + color=$white + prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}" + if [ "${THEME_SHOW_SUDO}" == "true" ]; then + if sudo -vn 1> /dev/null 2>&1; then + prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}" + fi + fi + printf "%s|%s" "${color}" "${prompt_char}" } ######### @@ -206,54 +206,56 @@ ___atomic_prompt_char() { ######### __atomic_show() { - typeset _seg=${1:-} - shift - export THEME_SHOW_${_seg}=true + typeset _seg=${1:-} + shift + export "THEME_SHOW_${_seg}"=true } __atomic_hide() { - typeset _seg=${1:-} - shift - export THEME_SHOW_${_seg}=false + typeset _seg=${1:-} + shift + export "THEME_SHOW_${_seg}"=false } _atomic_completion() { - local cur _action actions segments - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - _action="${COMP_WORDS[1]}" - actions="show hide" - segments="battery clock exitcode python ruby scm sudo todo" - case "${_action}" in - show) - COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) - return 0 - ;; - hide) - COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) - return 0 - ;; - esac + local cur _action actions segments + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + _action="${COMP_WORDS[1]}" + actions="show hide" + segments="battery clock exitcode python ruby scm sudo todo" + case "${_action}" in + show) + read -r -a COMPREPLY <<< "$(compgen -W "${segments}" -- "${cur}")" + return 0 + ;; + hide) + read -r -a COMPREPLY <<< "$(compgen -W "${segments}" -- "${cur}")" + return 0 + ;; + esac - COMPREPLY=( $(compgen -W "${actions}" -- "${cur}") ) - return 0 + read -r -a COMPREPLY <<< "$(compgen -W "${actions}" -- "${cur}")" + return 0 } atomic() { - typeset action=${1:-} - shift - typeset segs=${*:-} - typeset func - case $action in - show) - func=__atomic_show;; - hide) - func=__atomic_hide;; - esac - for seg in ${segs}; do - seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]') - $func "${seg}" - done + typeset action=${1:-} + shift + typeset segs=${*:-} + typeset func + case $action in + show) + func=__atomic_show + ;; + hide) + func=__atomic_hide + ;; + esac + for seg in ${segs}; do + seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]') + $func "${seg}" + done } complete -F _atomic_completion atomic @@ -302,19 +304,19 @@ ___ATOMIC_BOTTOM=${___ATOMIC_BOTTOM:-"char"} ############ __atomic_ps1() { - printf "%s%s%s" "$(____atomic_top)" "$(____atomic_bottom)" "${normal}" + printf "%s%s%s" "$(____atomic_top)" "$(____atomic_bottom)" "${normal}" } __atomic_ps2() { - color=$bold_white - printf "%s%s%s" "${color}" "${__ATOMIC_PROMPT_CHAR_PS2} " "${normal}" + color=$bold_white + printf "%s%s%s" "${color}" "${__ATOMIC_PROMPT_CHAR_PS2} " "${normal}" } _atomic_prompt() { - exitcode="$?" + exitcode="$?" - PS1="$(__atomic_ps1)" - PS2="$(__atomic_ps2)" + PS1="$(__atomic_ps1)" + PS2="$(__atomic_ps2)" } safe_append_prompt_command _atomic_prompt diff --git a/themes/axin/axin.theme.bash b/themes/axin/axin.theme.bash index d5e91753..7e90aded 100644 --- a/themes/axin/axin.theme.bash +++ b/themes/axin/axin.theme.bash @@ -1,36 +1,36 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # Axin Bash Prompt, inspired by theme "Sexy" and "Bobby" # thanks to them if tput setaf 1 &> /dev/null; then - if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then - MAGENTA=$(tput setaf 9) - ORANGE=$(tput setaf 172) - GREEN=$(tput setaf 190) - PURPLE=$(tput setaf 141) - WHITE=$(tput setaf 0) - else - MAGENTA=$(tput setaf 5) - ORANGE=$(tput setaf 4) - GREEN=$(tput setaf 2) - PURPLE=$(tput setaf 1) - WHITE=$(tput setaf 7) - fi - BOLD=$(tput bold) - RESET=$(tput sgr0) + if [[ $(tput colors) -ge 256 ]] 2> /dev/null; then + MAGENTA=$(tput setaf 9) + ORANGE=$(tput setaf 172) + GREEN=$(tput setaf 190) + PURPLE=$(tput setaf 141) + WHITE=$(tput setaf 0) + else + MAGENTA=$(tput setaf 5) + ORANGE=$(tput setaf 4) + GREEN=$(tput setaf 2) + PURPLE=$(tput setaf 1) + WHITE=$(tput setaf 7) + fi + BOLD=$(tput bold) + RESET=$(tput sgr0) else - MAGENTA="\033[1;31m" - ORANGE="\033[1;33m" - GREEN="\033[1;32m" - PURPLE="\033[1;35m" - WHITE="\033[1;37m" - BOLD="" - RESET="\033[m" + MAGENTA="\033[1;31m" + ORANGE="\033[1;33m" + GREEN="\033[1;32m" + PURPLE="\033[1;35m" + WHITE="\033[1;37m" + BOLD="" + RESET="\033[m" fi function prompt_command() { - PS1="\[${BOLD}${MAGENTA}\]\u \[$WHITE\]@ \[$ORANGE\]\h \[$WHITE\]in \[$GREEN\]\w\[$WHITE\]\[$SCM_THEME_PROMPT_PREFIX\]$(clock_prompt) \[$PURPLE\]$(scm_prompt_info) \n\$ \[$RESET\]" + PS1="\[${BOLD}${MAGENTA}\]\u \[$WHITE\]@ \[$ORANGE\]\h \[$WHITE\]in \[$GREEN\]\w\[$WHITE\]\[$SCM_THEME_PROMPT_PREFIX\]$(clock_prompt) \[$PURPLE\]$(scm_prompt_info) \n\$ \[$RESET\]" } THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"${white}"} diff --git a/themes/barbuk/README.rst b/themes/barbuk/README.rst new file mode 120000 index 00000000..ca150a95 --- /dev/null +++ b/themes/barbuk/README.rst @@ -0,0 +1 @@ +../../docs/themes-list/barbuk.rst \ No newline at end of file diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index e1e7f2c1..8e09d4be 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -1,5 +1,4 @@ -#!/usr/bin/env bash -# shellcheck disable=2034,2154 +# shellcheck shell=bash # Theme custom glyphs SCM_GIT_CHAR_GITLAB=${BARBUK_GITLAB_CHAR:=' '} @@ -11,6 +10,11 @@ SCM_HG_CHAR=${BARBUK_HG_CHAR:='☿ '} SCM_SVN_CHAR=${BARBUK_SVN_CHAR:='⑆ '} EXIT_CODE_ICON=${BARBUK_EXIT_CODE_ICON:=' '} PYTHON_VENV_CHAR=${BARBUK_PYTHON_VENV_CHAR:=' '} +COMMAND_DURATION_ICON=${BARBUK_COMMAND_DURATION_ICON:-"$bold_blue  "} + +# Command duration +COMMAND_DURATION_MIN_SECONDS=${COMMAND_DURATION_MIN_SECONDS:-1} +COMMAND_DURATION_COLOR="$normal" # Ssh user and hostname display SSH_INFO=${BARBUK_SSH_INFO:=true} @@ -36,70 +40,71 @@ SCM_THEME_CURRENT_USER_PREFFIX='  ' SCM_GIT_SHOW_CURRENT_USER=false function _git-uptream-remote-logo { - [[ "$(_git-upstream)" == "" ]] && SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT" + [[ "$(_git-upstream)" == "" ]] && SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT" - local remote remote_domain - remote=$(_git-upstream-remote) - remote_domain=$(git config --get remote."$remote".url | awk -F'[@:.]' '{print $2}') + local remote remote_domain + remote=$(_git-upstream-remote) + remote_domain=$(git config --get remote."$remote".url | awk -F'[@:.]' '{print $2}') - # remove // suffix for https:// url - remote_domain=${remote_domain//\//} + # remove // suffix for https:// url + remote_domain=${remote_domain//\//} - case $remote_domain in - github ) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITHUB";; - gitlab ) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITLAB";; - bitbucket ) SCM_GIT_CHAR="$SCM_GIT_CHAR_BITBUCKET";; - * ) SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT";; - esac + case $remote_domain in + github) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITHUB" ;; + gitlab) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITLAB" ;; + bitbucket) SCM_GIT_CHAR="$SCM_GIT_CHAR_BITBUCKET" ;; + *) SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT" ;; + esac } function git_prompt_info { - git_prompt_vars - echo -e " on $SCM_GIT_CHAR_ICON_BRANCH $SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_GIT_AHEAD$SCM_GIT_BEHIND$SCM_GIT_STASH$SCM_SUFFIX" + git_prompt_vars + echo -e " on $SCM_GIT_CHAR_ICON_BRANCH $SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_GIT_AHEAD$SCM_GIT_BEHIND$SCM_GIT_STASH$SCM_SUFFIX" } function _exit-code { - if [[ "$1" -ne 0 ]]; then - exit_code=" ${purple}${EXIT_CODE_ICON}${yellow}${exit_code}${bold_orange}" - else - exit_code="${bold_green}" - fi + if [[ "$1" -ne 0 ]]; then + exit_code=" ${purple}${EXIT_CODE_ICON}${yellow}${exit_code}${bold_orange}" + else + exit_code="${bold_green}" + fi } function _prompt { - local exit_code="$?" wrap_char=' ' dir_color=$green ssh_info='' python_venv='' host + local exit_code="$?" wrap_char=' ' dir_color=$green ssh_info='' python_venv='' host command_duration= - _exit-code exit_code - _git-uptream-remote-logo + command_duration=$(_command_duration) - history -a + _exit-code exit_code + _git-uptream-remote-logo - # Detect root shell - if [ "$(whoami)" = root ]; then - dir_color=$red - fi + history -a - # Detect ssh - if [[ -n "${SSH_CONNECTION}" ]] && [ "$SSH_INFO" = true ]; then - if [ "$HOST_INFO" = long ]; then - host="\H" - else - host="\h" - fi - ssh_info="${bold_blue}\u${bold_orange}@${cyan}$host ${bold_orange}in" - fi + # Detect root shell + if [ "$(whoami)" = root ]; then + dir_color=$red + fi - # Detect python venv - if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then - python_venv="$PYTHON_VENV_CHAR${CONDA_DEFAULT_ENV} " - elif [[ -n "${VIRTUAL_ENV}" ]]; then - python_venv="$PYTHON_VENV_CHAR$(basename "${VIRTUAL_ENV}") " - fi + # Detect ssh + if [[ -n "${SSH_CONNECTION}" ]] && [ "$SSH_INFO" = true ]; then + if [ "$HOST_INFO" = long ]; then + host="\H" + else + host="\h" + fi + ssh_info="${bold_blue}\u${bold_orange}@${cyan}$host ${bold_orange}in" + fi - PS1="\\n${ssh_info} ${purple}$(scm_char)${python_venv}${dir_color}\\w${normal}$(scm_prompt_info)${exit_code}" + # Detect python venv + if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then + python_venv="$PYTHON_VENV_CHAR${CONDA_DEFAULT_ENV} " + elif [[ -n "${VIRTUAL_ENV}" ]]; then + python_venv="$PYTHON_VENV_CHAR$(basename "${VIRTUAL_ENV}") " + fi - [[ ${#PS1} -gt $((COLUMNS*3)) ]] && wrap_char="\\n" - PS1="${PS1}${wrap_char}❯${normal} " + PS1="\\n${ssh_info} ${purple}$(scm_char)${python_venv}${dir_color}\\w${normal}$(scm_prompt_info)${command_duration}${exit_code}" + [[ ${#PS1} -gt $((COLUMNS * 2)) ]] && wrap_char="\\n" + PS1="${PS1}${wrap_char}❯${normal} " } safe_append_prompt_command _prompt diff --git a/themes/base.theme.bash b/themes/base.theme.bash index 58246720..30305957 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash CLOCK_CHAR_THEME_PROMPT_PREFIX='' CLOCK_CHAR_THEME_PROMPT_SUFFIX='' @@ -87,219 +87,235 @@ RBFU_THEME_PROMPT_SUFFIX='|' GIT_EXE=$(which git 2> /dev/null || true) P4_EXE=$(which p4 2> /dev/null || true) -HG_EXE=$(which hg 2> /dev/null || true) -SVN_EXE=$(which svn 2> /dev/null || true) +HG_EXE=$(which hg 2> /dev/null || true) +SVN_EXE=$(which svn 2> /dev/null || true) # Check for broken SVN exe that is caused by some versions of Xcode. # See https://github.com/Bash-it/bash-it/issues/1612 for more details. -if [[ -x "$SVN_EXE" ]] ; then - if ! "$SVN_EXE" --version > /dev/null 2>&1 ; then - # Unset the SVN exe variable so that SVN commands are avoided. - SVN_EXE="" - fi +if [[ -x "$SVN_EXE" ]]; then + if ! "$SVN_EXE" --version > /dev/null 2>&1; then + # Unset the SVN exe variable so that SVN commands are avoided. + SVN_EXE="" + fi fi function scm { - if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE - elif [[ -f .git/HEAD ]] && [[ -x "$GIT_EXE" ]]; then SCM=$SCM_GIT - elif [[ -x "$GIT_EXE" ]] && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then SCM=$SCM_GIT - elif [[ -x "$P4_EXE" ]] && [[ -n "$(p4 set P4CLIENT 2> /dev/null)" ]]; then SCM=$SCM_P4 - elif [[ -d .hg ]] && [[ -x "$HG_EXE" ]]; then SCM=$SCM_HG - elif [[ -x "$HG_EXE" ]] && [[ -n "$(hg root 2> /dev/null)" ]]; then SCM=$SCM_HG - elif [[ -d .svn ]] && [[ -x "$SVN_EXE" ]]; then SCM=$SCM_SVN - elif [[ -x "$SVN_EXE" ]] && [[ -n "$(svn info --show-item wc-root 2>/dev/null)" ]]; then SCM=$SCM_SVN - else SCM=$SCM_NONE - fi + if [[ "$SCM_CHECK" = false ]]; then + SCM=$SCM_NONE + elif [[ -f .git/HEAD ]] && [[ -x "$GIT_EXE" ]]; then + SCM=$SCM_GIT + elif [[ -x "$GIT_EXE" ]] && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then + SCM=$SCM_GIT + elif [[ -x "$P4_EXE" ]] && [[ -n "$(p4 set P4CLIENT 2> /dev/null)" ]]; then + SCM=$SCM_P4 + elif [[ -d .hg ]] && [[ -x "$HG_EXE" ]]; then + SCM=$SCM_HG + elif [[ -x "$HG_EXE" ]] && [[ -n "$(hg root 2> /dev/null)" ]]; then + SCM=$SCM_HG + elif [[ -d .svn ]] && [[ -x "$SVN_EXE" ]]; then + SCM=$SCM_SVN + elif [[ -x "$SVN_EXE" ]] && [[ -n "$(svn info --show-item wc-root 2> /dev/null)" ]]; then + SCM=$SCM_SVN + else + SCM=$SCM_NONE + fi } function scm_prompt_char { - if [[ -z $SCM ]]; then scm; fi - if [[ $SCM == $SCM_GIT ]]; then SCM_CHAR=$SCM_GIT_CHAR - elif [[ $SCM == $SCM_P4 ]]; then SCM_CHAR=$SCM_P4_CHAR - elif [[ $SCM == $SCM_HG ]]; then SCM_CHAR=$SCM_HG_CHAR - elif [[ $SCM == $SCM_SVN ]]; then SCM_CHAR=$SCM_SVN_CHAR - else SCM_CHAR=$SCM_NONE_CHAR - fi + if [[ -z $SCM ]]; then scm; fi + if [[ $SCM == "$SCM_GIT" ]]; then + SCM_CHAR=$SCM_GIT_CHAR + elif [[ $SCM == "$SCM_P4" ]]; then + SCM_CHAR=$SCM_P4_CHAR + elif [[ $SCM == "$SCM_HG" ]]; then + SCM_CHAR=$SCM_HG_CHAR + elif [[ $SCM == "$SCM_SVN" ]]; then + SCM_CHAR=$SCM_SVN_CHAR + else + SCM_CHAR=$SCM_NONE_CHAR + fi } function scm_prompt_vars { - scm - scm_prompt_char - SCM_DIRTY=0 - SCM_STATE='' - [[ $SCM == $SCM_GIT ]] && git_prompt_vars && return - [[ $SCM == $SCM_P4 ]] && p4_prompt_vars && return - [[ $SCM == $SCM_HG ]] && hg_prompt_vars && return - [[ $SCM == $SCM_SVN ]] && svn_prompt_vars && return + scm + scm_prompt_char + SCM_DIRTY=0 + SCM_STATE='' + [[ $SCM == "$SCM_GIT" ]] && git_prompt_vars && return + [[ $SCM == "$SCM_P4" ]] && p4_prompt_vars && return + [[ $SCM == "$SCM_HG" ]] && hg_prompt_vars && return + [[ $SCM == "$SCM_SVN" ]] && svn_prompt_vars && return } function scm_prompt_info { - scm - scm_prompt_char - scm_prompt_info_common + scm + scm_prompt_char + scm_prompt_info_common } function scm_prompt_char_info { - scm_prompt_char - echo -ne "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" - scm_prompt_info_common + scm_prompt_char + echo -ne "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" + scm_prompt_info_common } function scm_prompt_info_common { - SCM_DIRTY=0 - SCM_STATE='' + SCM_DIRTY=0 + SCM_STATE='' - if [[ ${SCM} == ${SCM_GIT} ]]; then - if [[ ${SCM_GIT_SHOW_MINIMAL_INFO} == true ]]; then - # user requests minimal git status information - git_prompt_minimal_info - else - # more detailed git status - git_prompt_info - fi - return - fi + if [[ ${SCM} == "${SCM_GIT}" ]]; then + if [[ ${SCM_GIT_SHOW_MINIMAL_INFO} == true ]]; then + # user requests minimal git status information + git_prompt_minimal_info + else + # more detailed git status + git_prompt_info + fi + return + fi - # TODO: consider adding minimal status information for hg and svn - { [[ ${SCM} == ${SCM_P4} ]] && p4_prompt_info && return; } || true - { [[ ${SCM} == ${SCM_HG} ]] && hg_prompt_info && return; } || true - { [[ ${SCM} == ${SCM_SVN} ]] && svn_prompt_info && return; } || true + # TODO: consider adding minimal status information for hg and svn + { [[ ${SCM} == "${SCM_P4}" ]] && p4_prompt_info && return; } || true + { [[ ${SCM} == "${SCM_HG}" ]] && hg_prompt_info && return; } || true + { [[ ${SCM} == "${SCM_SVN}" ]] && svn_prompt_info && return; } || true } function terraform_workspace_prompt { - if _command_exists terraform ; then - if [ -d .terraform ]; then - echo -e "$(terraform workspace show 2>/dev/null)" - fi - fi + if _command_exists terraform; then + if [ -d .terraform ]; then + echo -e "$(terraform workspace show 2> /dev/null)" + fi + fi } function git_prompt_minimal_info { - SCM_STATE=${SCM_THEME_PROMPT_CLEAN} + SCM_STATE=${SCM_THEME_PROMPT_CLEAN} - _git-hide-status && return + _git-hide-status && return - SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)" + SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)" - if [[ -n "$(_git-status | tail -n1)" ]]; then - SCM_DIRTY=1 - SCM_STATE=${SCM_THEME_PROMPT_DIRTY} - fi + if [[ -n "$(_git-status | tail -n1)" ]]; then + SCM_DIRTY=1 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + fi - # Output the git prompt - SCM_PREFIX=${SCM_THEME_PROMPT_PREFIX} - SCM_SUFFIX=${SCM_THEME_PROMPT_SUFFIX} - echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" + # Output the git prompt + SCM_PREFIX=${SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${SCM_THEME_PROMPT_SUFFIX} + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" } function git_prompt_vars { - if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then # use faster gitstatus - SCM_GIT_GITSTATUS_RAN=true # use this in githelpers and below to choose gitstatus output - else - SCM_GIT_GITSTATUS_RAN=false - fi + if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then + # we can use faster gitstatus + # use this variable in githelpers and below to choose gitstatus output + SCM_GIT_GITSTATUS_RAN=true + else + SCM_GIT_GITSTATUS_RAN=false + fi - if _git-branch &> /dev/null; then - SCM_GIT_DETACHED="false" - SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)" - else - SCM_GIT_DETACHED="true" + if _git-branch &> /dev/null; then + SCM_GIT_DETACHED="false" + SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)" + else + SCM_GIT_DETACHED="true" - local detached_prefix - if _git-tag &> /dev/null; then - detached_prefix=${SCM_THEME_TAG_PREFIX} - else - detached_prefix=${SCM_THEME_DETACHED_PREFIX} - fi - SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)" - fi + local detached_prefix + if _git-tag &> /dev/null; then + detached_prefix=${SCM_THEME_TAG_PREFIX} + else + detached_prefix=${SCM_THEME_DETACHED_PREFIX} + fi + SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)" + fi - if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then - commits_behind=${VCS_STATUS_COMMITS_BEHIND} - commits_ahead=${VCS_STATUS_COMMITS_AHEAD} - else - IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)" - fi - if [[ "${commits_ahead}" -gt 0 ]]; then - SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}" - [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}" - fi - if [[ "${commits_behind}" -gt 0 ]]; then - SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_BEHIND_CHAR}" - [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_behind}" - fi + if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then + commits_behind=${VCS_STATUS_COMMITS_BEHIND} + commits_ahead=${VCS_STATUS_COMMITS_AHEAD} + else + IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)" + fi + if [[ "${commits_ahead}" -gt 0 ]]; then + SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}" + [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}" + fi + if [[ "${commits_behind}" -gt 0 ]]; then + SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_BEHIND_CHAR}" + [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_behind}" + fi - if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then - local stash_count - if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then - stash_count=${VCS_STATUS_STASHES} - else - stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')" - fi - [[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}" - fi + if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then + local stash_count + if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then + stash_count=${VCS_STATUS_STASHES} + else + stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')" + fi + [[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}" + fi - SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} - if ! _git-hide-status; then - if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then - untracked_count=${VCS_STATUS_NUM_UNTRACKED} - unstaged_count=${VCS_STATUS_NUM_UNSTAGED} - staged_count=${VCS_STATUS_NUM_STAGED} - else - IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)" - fi - if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then - SCM_DIRTY=1 - if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then - [[ "${staged_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STAGED_CHAR}${staged_count}" && SCM_DIRTY=3 - [[ "${unstaged_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_UNSTAGED_CHAR}${unstaged_count}" && SCM_DIRTY=2 - [[ "${untracked_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_UNTRACKED_CHAR}${untracked_count}" && SCM_DIRTY=1 - fi - SCM_STATE=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} - fi - fi + SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + if ! _git-hide-status; then + if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then + untracked_count=${VCS_STATUS_NUM_UNTRACKED} + unstaged_count=${VCS_STATUS_NUM_UNSTAGED} + staged_count=${VCS_STATUS_NUM_STAGED} + else + IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)" + fi + if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then + SCM_DIRTY=1 + if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then + [[ "${staged_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STAGED_CHAR}${staged_count}" && SCM_DIRTY=3 + [[ "${unstaged_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_UNSTAGED_CHAR}${unstaged_count}" && SCM_DIRTY=2 + [[ "${untracked_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_UNTRACKED_CHAR}${untracked_count}" && SCM_DIRTY=1 + fi + SCM_STATE=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + fi + fi - # no if for gitstatus here, user extraction is not supported by it - [[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)" + # no if for gitstatus here, user extraction is not supported by it + [[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)" - SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} - SCM_SUFFIX=${GIT_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${GIT_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} - SCM_CHANGE=$(_git-short-sha 2>/dev/null || echo "") + SCM_CHANGE=$(_git-short-sha 2> /dev/null || echo "") } function p4_prompt_vars { - IFS=$'\t' read -r \ - opened_count non_default_changes default_count \ - add_file_count edit_file_count delete_file_count \ - <<< "$(_p4-opened-counts)" - if [[ "${opened_count}" -gt 0 ]]; then - SCM_DIRTY=1 - SCM_STATE=${SCM_THEME_PROMPT_DIRTY} - [[ "${opened_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_OPENED_CHAR}${opened_count}" - [[ "${non_default_changes}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_CHANGES_CHAR}${non_default_changes}" - [[ "${default_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_DEFAULT_CHAR}${default_count}" - else - SCM_DIRTY=0 - SCM_STATE=${SCM_THEME_PROMPT_DIRTY} - fi + IFS=$'\t' read -r \ + opened_count non_default_changes default_count \ + add_file_count edit_file_count delete_file_count \ + <<< "$(_p4-opened-counts)" + if [[ "${opened_count}" -gt 0 ]]; then + SCM_DIRTY=1 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + [[ "${opened_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_OPENED_CHAR}${opened_count}" + [[ "${non_default_changes}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_CHANGES_CHAR}${non_default_changes}" + [[ "${default_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_DEFAULT_CHAR}${default_count}" + else + SCM_DIRTY=0 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + fi - SCM_PREFIX=${P4_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} - SCM_SUFFIX=${P4_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + SCM_PREFIX=${P4_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${P4_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} } function svn_prompt_vars { - if [[ -n $(svn status |head -c1 2> /dev/null) ]]; then - SCM_DIRTY=1 - SCM_STATE=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} - else - SCM_DIRTY=0 - SCM_STATE=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} - fi - SCM_PREFIX=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} - SCM_SUFFIX=${SVN_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} - SCM_BRANCH=$(svn info --show-item=url 2> /dev/null | awk -F/ '{ for (i=0; i<=NF; i++) { if ($i == "branches" || $i == "tags" ) { print $(i+1); break }; if ($i == "trunk") { print $i; break } } }') || return - SCM_CHANGE=$(svn info --show-item=revision 2> /dev/null) + if [[ -n $(svn status | head -c1 2> /dev/null) ]]; then + SCM_DIRTY=1 + SCM_STATE=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + SCM_DIRTY=0 + SCM_STATE=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + SCM_PREFIX=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${SVN_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + SCM_BRANCH=$(svn info --show-item=url 2> /dev/null | awk -F/ '{ for (i=0; i<=NF; i++) { if ($i == "branches" || $i == "tags" ) { print $(i+1); break }; if ($i == "trunk") { print $i; break } } }') || return + SCM_CHANGE=$(svn info --show-item=revision 2> /dev/null) } # this functions returns absolute location of .hg directory if one exists @@ -310,268 +326,268 @@ function svn_prompt_vars { # - .hg is located in ~/Projects/Foo/.hg # - get_hg_root starts at ~/Projects/Foo/Bar and sees that there is no .hg directory, so then it goes into ~/Projects/Foo function get_hg_root { - local CURRENT_DIR=$(pwd) + local CURRENT_DIR=$(pwd) - while [ "$CURRENT_DIR" != "/" ]; do - if [ -d "$CURRENT_DIR/.hg" ]; then - echo "$CURRENT_DIR/.hg" - return - fi + while [ "$CURRENT_DIR" != "/" ]; do + if [ -d "$CURRENT_DIR/.hg" ]; then + echo "$CURRENT_DIR/.hg" + return + fi - CURRENT_DIR=$(dirname $CURRENT_DIR) - done + CURRENT_DIR=$(dirname "$CURRENT_DIR") + done } function hg_prompt_vars { - if [[ -n $(hg status 2> /dev/null) ]]; then - SCM_DIRTY=1 - SCM_STATE=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} - else - SCM_DIRTY=0 - SCM_STATE=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} - fi - SCM_PREFIX=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} - SCM_SUFFIX=${HG_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} + if [[ -n $(hg status 2> /dev/null) ]]; then + SCM_DIRTY=1 + SCM_STATE=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} + else + SCM_DIRTY=0 + SCM_STATE=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} + fi + SCM_PREFIX=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${HG_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} - HG_ROOT=$(get_hg_root) + HG_ROOT=$(get_hg_root) - if [ -f "$HG_ROOT/branch" ]; then - # Mercurial holds it's current branch in .hg/branch file - SCM_BRANCH=$(cat "$HG_ROOT/branch") - else - SCM_BRANCH=$(hg summary 2> /dev/null | grep branch: | awk '{print $2}') - fi + if [ -f "$HG_ROOT/branch" ]; then + # Mercurial holds it's current branch in .hg/branch file + SCM_BRANCH=$(cat "$HG_ROOT/branch") + else + SCM_BRANCH=$(hg summary 2> /dev/null | grep branch: | awk '{print $2}') + fi - if [ -f "$HG_ROOT/dirstate" ]; then - # Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState - SCM_CHANGE=$(hexdump -vn 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12) - else - SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}') - fi + if [ -f "$HG_ROOT/dirstate" ]; then + # Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState + SCM_CHANGE=$(hexdump -vn 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12) + else + SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}') + fi } function nvm_version_prompt { - local node - if declare -f -F nvm &> /dev/null; then - node=$(nvm current 2> /dev/null) - [[ "${node}" == "system" ]] && return - echo -e "${NVM_THEME_PROMPT_PREFIX}${node}${NVM_THEME_PROMPT_SUFFIX}" - fi + local node + if declare -f -F nvm &> /dev/null; then + node=$(nvm current 2> /dev/null) + [[ "${node}" == "system" ]] && return + echo -e "${NVM_THEME_PROMPT_PREFIX}${node}${NVM_THEME_PROMPT_SUFFIX}" + fi } function node_version_prompt { - echo -e "$(nvm_version_prompt)" + echo -e "$(nvm_version_prompt)" } function rvm_version_prompt { - if which rvm &> /dev/null; then - rvm=$(rvm-prompt) || return - if [ -n "$rvm" ]; then - echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX" - fi - fi + if which rvm &> /dev/null; then + rvm=$(rvm-prompt) || return + if [ -n "$rvm" ]; then + echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX" + fi + fi } function rbenv_version_prompt { - if which rbenv &> /dev/null; then - rbenv=$(rbenv version-name) || return - $(rbenv commands | grep -q gemset) && gemset=$(rbenv gemset active 2> /dev/null) && rbenv="$rbenv@${gemset%% *}" - if [ $rbenv != "system" ]; then - echo -e "$RBENV_THEME_PROMPT_PREFIX$rbenv$RBENV_THEME_PROMPT_SUFFIX" - fi - fi + if which rbenv &> /dev/null; then + rbenv=$(rbenv version-name) || return + rbenv commands | grep -q gemset && gemset=$(rbenv gemset active 2> /dev/null) && rbenv="$rbenv@${gemset%% *}" + if [ "$rbenv" != "system" ]; then + echo -e "$RBENV_THEME_PROMPT_PREFIX$rbenv$RBENV_THEME_PROMPT_SUFFIX" + fi + fi } function rbfu_version_prompt { - if [[ $RBFU_RUBY_VERSION ]]; then - echo -e "${RBFU_THEME_PROMPT_PREFIX}${RBFU_RUBY_VERSION}${RBFU_THEME_PROMPT_SUFFIX}" - fi + if [[ $RBFU_RUBY_VERSION ]]; then + echo -e "${RBFU_THEME_PROMPT_PREFIX}${RBFU_RUBY_VERSION}${RBFU_THEME_PROMPT_SUFFIX}" + fi } function chruby_version_prompt { - if declare -f -F chruby &> /dev/null; then - if declare -f -F chruby_auto &> /dev/null; then - chruby_auto - fi + if declare -f -F chruby &> /dev/null; then + if declare -f -F chruby_auto &> /dev/null; then + chruby_auto + fi - ruby_version=$(ruby --version | awk '{print $1, $2;}') || return + ruby_version=$(ruby --version | awk '{print $1, $2;}') || return - if [[ ! $(chruby | grep '\*') ]]; then - ruby_version="${ruby_version} (system)" - fi - echo -e "${CHRUBY_THEME_PROMPT_PREFIX}${ruby_version}${CHRUBY_THEME_PROMPT_SUFFIX}" - fi + if ! chruby | grep -q '\*'; then + ruby_version="${ruby_version} (system)" + fi + echo -e "${CHRUBY_THEME_PROMPT_PREFIX}${ruby_version}${CHRUBY_THEME_PROMPT_SUFFIX}" + fi } function ruby_version_prompt { - if [[ "${THEME_SHOW_RUBY_PROMPT}" = "true" ]]; then - echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)" - fi + if [[ "${THEME_SHOW_RUBY_PROMPT}" = "true" ]]; then + echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)" + fi } function k8s_context_prompt { - echo -e "$(kubectl config current-context 2> /dev/null)" + echo -e "$(kubectl config current-context 2> /dev/null)" } function virtualenv_prompt { - if [[ -n "$VIRTUAL_ENV" ]]; then - virtualenv=`basename "$VIRTUAL_ENV"` - echo -e "$VIRTUALENV_THEME_PROMPT_PREFIX$virtualenv$VIRTUALENV_THEME_PROMPT_SUFFIX" - fi + if [[ -n "$VIRTUAL_ENV" ]]; then + virtualenv=$(basename "$VIRTUAL_ENV") + echo -e "$VIRTUALENV_THEME_PROMPT_PREFIX$virtualenv$VIRTUALENV_THEME_PROMPT_SUFFIX" + fi } function condaenv_prompt { - if [[ $CONDA_DEFAULT_ENV ]]; then - echo -e "${CONDAENV_THEME_PROMPT_PREFIX}${CONDA_DEFAULT_ENV}${CONDAENV_THEME_PROMPT_SUFFIX}" - fi + if [[ $CONDA_DEFAULT_ENV ]]; then + echo -e "${CONDAENV_THEME_PROMPT_PREFIX}${CONDA_DEFAULT_ENV}${CONDAENV_THEME_PROMPT_SUFFIX}" + fi } function py_interp_prompt { - py_version=$(python --version 2>&1 | awk 'NR==1{print "py-"$2;}') || return - echo -e "${PYTHON_THEME_PROMPT_PREFIX}${py_version}${PYTHON_THEME_PROMPT_SUFFIX}" + py_version=$(python --version 2>&1 | awk 'NR==1{print "py-"$2;}') || return + echo -e "${PYTHON_THEME_PROMPT_PREFIX}${py_version}${PYTHON_THEME_PROMPT_SUFFIX}" } function python_version_prompt { - echo -e "$(virtualenv_prompt)$(condaenv_prompt)$(py_interp_prompt)" + echo -e "$(virtualenv_prompt)$(condaenv_prompt)$(py_interp_prompt)" } function git_user_info { - # support two or more initials, set by 'git pair' plugin - SCM_CURRENT_USER=$(git config user.initials | sed 's% %+%') - # if `user.initials` weren't set, attempt to extract initials from `user.name` - [[ -z "${SCM_CURRENT_USER}" ]] && SCM_CURRENT_USER=$(printf "%s" $(for word in $(git config user.name | PERLIO=:utf8 perl -pe '$_=lc'); do printf "%s" "${word:0:1}"; done)) - [[ -n "${SCM_CURRENT_USER}" ]] && printf "%s" "$SCM_THEME_CURRENT_USER_PREFFIX$SCM_CURRENT_USER$SCM_THEME_CURRENT_USER_SUFFIX" + # support two or more initials, set by 'git pair' plugin + SCM_CURRENT_USER=$(git config user.initials | sed 's% %+%') + # if `user.initials` weren't set, attempt to extract initials from `user.name` + [[ -z "${SCM_CURRENT_USER}" ]] && SCM_CURRENT_USER=$(printf "%s" "$(for word in $(git config user.name | PERLIO=:utf8 perl -pe '$_=lc'); do printf "%s" "${word:0:1}"; done)") + [[ -n "${SCM_CURRENT_USER}" ]] && printf "%s" "$SCM_THEME_CURRENT_USER_PREFFIX$SCM_CURRENT_USER$SCM_THEME_CURRENT_USER_SUFFIX" } function clock_char { - CLOCK_CHAR=${THEME_CLOCK_CHAR:-"⌚"} - CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$normal"} - SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"} + CLOCK_CHAR=${THEME_CLOCK_CHAR:-"⌚"} + CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$normal"} + SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"} - if [[ "${SHOW_CLOCK_CHAR}" = "true" ]]; then - echo -e "${CLOCK_CHAR_COLOR}${CLOCK_CHAR_THEME_PROMPT_PREFIX}${CLOCK_CHAR}${CLOCK_CHAR_THEME_PROMPT_SUFFIX}" - fi + if [[ "${SHOW_CLOCK_CHAR}" = "true" ]]; then + echo -e "${CLOCK_CHAR_COLOR}${CLOCK_CHAR_THEME_PROMPT_PREFIX}${CLOCK_CHAR}${CLOCK_CHAR_THEME_PROMPT_SUFFIX}" + fi } function clock_prompt { - CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$normal"} - CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"} - [ -z $THEME_SHOW_CLOCK ] && THEME_SHOW_CLOCK=${THEME_CLOCK_CHECK:-"true"} - SHOW_CLOCK=$THEME_SHOW_CLOCK + CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$normal"} + CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"} + [ -z "$THEME_SHOW_CLOCK" ] && THEME_SHOW_CLOCK=${THEME_CLOCK_CHECK:-"true"} + SHOW_CLOCK=$THEME_SHOW_CLOCK - if [[ "${SHOW_CLOCK}" = "true" ]]; then - CLOCK_STRING=$(date +"${CLOCK_FORMAT}") - echo -e "${CLOCK_COLOR}${CLOCK_THEME_PROMPT_PREFIX}${CLOCK_STRING}${CLOCK_THEME_PROMPT_SUFFIX}" - fi + if [[ "${SHOW_CLOCK}" = "true" ]]; then + CLOCK_STRING=$(date +"${CLOCK_FORMAT}") + echo -e "${CLOCK_COLOR}${CLOCK_THEME_PROMPT_PREFIX}${CLOCK_STRING}${CLOCK_THEME_PROMPT_SUFFIX}" + fi } function user_host_prompt { - if [[ "${THEME_SHOW_USER_HOST}" = "true" ]]; then - echo -e "${USER_HOST_THEME_PROMPT_PREFIX}\u@\h${USER_HOST_THEME_PROMPT_SUFFIX}" - fi + if [[ "${THEME_SHOW_USER_HOST}" = "true" ]]; then + echo -e "${USER_HOST_THEME_PROMPT_PREFIX}\u@\h${USER_HOST_THEME_PROMPT_SUFFIX}" + fi } # backwards-compatibility function git_prompt_info { - _git-hide-status && return - git_prompt_vars - echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" + _git-hide-status && return + git_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" } function p4_prompt_info() { - p4_prompt_vars - echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE}${SCM_STATE}${SCM_SUFFIX}" + p4_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE}${SCM_STATE}${SCM_SUFFIX}" } function svn_prompt_info { - svn_prompt_vars - echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" + svn_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" } function hg_prompt_info() { - hg_prompt_vars - echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE#*:}${SCM_STATE}${SCM_SUFFIX}" + hg_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE#*:}${SCM_STATE}${SCM_SUFFIX}" } function scm_char { - scm_prompt_char - echo -e "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" + scm_prompt_char + echo -e "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" } function prompt_char { - scm_char + scm_char } function battery_char { - if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then - echo -e "${bold_red}$(battery_percentage)%" - fi + if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then + echo -e "${bold_red}$(battery_percentage)%" + fi } -if ! _command_exists battery_charge ; then - # if user has installed battery plugin, skip this... - function battery_charge (){ - # no op - echo -n - } +if ! _command_exists battery_charge; then + # if user has installed battery plugin, skip this... + function battery_charge() { + # no op + echo -n + } fi # The battery_char function depends on the presence of the battery_percentage function. # If battery_percentage is not defined, then define battery_char as a no-op. -if ! _command_exists battery_percentage ; then - function battery_char (){ - # no op - echo -n - } +if ! _command_exists battery_percentage; then + function battery_char() { + # no op + echo -n + } fi function aws_profile { - if [[ $AWS_DEFAULT_PROFILE ]]; then - echo -e "${AWS_DEFAULT_PROFILE}" - else - echo -e "default" - fi + if [[ $AWS_DEFAULT_PROFILE ]]; then + echo -e "${AWS_DEFAULT_PROFILE}" + else + echo -e "default" + fi } function __check_precmd_conflict() { - local f - for f in "${precmd_functions[@]}"; do - if [[ "${f}" == "${1}" ]]; then - return 0 - fi - done - return 1 + local f + for f in "${precmd_functions[@]}"; do + if [[ "${f}" == "${1}" ]]; then + return 0 + fi + done + return 1 } function safe_append_prompt_command { - local prompt_re + local prompt_re - if [ "${__bp_imported}" == "defined" ]; then - # We are using bash-preexec - if ! __check_precmd_conflict "${1}" ; then - precmd_functions+=("${1}") - fi - else - # Set OS dependent exact match regular expression - if [[ ${OSTYPE} == darwin* ]]; then - # macOS - prompt_re="[[:<:]]${1}[[:>:]]" - else - # Linux, FreeBSD, etc. - prompt_re="\<${1}\>" - fi + if [ "${__bp_imported}" == "defined" ]; then + # We are using bash-preexec + if ! __check_precmd_conflict "${1}"; then + precmd_functions+=("${1}") + fi + else + # Set OS dependent exact match regular expression + if [[ ${OSTYPE} == darwin* ]]; then + # macOS + prompt_re="[[:<:]]${1}[[:>:]]" + else + # Linux, FreeBSD, etc. + prompt_re="\<${1}\>" + fi - if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then - return - elif [[ -z ${PROMPT_COMMAND} ]]; then - PROMPT_COMMAND="${1}" - else - PROMPT_COMMAND="${1};${PROMPT_COMMAND}" - fi - fi + if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then + return + elif [[ -z ${PROMPT_COMMAND} ]]; then + PROMPT_COMMAND="${1}" + else + PROMPT_COMMAND="${1};${PROMPT_COMMAND}" + fi + fi } function _save-and-reload-history() { - local autosave=${1:-0} - [[ $autosave -eq 1 ]] && history -a && history -c && history -r + local autosave=${1:-0} + [[ $autosave -eq 1 ]] && history -a && history -c && history -r } diff --git a/themes/command_duration.theme.bash b/themes/command_duration.theme.bash new file mode 100644 index 00000000..c721003e --- /dev/null +++ b/themes/command_duration.theme.bash @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +if [ -z "$BASH_IT_COMMAND_DURATION" ] || [ "$BASH_IT_COMMAND_DURATION" != true ]; then + _command_duration() { + echo -n + } + return +fi + +# Define tmp dir and file +COMMAND_DURATION_TMPDIR="${TMPDIR:-/tmp}" +COMMAND_DURATION_FILE="${COMMAND_DURATION_FILE:-$COMMAND_DURATION_TMPDIR/bashit_theme_execution_$BASHPID}" + +COMMAND_DURATION_ICON=${COMMAND_DURATION_ICON:-'  '} +COMMAND_DURATION_MIN_SECONDS=${COMMAND_DURATION_MIN_SECONDS:-'1'} + +trap _command_duration_delete_temp_file EXIT HUP INT TERM + +_command_duration_delete_temp_file() { + if [[ -f "$COMMAND_DURATION_FILE" ]]; then + rm -f "$COMMAND_DURATION_FILE" + fi +} + +_command_duration_pre_exec() { + date +%s.%1N > "$COMMAND_DURATION_FILE" +} + +_command_duration() { + local command_duration command_start current_time + local minutes seconds deciseconds + local command_start_sseconds current_time_seconds command_start_deciseconds current_time_deciseconds + current_time=$(date +%s.%1N) + + if [[ -f "$COMMAND_DURATION_FILE" ]]; then + command_start=$(< "$COMMAND_DURATION_FILE") + command_start_sseconds=${command_start%.*} + current_time_seconds=${current_time%.*} + + command_start_deciseconds=$((10#${command_start#*.})) + current_time_deciseconds=$((10#${current_time#*.})) + + # seconds + command_duration=$(( current_time_seconds - command_start_sseconds )) + + if (( current_time_deciseconds >= command_start_deciseconds )); then + deciseconds=$(( (current_time_deciseconds - command_start_deciseconds) )) + else + ((command_duration-=1)) + deciseconds=$(( 10 - ( (command_start_deciseconds - current_time_deciseconds) ) )) + fi + command rm "$COMMAND_DURATION_FILE" + else + command_duration=0 + fi + + if (( command_duration > 0 )); then + minutes=$(( command_duration / 60 )) + seconds=$(( command_duration % 60 )) + fi + + if (( minutes > 0 )); then + printf "%s%s%dm %ds" "$COMMAND_DURATION_ICON" "$COMMAND_DURATION_COLOR" "$minutes" "$seconds" + elif (( seconds >= COMMAND_DURATION_MIN_SECONDS )); then + printf "%s%s%d.%01ds" "$COMMAND_DURATION_ICON" "$COMMAND_DURATION_COLOR" "$seconds" "$deciseconds" + fi +} + +preexec() ( + _command_duration_pre_exec +) + +preexec_install diff --git a/themes/powerline/powerline.base.bash b/themes/powerline/powerline.base.bash index 38c5c895..dd39337e 100644 --- a/themes/powerline/powerline.base.bash +++ b/themes/powerline/powerline.base.bash @@ -1,3 +1,4 @@ +# shellcheck shell=bash # Define this here so it can be used by all of the Powerline themes THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true} diff --git a/themes/powerline/powerline.theme.bash b/themes/powerline/powerline.theme.bash index 83731614..3239b360 100644 --- a/themes/powerline/powerline.theme.bash +++ b/themes/powerline/powerline.theme.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# shellcheck shell=bash # shellcheck source=../../themes/powerline/powerline.base.bash . "$BASH_IT/themes/powerline/powerline.base.bash"