Merge remote-tracking branch 'origin/master' into feature/git-changelog

pull/1815/head
Gurkirat Singh 2021-01-24 17:53:42 +05:30
commit e189254ba3
No known key found for this signature in database
GPG Key ID: CFD64E1DCB3DA835
59 changed files with 1721 additions and 1542 deletions

View File

@ -9,13 +9,13 @@ charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[*.{md,rst}] [**.{md,rst}]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[.git*] [.git*]
indent_style = tab indent_style = tab
[*.*sh] [{**.*sh,test/run}]
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4
@ -23,7 +23,7 @@ shell_variant = bash
binary_next_line = true # like -bn binary_next_line = true # like -bn
switch_case_indent = true # like -ci switch_case_indent = true # like -ci
space_redirects = true # like -sr space_redirects = true # like -sr
keep_padding = true # like -kp keep_padding = false # like -kp
end_of_line = lf end_of_line = lf
charset = utf-8 charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true

View File

@ -11,7 +11,7 @@ jobs:
bats-test: bats-test:
strategy: strategy:
matrix: 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 }} runs-on: ${{ matrix.os }}

View File

@ -28,3 +28,17 @@ repos:
# - id: forbid-crlf # - id: forbid-crlf
- id: remove-crlf - id: remove-crlf
exclude: ".bat$" 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]

21
LICENSE 100644
View File

@ -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.

View File

@ -1,20 +1,17 @@
# shellcheck shell=bash
cite 'about-alias' cite 'about-alias'
about-alias 'pbcopy and pbpaste shortcuts to linux' about-alias 'xclip shortcuts'
case $OSTYPE in alias pbcopy="xclip -selection clipboard"
linux*) alias pbpaste="xclip -selection clipboard -o"
XCLIP=$(command -v xclip)
[[ $XCLIP ]] && \
alias pbcopy="$XCLIP -selection clipboard" && \
alias pbpaste="$XCLIP -selection clipboard -o"
;;
esac
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: # to use it just install xclip on your distribution and it would work like:
# $ echo "hello" | pbcopy # $ echo "hello" | xcpy
# $ pbpaste # $ xpst
# hello # hello
# very useful for things like: # very useful for things like:
# cat ~/.ssh/id_rsa.pub | pbcopy # cat ~/.ssh/id_rsa.pub | xcpy
# have fun! # have fun!

View File

@ -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

View File

@ -1,137 +1,197 @@
# shellcheck shell=bash
cite 'about-alias' cite 'about-alias'
about-alias 'common git abbreviations' 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 g='git'
alias get='git' alias get='git'
alias gs='git status'
alias gss='git status -s' # add
alias gsu='git submodule update --init --recursive' alias ga='git add'
alias gl='git pull' alias gall='git add -A'
alias gpl='git pull' alias gap='git add -p'
alias glum='git pull upstream master'
alias gpr='git pull --rebase' # branch
alias gpp='git pull && git push' alias gb='git branch'
alias gup='git fetch && git rebase' alias gbD='git branch -D'
alias gp='git push' alias gba='git branch -a'
alias gpd='git push --delete' alias gbd='git branch -d'
alias gpo='git push origin HEAD' alias gbm='git branch -m'
alias gpu='git push --set-upstream' alias gbt='git branch --track'
alias gpuo='git push --set-upstream origin' alias gdel='git branch -D'
alias gpuoc='git push --set-upstream origin $(git symbolic-ref --short HEAD)'
alias gpom='git push origin master' # for-each-ref
alias gr='git remote' 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
alias grv='git remote -v'
alias gra='git remote add' # commit
alias grb='git rebase' alias gc='git commit -v'
alias grm='git rebase master' alias gca='git commit -v -a'
alias grmi='git rebase master -i' 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 gd='git diff'
alias gds='git diff --staged' alias gds='git diff --staged'
alias gdt='git difftool' 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 # archive
alias gsr='git svn rebase' 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 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 case $OSTYPE in
darwin*) darwin*)
alias gtls="git tag -l | gsort -V" alias gtls="git tag -l | gsort -V"
;; ;;
*) *)
alias gtls='git tag -l | sort -V' alias gtls='git tag -l | sort -V'
;; ;;
esac esac
# functions
function gdv() {
git diff --ignore-all-space "$@" | vim -R -
}

View File

@ -1,3 +1,4 @@
# shellcheck shell=bash
cite 'about-alias' cite 'about-alias'
about-alias 'vim abbreviations' about-alias 'vim abbreviations'
@ -5,15 +6,20 @@ VIM=$(command -v vim)
GVIM=$(command -v gvim) GVIM=$(command -v gvim)
MVIM=$(command -v mvim) 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 # open vim in new tab is taken from
# http://stackoverflow.com/questions/936501/let-gvim-always-run-a-single-instancek # http://stackoverflow.com/questions/936501/let-gvim-always-run-a-single-instancek
case $OSTYPE in case $OSTYPE in
darwin*) darwin*)
[[ -n $MVIM ]] && function mvimt { command mvim --remote-tab-silent "$@" || command mvim "$@"; } [[ -n $MVIM ]] && function mvimt { command mvim --remote-tab-silent "$@" || command mvim "$@"; }
;; ;;
*) *)
[[ -n $GVIM ]] && function gvimt { command gvim --remote-tab-silent "$@" || command gvim "$@"; } [[ -n $GVIM ]] && function gvimt { command gvim --remote-tab-silent "$@" || command gvim "$@"; }
;; ;;
esac esac

View File

@ -74,6 +74,9 @@ if [[ ! -z "${BASH_IT_THEME}" ]]; then
BASH_IT_LOG_PREFIX="themes: p4helpers: " BASH_IT_LOG_PREFIX="themes: p4helpers: "
# shellcheck source=./themes/p4helpers.theme.bash # shellcheck source=./themes/p4helpers.theme.bash
source "${BASH_IT}/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: " BASH_IT_LOG_PREFIX="themes: base: "
# shellcheck source=./themes/base.theme.bash # shellcheck source=./themes/base.theme.bash
source "${BASH_IT}/themes/base.theme.bash" source "${BASH_IT}/themes/base.theme.bash"

View File

@ -17,20 +17,45 @@
# root directories # root directories
# #
docs docs
hooks
# root files # root files
# #
.gitattributes .gitattributes
lint_clean_files.sh 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
# #
themes/agnoster
themes/90210 themes/90210
themes/powerline themes/powerline
themes/barbuk
themes/atomic
themes/axin
themes/base.theme.bash
# plugins
#
plugins/available/basher.plugin.bash
# completions # completions
# #
completion/available/cargo.completion.bash completion/available/cargo.completion.bash
completion/available/knife.completion.bash completion/available/knife.completion.bash
completion/available/packer.completion.bash
completion/available/pipx.completion.bash completion/available/pipx.completion.bash
completion/available/rustup.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

View File

@ -1,6 +1,27 @@
#!/usr/bin/env bash #!/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 # repo: https://github.com/vigo/apm-bash-completion
__apm(){ __apm(){

View File

@ -1,9 +1,28 @@
#! bash #! bash
# bash completion for the `bundle` command. # bash completion for the `bundle` command.
# #
# Copyright (c) 2011-2017 Daniel Luz <dev at mernen dot com>. # Copyright (c) 2008 Daniel Luz
# Distributed under the MIT license.
# http://mernen.com/projects/completion-ruby # 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: # To use, source this file on bash:
# . completion-bundle # . completion-bundle

View File

@ -1,5 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# cargo (Rust package manager) completion # cargo (Rust package manager) completion
if _binary_exists rustup && _binary_exists cargo; then if _binary_exists rustup && _binary_exists cargo; then

View File

@ -30,6 +30,36 @@
# ============ # ============
# #
# To uninstall, just remove the line from your .bash_profile and .bashrc. # 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() _django_completion()
{ {

View File

@ -1,5 +1,20 @@
#!/bin/bash #!/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 # bash completion for docker-compose
# #
# This work is based on the completion for the docker command. # This work is based on the completion for the docker command.

View File

@ -1,5 +1,20 @@
# #
# bash completion file for docker-machine commands # 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: # This script provides completion of:
# - commands and their options # - commands and their options

View File

@ -1,37 +1,2 @@
#!/usr/bin/env bash _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.'
# 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

View File

@ -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 ':' # Bash breaks words on : by default. Subproject tasks have ':'
# Avoid inaccurate completions for subproject tasks # Avoid inaccurate completions for subproject tasks
COMP_WORDBREAKS=$(echo "$COMP_WORDBREAKS" | sed -e 's/://g') COMP_WORDBREAKS=$(echo "$COMP_WORDBREAKS" | sed -e 's/://g')

View File

@ -3,9 +3,35 @@
# grunt-cli # grunt-cli
# http://gruntjs.com/ # http://gruntjs.com/
# #
# Copyright (c) 2012 Tyler Kellen, contributors # Copyright jQuery Foundation and other contributors, https://jquery.org/
# Licensed under the MIT license.
# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT # 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: # Usage:
# #

View File

@ -2,9 +2,36 @@
# Borrowed from grunt-cli # Borrowed from grunt-cli
# http://gruntjs.com/ # http://gruntjs.com/
# #
# Copyright (c) 2012 Tyler Kellen, contributors # Copyright jQuery Foundation and other contributors, https://jquery.org/
# Licensed under the MIT license.
# https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT # 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: # Usage:
# #
# To enable bash <tab> completion for gulp, add the following line (minus the # To enable bash <tab> completion for gulp, add the following line (minus the

View File

@ -1,59 +1,2 @@
# Bash completion script for 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.'
# 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

View File

@ -1,6 +1,27 @@
# hub tab-completion script for bash. # hub tab-completion script for bash.
# This script complements the completion script that ships with git. # 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 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 if ! declare -F _git > /dev/null && declare -F _completion_loader > /dev/null; then
_completion_loader git _completion_loader git

View File

@ -1,4 +1,28 @@
# Invoke (pyinvoke.org) tab-completion script to be sourced with Bash shell. # 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 # https://github.com/pyinvoke/invoke/blob/master/completion/bash
_complete_invoke() { _complete_invoke() {

View File

@ -3,8 +3,27 @@
# DATE: 2012-10-30 # DATE: 2012-10-30
# rparree-at-edc4it-dot-com # 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(){ _serverProfiles(){
if [[ $COMP_WORDS == *standalone.sh* ]] if [[ $COMP_WORDS == *standalone.sh* ]]

View File

@ -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 # Published originally as public domain code at https://github.com/wk8/knife-bash-autocomplete

View File

@ -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 if _binary_exists packer; then
# complete -C packer packer
# This script provides bash completion for packer and supports: fi
#
# - 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 <spearce@spearce.org> 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

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# pipx completion # pipx completion
if _command_exists register-python-argcomplete && _command_exists pipx; then if _command_exists register-python-argcomplete && _command_exists pipx; then

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# rustup (Rust toolchain installer) completion # rustup (Rust toolchain installer) completion

View File

@ -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 # written by David Pravec
# - feel free to /msg alekibango on IRC if you want to talk about this file # - feel free to /msg alekibango on IRC if you want to talk about this file

View File

@ -1,71 +1,83 @@
_sdkman_complete() # shellcheck shell=bash
{ _sdkman_complete() {
local CANDIDATES local CANDIDATES
local CANDIDATE_VERSIONS local CANDIDATE_VERSIONS
COMPREPLY=() COMPREPLY=()
if [ $COMP_CWORD -eq 1 ]; then 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]}) ) 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 elif [ "$COMP_CWORD" -eq 2 ]; then
case "${COMP_WORDS[COMP_CWORD-1]}" in case "${COMP_WORDS[COMP_CWORD - 1]}" in
"install" | "uninstall" | "rm" | "list" | "ls" | "use" | "current" | "outdated" ) "install" | "i" | "uninstall" | "rm" | "list" | "ls" | "use" | "u" | "default" | "d" | "home" | "h" | "current" | "c" | "upgrade" | "ug")
CANDIDATES=$(echo "${SDKMAN_CANDIDATES_CSV}" | tr ',' ' ') CANDIDATES=$(echo "${SDKMAN_CANDIDATES_CSV}" | tr ',' ' ')
COMPREPLY=( $(compgen -W "$CANDIDATES" -- ${COMP_WORDS[COMP_CWORD]}) ) mapfile -t COMPREPLY < <(compgen -W "$CANDIDATES" -- "${COMP_WORDS[COMP_CWORD]}")
;; ;;
"offline" ) "env")
COMPREPLY=( $(compgen -W "enable disable" -- ${COMP_WORDS[COMP_CWORD]}) ) mapfile -t COMPREPLY < <(compgen -W "init" -- "${COMP_WORDS[COMP_CWORD]}")
;; ;;
"selfupdate" ) "offline")
COMPREPLY=( $(compgen -W "force" -P "[" -S "]" -- ${COMP_WORDS[COMP_CWORD]}) ) mapfile -t COMPREPLY < <(compgen -W "enable disable" -- "${COMP_WORDS[COMP_CWORD]}")
;; ;;
"flush" ) "selfupdate")
COMPREPLY=( $(compgen -W "candidates broadcast archives temp" -- ${COMP_WORDS[COMP_CWORD]}) ) mapfile -t COMPREPLY < <(compgen -W "force" -- "${COMP_WORDS[COMP_CWORD]}")
;; ;;
*) "flush")
;; mapfile -t COMPREPLY < <(compgen -W "archives tmp broadcast version" -- "${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
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) CANDIDATE_VERSIONS=$(__sdkman_cleanup_local_versions "$1")
if [ "$SDKMAN_OFFLINE_MODE" = "true" ]; then
CANDIDATE_VERSIONS=$CANDIDATE_LOCAL_VERSIONS
else
CANDIDATE_ONLINE_VERSIONS="$(curl -s "${SDKMAN_SERVICE}/candidates/$1" | tr ',' ' ')"
CANDIDATE_VERSIONS="$(echo $CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS |sort | uniq ) "
fi
} }
_sdkman_candidate_not_installed_versions(){ _sdkman_candidate_all_versions() {
CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions $1)
if [ "$SDKMAN_OFFLINE_MODE" = "false" ]; then candidate="$1"
CANDIDATE_ONLINE_VERSIONS="$(__sdkman_list_versions $1 | grep " " | grep "\." | cut -c 6-)" CANDIDATE_LOCAL_VERSIONS=$(__sdkman_cleanup_local_versions "$candidate")
CANDIDATE_VERSIONS="$(echo $CANDIDATE_ONLINE_VERSIONS $CANDIDATE_LOCAL_VERSIONS | tr ' ' '\n' | sort | uniq -u) " if [ "$SDKMAN_OFFLINE_MODE" = "true" ]; then
fi 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 ',' ' '
} }

View File

@ -3,7 +3,6 @@
# tmux completion # tmux completion
# See: http://www.debian-administration.org/articles/317 for how to write more. # See: http://www.debian-administration.org/articles/317 for how to write more.
# Usage: Put "source bash_completion_tmux.sh" into your .bashrc # Usage: Put "source bash_completion_tmux.sh" into your .bashrc
# Based upon the example at http://paste-it.appspot.com/Pj4mLycDE
_tmux_expand () _tmux_expand ()
{ {

View File

@ -1,70 +1,2 @@
# link: https://github.com/ginatrapani/todo.txt-cli/blob/master/todo_completion _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.'
_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

View File

@ -1,51 +1,7 @@
# --------------------------------------------------------------------------- # shellcheck shell=bash
# vault-bash-completion cite "about-completion"
# about-completion "vault completion"
# This adds bash completions for [HashiCorp Vault](https://www.vaultproject.io/)
#
# see https://github.com/iljaweis/vault-bash-completion
# ---------------------------------------------------------------------------
function _vault_mounts() { if _binary_exists vault; then
( complete -C vault vault
set -euo pipefail fi
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

View File

@ -1,148 +1,2 @@
#!/usr/bin/env bash _log_error 'Bash completion for "virsh" is now deprecated, as it used code with incompatible license.
# bash completion for virsh - main CLI of libvirt Please disable this completion and use the instructions from "virsh" developers instead.'
# 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

View File

@ -1,14 +1,48 @@
#!/usr/bin/bash #!/usr/bin/bash
if command -v vue > /dev/null; then if _command_exists vue; then
__vuejs_completion() { __vuejs_completion() {
local OPTS=("--version --help create add invoke inspect serve build ui init config upgrade info") local prev=$(_get_pword)
COMPREPLY=() local curr=$(_get_cword)
for _opt_ in ${OPTS[@]}; do
if [[ "$_opt_" == "$2"* ]]; then case $prev in
COMPREPLY+=("$_opt_") create)
fi 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"))
done ;;
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 complete -F __vuejs_completion vue

View File

@ -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. * 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... 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. * 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. * 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 <http://EditorConfig.org>`_\ , the editor should automatically use the settings defined in Bash-it's `.editorconfig file <.editorconfig>`_. If you're using an editor that supports `EditorConfig <http://EditorConfig.org>`_\ , 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``. * 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``. 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``. * 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. 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. 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 <https://travis-ci.org/Bash-it/bash-it>`_\ , where the test suite is run on both Linux and macOS. Any code pushed to GitHub as part of a Pull Request will automatically trigger a continuous integration build on `GitHub Actions <https://github.com/Bash-it/bash-it/actions>`_\ , 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. 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. 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. Adding new functionality or changing existing functionality is a good opportunity to increase Bash-it's test coverage.

View File

@ -38,6 +38,7 @@ Default theme glyphs
BARBUK_SVN_CHAR='⑆ ' BARBUK_SVN_CHAR='⑆ '
BARBUK_EXIT_CODE_ICON=' ' BARBUK_EXIT_CODE_ICON=' '
BARBUK_PYTHON_VENV_CHAR=' ' BARBUK_PYTHON_VENV_CHAR=' '
BARBUK_COMMAND_DURATION_ICON='  '
Customize glyphs Customize glyphs
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -92,6 +93,11 @@ Please refer to the following documentation for more information:
EOF EOF
chmod 400 /etc/sudoers.d/keepenv chmod 400 /etc/sudoers.d/keepenv
Command duration
----------------
See :ref:`Command duration <command_duration>`.
Examples Examples
-------- --------
@ -122,3 +128,11 @@ Python venv
.. code-block:: bash .. code-block:: bash
  flask ~/test on  master ✓   flask ~/test on  master ✓
Command duration
^^^^^^^^^^^^^^^^
.. code-block:: bash
# sleep 3s
user@hostname in  ~/bash-it on  master ✓  3.2s

View File

@ -37,6 +37,29 @@ See :ref:`here <list_of_themes>`.
Theme Switches & Variables 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 Clock Related
============= =============

21
hooks/dot-bash.sh 100755
View File

@ -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

21
hooks/dot-sh.sh 100755
View File

@ -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

View File

@ -346,6 +346,11 @@ _bash-it-version() {
BASH_IT_GIT_REMOTE=$(git remote get-url $BASH_IT_REMOTE) BASH_IT_GIT_REMOTE=$(git remote get-url $BASH_IT_REMOTE)
BASH_IT_GIT_URL=${BASH_IT_GIT_REMOTE%.git} 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) current_tag=$(git describe --exact-match --tags 2> /dev/null)

View File

@ -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
}

View File

@ -91,5 +91,5 @@ function alias_completion {
echo "$new_completion" >> "$tmp_file" echo "$new_completion" >> "$tmp_file"
fi fi
done < <(alias -p | sed -Ene "s/$alias_regex/\2 '\3' '\4'/p") 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 }; alias_completion

View File

@ -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)"

View File

@ -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

View File

@ -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

View File

@ -1,9 +1,39 @@
# shellcheck shell=bash
cite about-plugin cite about-plugin
about-plugin 'history manipulation' about-plugin 'improve history handling with sane defaults'
# enter a few characters and press UpArrow/DownArrow
# to search backwards/forwards through the history # append to bash_history if Terminal.app quits
if [[ ${SHELLOPTS} =~ (vi|emacs) ]] shopt -s histappend
then
bind '"":history-search-backward' # erase duplicates; alternative option: export HISTCONTROL=ignoredups
bind '"":history-search-forward' export HISTCONTROL=${HISTCONTROL:-ignorespace:erasedups}
fi
# 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 ' | '
}

View File

@ -51,6 +51,13 @@ export SCM_CHECK=true
# Will otherwise fall back on $USER. # Will otherwise fall back on $USER.
#export SHORT_USER=${USER:0:8} #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. # Set Xterm/screen/Tmux title with shortened command and directory.
# Uncomment this to set. # Uncomment this to set.
#export SHORT_TERM_LINE=true #export SHORT_TERM_LINE=true

View File

@ -7,7 +7,7 @@ load ../../lib/helpers
cite _about _param _example _group _author _version 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" { @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" 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 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
}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
SCM_THEME_PROMPT_DIRTY=" ${red}" SCM_THEME_PROMPT_DIRTY=" ${red}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}" SCM_THEME_PROMPT_CLEAN=" ${bold_green}"
SCM_THEME_PROMPT_PREFIX=" |" SCM_THEME_PROMPT_PREFIX=" |"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# vim: ft=bash ts=2 sw=2 sts=2 # vim: ft=bash ts=2 sw=2 sts=2
# #
# agnoster's Theme - https://gist.github.com/3712874 # agnoster's Theme - https://gist.github.com/3712874
@ -70,9 +70,9 @@ PROMPT_DIRTRIM=2 # bash4 and above
###################################################################### ######################################################################
DEBUG=0 DEBUG=0
debug() { debug() {
if [[ ${DEBUG} -ne 0 ]]; then if [[ ${DEBUG} -ne 0 ]]; then
>&2 echo -e $* echo >&2 -e "$@"
fi fi
} }
###################################################################### ######################################################################
@ -87,178 +87,176 @@ LEFT_SUBSEG=''
RIGHT_SUBSEG='' RIGHT_SUBSEG=''
text_effect() { text_effect() {
case "$1" in case "$1" in
reset) echo 0;; reset) echo 0 ;;
bold) echo 1;; bold) echo 1 ;;
underline) echo 4;; underline) echo 4 ;;
esac esac
} }
# to add colors, see # to add colors, see
# http://bitmote.com/index.php?post/2012/11/19/Using-ANSI-Color-Codes-to-Colorize-Your-Bash-Prompt-on-Linux # 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 # under the "256 (8-bit) Colors" section, and follow the example for orange below
fg_color() { fg_color() {
case "$1" in case "$1" in
black) echo 30;; black) echo 30 ;;
red) echo 31;; red) echo 31 ;;
green) echo 32;; green) echo 32 ;;
yellow) echo 33;; yellow) echo 33 ;;
blue) echo 34;; blue) echo 34 ;;
magenta) echo 35;; magenta) echo 35 ;;
cyan) echo 36;; cyan) echo 36 ;;
white) echo 37;; white) echo 37 ;;
orange) echo 38\;5\;166;; orange) echo 38\;5\;166 ;;
esac esac
} }
bg_color() { bg_color() {
case "$1" in case "$1" in
black) echo 40;; black) echo 40 ;;
red) echo 41;; red) echo 41 ;;
green) echo 42;; green) echo 42 ;;
yellow) echo 43;; yellow) echo 43 ;;
blue) echo 44;; blue) echo 44 ;;
magenta) echo 45;; magenta) echo 45 ;;
cyan) echo 46;; cyan) echo 46 ;;
white) echo 47;; white) echo 47 ;;
orange) echo 48\;5\;166;; orange) echo 48\;5\;166 ;;
esac; esac
} }
# TIL: declare is global not local, so best use a different name # TIL: declare is global not local, so best use a different name
# for codes (mycodes) as otherwise it'll clobber the original. # for codes (mycodes) as otherwise it'll clobber the original.
# this changes from BASH v3 to BASH v4. # this changes from BASH v3 to BASH v4.
ansi() { ansi() {
local seq local seq
declare -a mycodes=("${!1}") declare -a mycodes=("${!1}")
debug "ansi: ${!1} all: $* aka ${mycodes[@]}" debug "ansi: ${!1} all: $* aka " "${mycodes[@]}"
seq="" seq=""
for ((i = 0; i < ${#mycodes[@]}; i++)); do for ((i = 0; i < ${#mycodes[@]}; i++)); do
if [[ -n $seq ]]; then if [[ -n $seq ]]; then
seq="${seq};" seq="${seq};"
fi fi
seq="${seq}${mycodes[$i]}" seq="${seq}${mycodes[$i]}"
done done
debug "ansi debug:" '\\[\\033['${seq}'m\\]' debug "ansi debug:" '\\[\\033['"${seq}"'m\\]'
echo -ne '\[\033['${seq}'m\]' echo -ne '\[\033['"${seq}"'m\]'
# PR="$PR\[\033[${seq}m\]" # PR="$PR\[\033[${seq}m\]"
} }
ansi_single() { ansi_single() {
echo -ne '\[\033['$1'm\]' echo -ne '\[\033['"$1"'m\]'
} }
# Begin a segment # Begin a segment
# Takes two arguments, background and foreground. Both can be omitted, # Takes two arguments, background and foreground. Both can be omitted,
# rendering default background/foreground. # rendering default background/foreground.
prompt_segment() { prompt_segment() {
local bg fg local bg fg
declare -a codes 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 commented out from kruton's original... I'm not clear
# if it did anything, but it messed up things like # if it did anything, but it messed up things like
# prompt_status - Erik 1/14/17 # prompt_status - Erik 1/14/17
# if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then
codes=("${codes[@]}" $(text_effect reset)) codes=("${codes[@]}" "$(text_effect reset)")
# fi # fi
if [[ -n $1 ]]; then if [[ -n $1 ]]; then
bg=$(bg_color $1) bg=$(bg_color "$1")
codes=("${codes[@]}" $bg) codes=("${codes[@]}" "$bg")
debug "Added $bg as background to codes" debug "Added $bg as background to codes"
fi fi
if [[ -n $2 ]]; then if [[ -n $2 ]]; then
fg=$(fg_color $2) fg=$(fg_color "$2")
codes=("${codes[@]}" $fg) codes=("${codes[@]}" "$fg")
debug "Added $fg as foreground to codes" debug "Added $fg as foreground to codes"
fi fi
debug "Codes: " debug "Codes: "
# declare -p codes # declare -p codes
if [[ $CURRENT_BG != NONE && $1 != $CURRENT_BG ]]; then if [[ $CURRENT_BG != NONE && $1 != "$CURRENT_BG" ]]; then
declare -a intermediate=($(fg_color $CURRENT_BG) $(bg_color $1)) declare -a intermediate=("$(fg_color $CURRENT_BG)" "$(bg_color "$1")")
debug "pre prompt " $(ansi intermediate[@]) debug "pre prompt " "$(ansi intermediate[@])"
PR="$PR $(ansi intermediate[@])$SEGMENT_SEPARATOR" PR="$PR $(ansi intermediate[@])$SEGMENT_SEPARATOR"
debug "post prompt " $(ansi codes[@]) debug "post prompt " "$(ansi codes[@])"
PR="$PR$(ansi codes[@]) " PR="$PR$(ansi codes[@]) "
else else
debug "no current BG, codes is $codes[@]" debug "no current BG, codes is " "${codes[@]}"
PR="$PR$(ansi codes[@]) " PR="$PR$(ansi codes[@]) "
fi fi
CURRENT_BG=$1 CURRENT_BG=$1
[[ -n $3 ]] && PR="$PR$3" [[ -n $3 ]] && PR="$PR$3"
} }
# End the prompt, closing any open segments # End the prompt, closing any open segments
prompt_end() { prompt_end() {
if [[ -n $CURRENT_BG ]]; then if [[ -n $CURRENT_BG ]]; then
declare -a codes=($(text_effect reset) $(fg_color $CURRENT_BG)) declare -a codes=("$(text_effect reset)" "$(fg_color "$CURRENT_BG")")
PR="$PR $(ansi codes[@])$SEGMENT_SEPARATOR" PR="$PR $(ansi codes[@])$SEGMENT_SEPARATOR"
fi fi
declare -a reset=($(text_effect reset)) declare -a reset=("$(text_effect reset)")
PR="$PR $(ansi reset[@])" PR="$PR $(ansi reset[@])"
CURRENT_BG='' CURRENT_BG=''
} }
### virtualenv prompt ### virtualenv prompt
prompt_virtualenv() { prompt_virtualenv() {
if [[ -n $VIRTUAL_ENV ]]; then if [[ -n $VIRTUAL_ENV ]]; then
color=cyan color=cyan
prompt_segment $color $PRIMARY_FG prompt_segment $color "$PRIMARY_FG"
ve=`basename "$VIRTUAL_ENV"` ve=$(basename "$VIRTUAL_ENV")
prompt_segment $color white "$ve" prompt_segment $color white "$ve"
fi fi
} }
### Prompt components ### Prompt components
# Each component will draw itself, and hide itself if no information needs to be shown # 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) # Context: user@hostname (who am I and where am I)
prompt_context() { prompt_context() {
local user=`whoami` local user=$(whoami)
if [[ $user != $DEFAULT_USER || -n $SSH_CLIENT ]]; then if [[ $user != "$DEFAULT_USER" || -n $SSH_CLIENT ]]; then
prompt_segment black default "$user@\h" prompt_segment black default "$user@\h"
fi fi
} }
# prints history followed by HH:MM, useful for remembering what # prints history followed by HH:MM, useful for remembering what
# we did previously # we did previously
prompt_histdt() { prompt_histdt() {
prompt_segment black default "\! [\A]" prompt_segment black default "\! [\A]"
} }
git_status_dirty() { git_status_dirty() {
dirty=$(git status -s 2> /dev/null | tail -n 1) dirty=$(git status -s 2> /dev/null | tail -n 1)
[[ -n $dirty ]] && echo " ●" [[ -n $dirty ]] && echo " ●"
} }
# Git: branch/detached head, dirty status # Git: branch/detached head, dirty status
prompt_git() { prompt_git() {
local ref dirty local ref dirty
if $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
ZSH_THEME_GIT_PROMPT_DIRTY='±' ZSH_THEME_GIT_PROMPT_DIRTY='±'
dirty=$(git_status_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)" ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="$(git show-ref --head -s --abbrev | head -n1 2> /dev/null)"
if [[ -n $dirty ]]; then if [[ -n $dirty ]]; then
prompt_segment yellow black prompt_segment yellow black
else else
prompt_segment green black prompt_segment green black
fi fi
PR="$PR${ref/refs\/heads\// }$dirty" PR="$PR${ref/refs\/heads\// }$dirty"
fi fi
} }
# Dir: current working directory # Dir: current working directory
prompt_dir() { prompt_dir() {
prompt_segment blue black '\w' prompt_segment blue black '\w'
} }
# Status: # Status:
@ -266,13 +264,13 @@ prompt_dir() {
# - am I root # - am I root
# - are there background jobs? # - are there background jobs?
prompt_status() { prompt_status() {
local symbols local symbols
symbols=() symbols=()
[[ $RETVAL -ne 0 ]] && symbols+="$(ansi_single $(fg_color red))" [[ $RETVAL -ne 0 ]] && symbols+=("$(ansi_single "$(fg_color red)")")
[[ $UID -eq 0 ]] && symbols+="$(ansi_single $(fg_color yellow))" [[ $UID -eq 0 ]] && symbols+=("$(ansi_single "$(fg_color yellow)")")
[[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="$(ansi_single $(fg_color cyan))" [[ $(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 # doesn't quite work per above
rightprompt() { rightprompt() {
printf "%*s" $COLUMNS "$PRIGHT" printf "%*s" $COLUMNS "$PRIGHT"
} }
# quick right prompt I grabbed to test things. # quick right prompt I grabbed to test things.
__command_rprompt() { __command_rprompt() {
local times= n=$COLUMNS tz local times=n=$COLUMNS tz
for tz in ZRH:Europe/Zurich PIT:US/Eastern \ for tz in ZRH:Europe/Zurich PIT:US/Eastern \
MTV:US/Pacific TOK:Asia/Tokyo; do MTV:US/Pacific TOK:Asia/Tokyo; do
[ $n -gt 40 ] || break [ "$n" -gt 40 ] || break
times="$times ${tz%%:*}\e[30;1m:\e[0;36;1m" times="$times ${tz%%:*}\e[30;1m:\e[0;36;1m"
times="$times$(TZ=${tz#*:} date +%H:%M)\e[0m" times="$times$(TZ=${tz#*:} date +%H:%M)\e[0m"
n=$(( $n - 10 )) n=$(("$n" - 10))
done done
[ -z "$times" ] || printf "%${n}s$times\\r" '' [ -z "$times" ] || printf "%${n}s$times\\r" ''
} }
# PROMPT_COMMAND=__command_rprompt # PROMPT_COMMAND=__command_rprompt
# this doens't wrap code in \[ \] # this doens't wrap code in \[ \]
ansi_r() { ansi_r() {
local seq local seq
declare -a mycodes2=("${!1}") declare -a mycodes2=("${!1}")
debug "ansi: ${!1} all: $* aka ${mycodes2[@]}" debug "ansi: ${!1} all: $* aka " "${mycodes2[@]}"
seq="" seq=""
for ((i = 0; i < ${#mycodes2[@]}; i++)); do for ((i = 0; i < ${#mycodes2[@]}; i++)); do
if [[ -n $seq ]]; then if [[ -n $seq ]]; then
seq="${seq};" seq="${seq};"
fi fi
seq="${seq}${mycodes2[$i]}" seq="${seq}${mycodes2[$i]}"
done done
debug "ansi debug:" '\\[\\033['${seq}'m\\]' debug "ansi debug:" '\\[\\033['"${seq}"'m\\]'
echo -ne '\033['${seq}'m' echo -ne '\033['"${seq}"'m'
# PR="$PR\[\033[${seq}m\]" # PR="$PR\[\033[${seq}m\]"
} }
# Begin a segment on the right # Begin a segment on the right
# Takes two arguments, background and foreground. Both can be omitted, # Takes two arguments, background and foreground. Both can be omitted,
# rendering default background/foreground. # rendering default background/foreground.
prompt_right_segment() { prompt_right_segment() {
local bg fg local bg fg
declare -a codes declare -a codes
debug "Prompt right" debug "Prompt right"
debug "Prompting $1 $2 $3" debug "Prompting $1 $2 $3"
# if commented out from kruton's original... I'm not clear # if commented out from kruton's original... I'm not clear
# if it did anything, but it messed up things like # if it did anything, but it messed up things like
# prompt_status - Erik 1/14/17 # prompt_status - Erik 1/14/17
# if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then # if [[ -z $1 || ( -z $2 && $2 != default ) ]]; then
codes=("${codes[@]}" $(text_effect reset)) codes=("${codes[@]}" "$(text_effect reset)")
# fi # fi
if [[ -n $1 ]]; then if [[ -n $1 ]]; then
bg=$(bg_color $1) bg=$(bg_color "$1")
codes=("${codes[@]}" $bg) codes=("${codes[@]}" "$bg")
debug "Added $bg as background to codes" debug "Added $bg as background to codes"
fi fi
if [[ -n $2 ]]; then if [[ -n $2 ]]; then
fg=$(fg_color $2) fg=$(fg_color "$2")
codes=("${codes[@]}" $fg) codes=("${codes[@]}" "$fg")
debug "Added $fg as foreground to codes" debug "Added $fg as foreground to codes"
fi fi
debug "Right Codes: " debug "Right Codes: "
# declare -p codes # declare -p codes
# right always has a separator # right always has a separator
# if [[ $CURRENT_RBG != NONE && $1 != $CURRENT_RBG ]]; then # if [[ $CURRENT_RBG != NONE && $1 != $CURRENT_RBG ]]; then
# $CURRENT_RBG= # $CURRENT_RBG=
# fi # fi
declare -a intermediate2=($(fg_color $1) $(bg_color $CURRENT_RBG) ) declare -a intermediate2=("$(fg_color "$1")" "$(bg_color $CURRENT_RBG)")
# PRIGHT="$PRIGHT---" # PRIGHT="$PRIGHT---"
debug "pre prompt " $(ansi_r intermediate2[@]) debug "pre prompt " "$(ansi_r intermediate2[@])"
PRIGHT="$PRIGHT$(ansi_r intermediate2[@])$RIGHT_SEPARATOR" PRIGHT="$PRIGHT$(ansi_r intermediate2[@])$RIGHT_SEPARATOR"
debug "post prompt " $(ansi_r codes[@]) debug "post prompt " "$(ansi_r codes[@])"
PRIGHT="$PRIGHT$(ansi_r codes[@]) " PRIGHT="$PRIGHT$(ansi_r codes[@]) "
# else # else
# debug "no current BG, codes is $codes[@]" # debug "no current BG, codes is $codes[@]"
# PRIGHT="$PRIGHT$(ansi codes[@]) " # PRIGHT="$PRIGHT$(ansi codes[@]) "
# fi # fi
CURRENT_RBG=$1 CURRENT_RBG=$1
[[ -n $3 ]] && PRIGHT="$PRIGHT$3" [[ -n $3 ]] && PRIGHT="$PRIGHT$3"
} }
###################################################################### ######################################################################
@ -385,22 +383,22 @@ prompt_right_segment() {
# 'dirtrack-filter-out-pwd-prompt t t))) # 'dirtrack-filter-out-pwd-prompt t t)))
prompt_emacsdir() { prompt_emacsdir() {
# no color or other setting... this will be deleted per above # no color or other setting... this will be deleted per above
PR="DIR \w DIR$PR" PR="DIR \w DIR$PR"
} }
###################################################################### ######################################################################
## Main prompt ## Main prompt
build_prompt() { build_prompt() {
[[ ! -z ${AG_EMACS_DIR+x} ]] && prompt_emacsdir [[ -n ${AG_EMACS_DIR+x} ]] && prompt_emacsdir
prompt_status prompt_status
#[[ -z ${AG_NO_HIST+x} ]] && prompt_histdt #[[ -z ${AG_NO_HIST+x} ]] && prompt_histdt
[[ -z ${AG_NO_CONTEXT+x} ]] && prompt_context [[ -z ${AG_NO_CONTEXT+x} ]] && prompt_context
prompt_virtualenv prompt_virtualenv
prompt_dir prompt_dir
prompt_git prompt_git
prompt_end prompt_end
} }
# from orig... # from orig...
@ -409,16 +407,16 @@ build_prompt() {
# use that. # use that.
set_bash_prompt() { set_bash_prompt() {
RETVAL=$? RETVAL=$?
PR="" PR=""
PRIGHT="" PRIGHT=""
CURRENT_BG=NONE CURRENT_BG=NONE
PR="$(ansi_single $(text_effect reset))" PR="$(ansi_single "$(text_effect reset)")"
build_prompt build_prompt
# uncomment below to use right prompt # uncomment below to use right prompt
# PS1='\[$(tput sc; printf "%*s" $COLUMNS "$PRIGHT"; tput rc)\]'$PR # PS1='\[$(tput sc; printf "%*s" $COLUMNS "$PRIGHT"; tput rc)\]'$PR
PS1=$PR PS1=$PR
} }
PROMPT_COMMAND=set_bash_prompt PROMPT_COMMAND=set_bash_prompt

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# Atomic Bash Prompt for Bash-it # Atomic Bash Prompt for Bash-it
# By lfelipe base on the theme brainy of MunifTanjim # By lfelipe base on the theme brainy of MunifTanjim
@ -28,79 +28,79 @@ Face="\342\230\273"
############# #############
____atomic_top_left_parse() { ____atomic_top_left_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) read -r -a args <<< "$@"
IFS="${ifs_old}" IFS="${ifs_old}"
if [ -n "${args[3]}" ]; then if [ -n "${args[3]}" ]; then
_TOP_LEFT+="${args[2]}${args[3]}" _TOP_LEFT+="${args[2]}${args[3]}"
fi fi
_TOP_LEFT+="${args[0]}${args[1]}" _TOP_LEFT+="${args[0]}${args[1]}"
if [ -n "${args[4]}" ]; then if [ -n "${args[4]}" ]; then
_TOP_LEFT+="${args[2]}${args[4]}" _TOP_LEFT+="${args[2]}${args[4]}"
fi fi
_TOP_LEFT+="" _TOP_LEFT+=""
} }
____atomic_top_right_parse() { ____atomic_top_right_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) read -r -a args <<< "$@"
IFS="${ifs_old}" IFS="${ifs_old}"
_TOP_RIGHT+=" " _TOP_RIGHT+=" "
if [ -n "${args[3]}" ]; then if [ -n "${args[3]}" ]; then
_TOP_RIGHT+="${args[2]}${args[3]}" _TOP_RIGHT+="${args[2]}${args[3]}"
fi fi
_TOP_RIGHT+="${args[0]}${args[1]}" _TOP_RIGHT+="${args[0]}${args[1]}"
if [ -n "${args[4]}" ]; then if [ -n "${args[4]}" ]; then
_TOP_RIGHT+="${args[2]}${args[4]}" _TOP_RIGHT+="${args[2]}${args[4]}"
fi fi
__TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1 )) __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1))
(( __SEG_AT_RIGHT += 1 )) ((__SEG_AT_RIGHT += 1))
} }
____atomic_bottom_parse() { ____atomic_bottom_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) read -r -a args <<< "$@"
IFS="${ifs_old}" IFS="${ifs_old}"
_BOTTOM+="${args[0]}${args[1]}" _BOTTOM+="${args[0]}${args[1]}"
[ ${#args[1]} -gt 0 ] && _BOTTOM+=" " [ ${#args[1]} -gt 0 ] && _BOTTOM+=" "
} }
____atomic_top() { ____atomic_top() {
_TOP_LEFT="" _TOP_LEFT=""
_TOP_RIGHT="" _TOP_RIGHT=""
__TOP_RIGHT_LEN=0 __TOP_RIGHT_LEN=0
__SEG_AT_RIGHT=0 __SEG_AT_RIGHT=0
for seg in ${___ATOMIC_TOP_LEFT}; do for seg in ${___ATOMIC_TOP_LEFT}; do
info="$(___atomic_prompt_"${seg}")" info="$(___atomic_prompt_"${seg}")"
[ -n "${info}" ] && ____atomic_top_left_parse "${info}" [ -n "${info}" ] && ____atomic_top_left_parse "${info}"
done done
___cursor_right="\e[500C" ___cursor_right="\e[500C"
_TOP_LEFT+="${___cursor_right}" _TOP_LEFT+="${___cursor_right}"
for seg in ${___ATOMIC_TOP_RIGHT}; do for seg in ${___ATOMIC_TOP_RIGHT}; do
info="$(___atomic_prompt_"${seg}")" info="$(___atomic_prompt_"${seg}")"
[ -n "${info}" ] && ____atomic_top_right_parse "${info}" [ -n "${info}" ] && ____atomic_top_right_parse "${info}"
done done
[ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN - 0 )) [ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN - 0))
___cursor_adjust="\e[${__TOP_RIGHT_LEN}D" ___cursor_adjust="\e[${__TOP_RIGHT_LEN}D"
_TOP_LEFT+="${___cursor_adjust}" _TOP_LEFT+="${___cursor_adjust}"
printf "%s%s" "${_TOP_LEFT}" "${_TOP_RIGHT}" printf "%s%s" "${_TOP_LEFT}" "${_TOP_RIGHT}"
} }
____atomic_bottom() { ____atomic_bottom() {
_BOTTOM="" _BOTTOM=""
for seg in $___ATOMIC_BOTTOM; do for seg in $___ATOMIC_BOTTOM; do
info="$(___atomic_prompt_"${seg}")" info="$(___atomic_prompt_"${seg}")"
[ -n "${info}" ] && ____atomic_bottom_parse "${info}" [ -n "${info}" ] && ____atomic_bottom_parse "${info}"
done done
printf "\n%s" "${_BOTTOM}" printf "\n%s" "${_BOTTOM}"
} }
############## ##############
@ -108,97 +108,97 @@ ____atomic_bottom() {
############## ##############
___atomic_prompt_user_info() { ___atomic_prompt_user_info() {
color=$white color=$white
box="${normal}${LineA}\$([[ \$? != 0 ]] && echo \"${BIWhite}[${IRed}${SX}${BIWhite}]${normal}${Line}\")${Line}${BIWhite}[|${BIWhite}]${normal}${Line}" box="${normal}${LineA}\$([[ \$? != 0 ]] && echo \"${BIWhite}[${IRed}${SX}${BIWhite}]${normal}${Line}\")${Line}${BIWhite}[|${BIWhite}]${normal}${Line}"
info="${IYellow}\u${IRed}@${IGreen}\h" 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() { ___atomic_prompt_dir() {
color=${IRed} color=${IRed}
box="[|]${normal}" box="[|]${normal}"
info="\w" info="\w"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}"
} }
___atomic_prompt_scm() { ___atomic_prompt_scm() {
[ "${THEME_SHOW_SCM}" != "true" ] && return [ "${THEME_SHOW_SCM}" != "true" ] && return
color=$bold_green color=$bold_green
box="${Line}[${IWhite}$(scm_char)] " box="${Line}[${IWhite}$(scm_char)] "
info="$(scm_prompt_info)" info="$(scm_prompt_info)"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}"
} }
___atomic_prompt_python() { ___atomic_prompt_python() {
[ "${THEME_SHOW_PYTHON}" != "true" ] && return [ "${THEME_SHOW_PYTHON}" != "true" ] && return
color=$bold_yellow color=$bold_yellow
box="[|]" box="[|]"
info="$(python_version_prompt)" info="$(python_version_prompt)"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_blue}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_blue}" "${box}"
} }
___atomic_prompt_ruby() { ___atomic_prompt_ruby() {
[ "${THEME_SHOW_RUBY}" != "true" ] && return [ "${THEME_SHOW_RUBY}" != "true" ] && return
color=$bold_white color=$bold_white
box="[|]" box="[|]"
info="rb-$(ruby_version_prompt)" info="rb-$(ruby_version_prompt)"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_red}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_red}" "${box}"
} }
___atomic_prompt_todo() { ___atomic_prompt_todo() {
[ "${THEME_SHOW_TODO}" != "true" ] || [ "${THEME_SHOW_TODO}" != "true" ] \
[ -z "$(which todo.sh)" ] && return || [ -z "$(which todo.sh)" ] && return
color=$bold_white color=$bold_white
box="[|]" box="[|]"
info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }' )" 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}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}"
} }
___atomic_prompt_clock() { ___atomic_prompt_clock() {
[ "${THEME_SHOW_CLOCK}" != "true" ] && return [ "${THEME_SHOW_CLOCK}" != "true" ] && return
color=$THEME_CLOCK_COLOR color=$THEME_CLOCK_COLOR
box="[|]" box="[|]"
info="$(date +"${THEME_CLOCK_FORMAT}")" info="$(date +"${THEME_CLOCK_FORMAT}")"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}"
} }
___atomic_prompt_battery() { ___atomic_prompt_battery() {
! _command_exists battery_percentage || ! _command_exists battery_percentage \
[ "${THEME_SHOW_BATTERY}" != "true" ] || || [ "${THEME_SHOW_BATTERY}" != "true" ] \
[ "$(battery_percentage)" = "no" ] && return || [ "$(battery_percentage)" = "no" ] && return
batp=$(battery_percentage) batp=$(battery_percentage)
if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then
color=$bold_green color=$bold_green
elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then
color=$bold_yellow color=$bold_yellow
elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then
color=$IRed color=$IRed
fi fi
box="[|]" box="[|]"
ac_adapter_connected && info="+" ac_adapter_connected && info="+"
ac_adapter_disconnected && info="-" ac_adapter_disconnected && info="-"
info+=$batp info+=$batp
[ "$batp" -eq 100 ] || [ "$batp" -gt 100 ] && info="AC" [ "$batp" -eq 100 ] || [ "$batp" -gt 100 ] && info="AC"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_white}" "${box}"
} }
___atomic_prompt_exitcode() { ___atomic_prompt_exitcode() {
[ "${THEME_SHOW_EXITCODE}" != "true" ] && return [ "${THEME_SHOW_EXITCODE}" != "true" ] && return
color=$bold_purple color=$bold_purple
[ "$exitcode" -ne 0 ] && printf "%s|%s" "${color}" "${exitcode}" [ "$exitcode" -ne 0 ] && printf "%s|%s" "${color}" "${exitcode}"
} }
___atomic_prompt_char() { ___atomic_prompt_char() {
color=$white color=$white
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}" prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}"
if [ "${THEME_SHOW_SUDO}" == "true" ]; then if [ "${THEME_SHOW_SUDO}" == "true" ]; then
if sudo -vn 1>/dev/null 2>&1; then if sudo -vn 1> /dev/null 2>&1; then
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}" prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}"
fi fi
fi fi
printf "%s|%s" "${color}" "${prompt_char}" printf "%s|%s" "${color}" "${prompt_char}"
} }
######### #########
@ -206,54 +206,56 @@ ___atomic_prompt_char() {
######### #########
__atomic_show() { __atomic_show() {
typeset _seg=${1:-} typeset _seg=${1:-}
shift shift
export THEME_SHOW_${_seg}=true export "THEME_SHOW_${_seg}"=true
} }
__atomic_hide() { __atomic_hide() {
typeset _seg=${1:-} typeset _seg=${1:-}
shift shift
export THEME_SHOW_${_seg}=false export "THEME_SHOW_${_seg}"=false
} }
_atomic_completion() { _atomic_completion() {
local cur _action actions segments local cur _action actions segments
COMPREPLY=() COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
_action="${COMP_WORDS[1]}" _action="${COMP_WORDS[1]}"
actions="show hide" actions="show hide"
segments="battery clock exitcode python ruby scm sudo todo" segments="battery clock exitcode python ruby scm sudo todo"
case "${_action}" in case "${_action}" in
show) show)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) read -r -a COMPREPLY <<< "$(compgen -W "${segments}" -- "${cur}")"
return 0 return 0
;; ;;
hide) hide)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) read -r -a COMPREPLY <<< "$(compgen -W "${segments}" -- "${cur}")"
return 0 return 0
;; ;;
esac esac
COMPREPLY=( $(compgen -W "${actions}" -- "${cur}") ) read -r -a COMPREPLY <<< "$(compgen -W "${actions}" -- "${cur}")"
return 0 return 0
} }
atomic() { atomic() {
typeset action=${1:-} typeset action=${1:-}
shift shift
typeset segs=${*:-} typeset segs=${*:-}
typeset func typeset func
case $action in case $action in
show) show)
func=__atomic_show;; func=__atomic_show
hide) ;;
func=__atomic_hide;; hide)
esac func=__atomic_hide
for seg in ${segs}; do ;;
seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]') esac
$func "${seg}" for seg in ${segs}; do
done seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]')
$func "${seg}"
done
} }
complete -F _atomic_completion atomic complete -F _atomic_completion atomic
@ -302,19 +304,19 @@ ___ATOMIC_BOTTOM=${___ATOMIC_BOTTOM:-"char"}
############ ############
__atomic_ps1() { __atomic_ps1() {
printf "%s%s%s" "$(____atomic_top)" "$(____atomic_bottom)" "${normal}" printf "%s%s%s" "$(____atomic_top)" "$(____atomic_bottom)" "${normal}"
} }
__atomic_ps2() { __atomic_ps2() {
color=$bold_white color=$bold_white
printf "%s%s%s" "${color}" "${__ATOMIC_PROMPT_CHAR_PS2} " "${normal}" printf "%s%s%s" "${color}" "${__ATOMIC_PROMPT_CHAR_PS2} " "${normal}"
} }
_atomic_prompt() { _atomic_prompt() {
exitcode="$?" exitcode="$?"
PS1="$(__atomic_ps1)" PS1="$(__atomic_ps1)"
PS2="$(__atomic_ps2)" PS2="$(__atomic_ps2)"
} }
safe_append_prompt_command _atomic_prompt safe_append_prompt_command _atomic_prompt

View File

@ -1,36 +1,36 @@
#!/usr/bin/env bash # shellcheck shell=bash
# Axin Bash Prompt, inspired by theme "Sexy" and "Bobby" # Axin Bash Prompt, inspired by theme "Sexy" and "Bobby"
# thanks to them # thanks to them
if tput setaf 1 &> /dev/null; then if tput setaf 1 &> /dev/null; then
if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then if [[ $(tput colors) -ge 256 ]] 2> /dev/null; then
MAGENTA=$(tput setaf 9) MAGENTA=$(tput setaf 9)
ORANGE=$(tput setaf 172) ORANGE=$(tput setaf 172)
GREEN=$(tput setaf 190) GREEN=$(tput setaf 190)
PURPLE=$(tput setaf 141) PURPLE=$(tput setaf 141)
WHITE=$(tput setaf 0) WHITE=$(tput setaf 0)
else else
MAGENTA=$(tput setaf 5) MAGENTA=$(tput setaf 5)
ORANGE=$(tput setaf 4) ORANGE=$(tput setaf 4)
GREEN=$(tput setaf 2) GREEN=$(tput setaf 2)
PURPLE=$(tput setaf 1) PURPLE=$(tput setaf 1)
WHITE=$(tput setaf 7) WHITE=$(tput setaf 7)
fi fi
BOLD=$(tput bold) BOLD=$(tput bold)
RESET=$(tput sgr0) RESET=$(tput sgr0)
else else
MAGENTA="\033[1;31m" MAGENTA="\033[1;31m"
ORANGE="\033[1;33m" ORANGE="\033[1;33m"
GREEN="\033[1;32m" GREEN="\033[1;32m"
PURPLE="\033[1;35m" PURPLE="\033[1;35m"
WHITE="\033[1;37m" WHITE="\033[1;37m"
BOLD="" BOLD=""
RESET="\033[m" RESET="\033[m"
fi fi
function prompt_command() { 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}"} THEME_CLOCK_COLOR=${THEME_CLOCK_COLOR:-"${white}"}

View File

@ -0,0 +1 @@
../../docs/themes-list/barbuk.rst

View File

@ -1,5 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# shellcheck disable=2034,2154
# Theme custom glyphs # Theme custom glyphs
SCM_GIT_CHAR_GITLAB=${BARBUK_GITLAB_CHAR:=' '} SCM_GIT_CHAR_GITLAB=${BARBUK_GITLAB_CHAR:=' '}
@ -11,6 +10,11 @@ SCM_HG_CHAR=${BARBUK_HG_CHAR:='☿ '}
SCM_SVN_CHAR=${BARBUK_SVN_CHAR:='⑆ '} SCM_SVN_CHAR=${BARBUK_SVN_CHAR:='⑆ '}
EXIT_CODE_ICON=${BARBUK_EXIT_CODE_ICON:=' '} EXIT_CODE_ICON=${BARBUK_EXIT_CODE_ICON:=' '}
PYTHON_VENV_CHAR=${BARBUK_PYTHON_VENV_CHAR:=' '} 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 user and hostname display
SSH_INFO=${BARBUK_SSH_INFO:=true} SSH_INFO=${BARBUK_SSH_INFO:=true}
@ -36,70 +40,71 @@ SCM_THEME_CURRENT_USER_PREFFIX='  '
SCM_GIT_SHOW_CURRENT_USER=false SCM_GIT_SHOW_CURRENT_USER=false
function _git-uptream-remote-logo { 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 local remote remote_domain
remote=$(_git-upstream-remote) remote=$(_git-upstream-remote)
remote_domain=$(git config --get remote."$remote".url | awk -F'[@:.]' '{print $2}') remote_domain=$(git config --get remote."$remote".url | awk -F'[@:.]' '{print $2}')
# remove // suffix for https:// url # remove // suffix for https:// url
remote_domain=${remote_domain//\//} remote_domain=${remote_domain//\//}
case $remote_domain in case $remote_domain in
github ) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITHUB";; github) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITHUB" ;;
gitlab ) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITLAB";; gitlab) SCM_GIT_CHAR="$SCM_GIT_CHAR_GITLAB" ;;
bitbucket ) SCM_GIT_CHAR="$SCM_GIT_CHAR_BITBUCKET";; bitbucket) SCM_GIT_CHAR="$SCM_GIT_CHAR_BITBUCKET" ;;
* ) SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT";; *) SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT" ;;
esac esac
} }
function git_prompt_info { function git_prompt_info {
git_prompt_vars 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" 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 { function _exit-code {
if [[ "$1" -ne 0 ]]; then if [[ "$1" -ne 0 ]]; then
exit_code=" ${purple}${EXIT_CODE_ICON}${yellow}${exit_code}${bold_orange}" exit_code=" ${purple}${EXIT_CODE_ICON}${yellow}${exit_code}${bold_orange}"
else else
exit_code="${bold_green}" exit_code="${bold_green}"
fi fi
} }
function _prompt { 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 command_duration=$(_command_duration)
_git-uptream-remote-logo
history -a _exit-code exit_code
_git-uptream-remote-logo
# Detect root shell history -a
if [ "$(whoami)" = root ]; then
dir_color=$red
fi
# Detect ssh # Detect root shell
if [[ -n "${SSH_CONNECTION}" ]] && [ "$SSH_INFO" = true ]; then if [ "$(whoami)" = root ]; then
if [ "$HOST_INFO" = long ]; then dir_color=$red
host="\H" fi
else
host="\h"
fi
ssh_info="${bold_blue}\u${bold_orange}@${cyan}$host ${bold_orange}in"
fi
# Detect python venv # Detect ssh
if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then if [[ -n "${SSH_CONNECTION}" ]] && [ "$SSH_INFO" = true ]; then
python_venv="$PYTHON_VENV_CHAR${CONDA_DEFAULT_ENV} " if [ "$HOST_INFO" = long ]; then
elif [[ -n "${VIRTUAL_ENV}" ]]; then host="\H"
python_venv="$PYTHON_VENV_CHAR$(basename "${VIRTUAL_ENV}") " else
fi 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="\\n${ssh_info} ${purple}$(scm_char)${python_venv}${dir_color}\\w${normal}$(scm_prompt_info)${command_duration}${exit_code}"
PS1="${PS1}${wrap_char}${normal} " [[ ${#PS1} -gt $((COLUMNS * 2)) ]] && wrap_char="\\n"
PS1="${PS1}${wrap_char}${normal} "
} }
safe_append_prompt_command _prompt safe_append_prompt_command _prompt

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
CLOCK_CHAR_THEME_PROMPT_PREFIX='' CLOCK_CHAR_THEME_PROMPT_PREFIX=''
CLOCK_CHAR_THEME_PROMPT_SUFFIX='' CLOCK_CHAR_THEME_PROMPT_SUFFIX=''
@ -87,219 +87,235 @@ RBFU_THEME_PROMPT_SUFFIX='|'
GIT_EXE=$(which git 2> /dev/null || true) GIT_EXE=$(which git 2> /dev/null || true)
P4_EXE=$(which p4 2> /dev/null || true) P4_EXE=$(which p4 2> /dev/null || true)
HG_EXE=$(which hg 2> /dev/null || true) HG_EXE=$(which hg 2> /dev/null || true)
SVN_EXE=$(which svn 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. # 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. # See https://github.com/Bash-it/bash-it/issues/1612 for more details.
if [[ -x "$SVN_EXE" ]] ; then if [[ -x "$SVN_EXE" ]]; then
if ! "$SVN_EXE" --version > /dev/null 2>&1 ; then if ! "$SVN_EXE" --version > /dev/null 2>&1; then
# Unset the SVN exe variable so that SVN commands are avoided. # Unset the SVN exe variable so that SVN commands are avoided.
SVN_EXE="" SVN_EXE=""
fi fi
fi fi
function scm { function scm {
if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE if [[ "$SCM_CHECK" = false ]]; then
elif [[ -f .git/HEAD ]] && [[ -x "$GIT_EXE" ]]; then SCM=$SCM_GIT SCM=$SCM_NONE
elif [[ -x "$GIT_EXE" ]] && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then SCM=$SCM_GIT elif [[ -f .git/HEAD ]] && [[ -x "$GIT_EXE" ]]; then
elif [[ -x "$P4_EXE" ]] && [[ -n "$(p4 set P4CLIENT 2> /dev/null)" ]]; then SCM=$SCM_P4 SCM=$SCM_GIT
elif [[ -d .hg ]] && [[ -x "$HG_EXE" ]]; then SCM=$SCM_HG elif [[ -x "$GIT_EXE" ]] && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then
elif [[ -x "$HG_EXE" ]] && [[ -n "$(hg root 2> /dev/null)" ]]; then SCM=$SCM_HG SCM=$SCM_GIT
elif [[ -d .svn ]] && [[ -x "$SVN_EXE" ]]; then SCM=$SCM_SVN elif [[ -x "$P4_EXE" ]] && [[ -n "$(p4 set P4CLIENT 2> /dev/null)" ]]; then
elif [[ -x "$SVN_EXE" ]] && [[ -n "$(svn info --show-item wc-root 2>/dev/null)" ]]; then SCM=$SCM_SVN SCM=$SCM_P4
else SCM=$SCM_NONE elif [[ -d .hg ]] && [[ -x "$HG_EXE" ]]; then
fi 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 { function scm_prompt_char {
if [[ -z $SCM ]]; then scm; fi if [[ -z $SCM ]]; then scm; fi
if [[ $SCM == $SCM_GIT ]]; then SCM_CHAR=$SCM_GIT_CHAR if [[ $SCM == "$SCM_GIT" ]]; then
elif [[ $SCM == $SCM_P4 ]]; then SCM_CHAR=$SCM_P4_CHAR SCM_CHAR=$SCM_GIT_CHAR
elif [[ $SCM == $SCM_HG ]]; then SCM_CHAR=$SCM_HG_CHAR elif [[ $SCM == "$SCM_P4" ]]; then
elif [[ $SCM == $SCM_SVN ]]; then SCM_CHAR=$SCM_SVN_CHAR SCM_CHAR=$SCM_P4_CHAR
else SCM_CHAR=$SCM_NONE_CHAR elif [[ $SCM == "$SCM_HG" ]]; then
fi 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 { function scm_prompt_vars {
scm scm
scm_prompt_char scm_prompt_char
SCM_DIRTY=0 SCM_DIRTY=0
SCM_STATE='' SCM_STATE=''
[[ $SCM == $SCM_GIT ]] && git_prompt_vars && return [[ $SCM == "$SCM_GIT" ]] && git_prompt_vars && return
[[ $SCM == $SCM_P4 ]] && p4_prompt_vars && return [[ $SCM == "$SCM_P4" ]] && p4_prompt_vars && return
[[ $SCM == $SCM_HG ]] && hg_prompt_vars && return [[ $SCM == "$SCM_HG" ]] && hg_prompt_vars && return
[[ $SCM == $SCM_SVN ]] && svn_prompt_vars && return [[ $SCM == "$SCM_SVN" ]] && svn_prompt_vars && return
} }
function scm_prompt_info { function scm_prompt_info {
scm scm
scm_prompt_char scm_prompt_char
scm_prompt_info_common scm_prompt_info_common
} }
function scm_prompt_char_info { function scm_prompt_char_info {
scm_prompt_char scm_prompt_char
echo -ne "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" echo -ne "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}"
scm_prompt_info_common scm_prompt_info_common
} }
function scm_prompt_info_common { function scm_prompt_info_common {
SCM_DIRTY=0 SCM_DIRTY=0
SCM_STATE='' SCM_STATE=''
if [[ ${SCM} == ${SCM_GIT} ]]; then if [[ ${SCM} == "${SCM_GIT}" ]]; then
if [[ ${SCM_GIT_SHOW_MINIMAL_INFO} == true ]]; then if [[ ${SCM_GIT_SHOW_MINIMAL_INFO} == true ]]; then
# user requests minimal git status information # user requests minimal git status information
git_prompt_minimal_info git_prompt_minimal_info
else else
# more detailed git status # more detailed git status
git_prompt_info git_prompt_info
fi fi
return return
fi fi
# TODO: consider adding minimal status information for hg and svn # TODO: consider adding minimal status information for hg and svn
{ [[ ${SCM} == ${SCM_P4} ]] && p4_prompt_info && return; } || true { [[ ${SCM} == "${SCM_P4}" ]] && p4_prompt_info && return; } || true
{ [[ ${SCM} == ${SCM_HG} ]] && hg_prompt_info && return; } || true { [[ ${SCM} == "${SCM_HG}" ]] && hg_prompt_info && return; } || true
{ [[ ${SCM} == ${SCM_SVN} ]] && svn_prompt_info && return; } || true { [[ ${SCM} == "${SCM_SVN}" ]] && svn_prompt_info && return; } || true
} }
function terraform_workspace_prompt { function terraform_workspace_prompt {
if _command_exists terraform ; then if _command_exists terraform; then
if [ -d .terraform ]; then if [ -d .terraform ]; then
echo -e "$(terraform workspace show 2>/dev/null)" echo -e "$(terraform workspace show 2> /dev/null)"
fi fi
fi fi
} }
function git_prompt_minimal_info { 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 if [[ -n "$(_git-status | tail -n1)" ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
SCM_STATE=${SCM_THEME_PROMPT_DIRTY} SCM_STATE=${SCM_THEME_PROMPT_DIRTY}
fi fi
# Output the git prompt # Output the git prompt
SCM_PREFIX=${SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${SCM_THEME_PROMPT_PREFIX}
SCM_SUFFIX=${SCM_THEME_PROMPT_SUFFIX} SCM_SUFFIX=${SCM_THEME_PROMPT_SUFFIX}
echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}"
} }
function git_prompt_vars { function git_prompt_vars {
if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then # use faster gitstatus if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then
SCM_GIT_GITSTATUS_RAN=true # use this in githelpers and below to choose gitstatus output # we can use faster gitstatus
else # use this variable in githelpers and below to choose gitstatus output
SCM_GIT_GITSTATUS_RAN=false SCM_GIT_GITSTATUS_RAN=true
fi else
SCM_GIT_GITSTATUS_RAN=false
fi
if _git-branch &> /dev/null; then if _git-branch &> /dev/null; then
SCM_GIT_DETACHED="false" SCM_GIT_DETACHED="false"
SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)" SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)"
else else
SCM_GIT_DETACHED="true" SCM_GIT_DETACHED="true"
local detached_prefix local detached_prefix
if _git-tag &> /dev/null; then if _git-tag &> /dev/null; then
detached_prefix=${SCM_THEME_TAG_PREFIX} detached_prefix=${SCM_THEME_TAG_PREFIX}
else else
detached_prefix=${SCM_THEME_DETACHED_PREFIX} detached_prefix=${SCM_THEME_DETACHED_PREFIX}
fi fi
SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)" SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)"
fi fi
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
commits_behind=${VCS_STATUS_COMMITS_BEHIND} commits_behind=${VCS_STATUS_COMMITS_BEHIND}
commits_ahead=${VCS_STATUS_COMMITS_AHEAD} commits_ahead=${VCS_STATUS_COMMITS_AHEAD}
else else
IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)" IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)"
fi fi
if [[ "${commits_ahead}" -gt 0 ]]; then if [[ "${commits_ahead}" -gt 0 ]]; then
SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}" SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}"
[[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}" [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}"
fi fi
if [[ "${commits_behind}" -gt 0 ]]; then if [[ "${commits_behind}" -gt 0 ]]; then
SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_BEHIND_CHAR}" SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_BEHIND_CHAR}"
[[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_behind}" [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_behind}"
fi fi
if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then
local stash_count local stash_count
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
stash_count=${VCS_STATUS_STASHES} stash_count=${VCS_STATUS_STASHES}
else else
stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')" stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')"
fi fi
[[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}" [[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}"
fi fi
SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN}
if ! _git-hide-status; then if ! _git-hide-status; then
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
untracked_count=${VCS_STATUS_NUM_UNTRACKED} untracked_count=${VCS_STATUS_NUM_UNTRACKED}
unstaged_count=${VCS_STATUS_NUM_UNSTAGED} unstaged_count=${VCS_STATUS_NUM_UNSTAGED}
staged_count=${VCS_STATUS_NUM_STAGED} staged_count=${VCS_STATUS_NUM_STAGED}
else else
IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)" IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)"
fi fi
if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then
[[ "${staged_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STAGED_CHAR}${staged_count}" && SCM_DIRTY=3 [[ "${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 [[ "${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 [[ "${untracked_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_UNTRACKED_CHAR}${untracked_count}" && SCM_DIRTY=1
fi fi
SCM_STATE=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} SCM_STATE=${GIT_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY}
fi fi
fi fi
# no if for gitstatus here, user extraction is not supported by it # no if for gitstatus here, user extraction is not supported by it
[[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)" [[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)"
SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
SCM_SUFFIX=${GIT_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} 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 { function p4_prompt_vars {
IFS=$'\t' read -r \ IFS=$'\t' read -r \
opened_count non_default_changes default_count \ opened_count non_default_changes default_count \
add_file_count edit_file_count delete_file_count \ add_file_count edit_file_count delete_file_count \
<<< "$(_p4-opened-counts)" <<< "$(_p4-opened-counts)"
if [[ "${opened_count}" -gt 0 ]]; then if [[ "${opened_count}" -gt 0 ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
SCM_STATE=${SCM_THEME_PROMPT_DIRTY} SCM_STATE=${SCM_THEME_PROMPT_DIRTY}
[[ "${opened_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_OPENED_CHAR}${opened_count}" [[ "${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}" [[ "${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}" [[ "${default_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_DEFAULT_CHAR}${default_count}"
else else
SCM_DIRTY=0 SCM_DIRTY=0
SCM_STATE=${SCM_THEME_PROMPT_DIRTY} SCM_STATE=${SCM_THEME_PROMPT_DIRTY}
fi fi
SCM_PREFIX=${P4_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${P4_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
SCM_SUFFIX=${P4_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} SCM_SUFFIX=${P4_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX}
} }
function svn_prompt_vars { function svn_prompt_vars {
if [[ -n $(svn status |head -c1 2> /dev/null) ]]; then if [[ -n $(svn status | head -c1 2> /dev/null) ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
SCM_STATE=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} SCM_STATE=${SVN_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY}
else else
SCM_DIRTY=0 SCM_DIRTY=0
SCM_STATE=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} SCM_STATE=${SVN_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN}
fi fi
SCM_PREFIX=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${SVN_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
SCM_SUFFIX=${SVN_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} 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_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) SCM_CHANGE=$(svn info --show-item=revision 2> /dev/null)
} }
# this functions returns absolute location of .hg directory if one exists # 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 # - .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 # - 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 { function get_hg_root {
local CURRENT_DIR=$(pwd) local CURRENT_DIR=$(pwd)
while [ "$CURRENT_DIR" != "/" ]; do while [ "$CURRENT_DIR" != "/" ]; do
if [ -d "$CURRENT_DIR/.hg" ]; then if [ -d "$CURRENT_DIR/.hg" ]; then
echo "$CURRENT_DIR/.hg" echo "$CURRENT_DIR/.hg"
return return
fi fi
CURRENT_DIR=$(dirname $CURRENT_DIR) CURRENT_DIR=$(dirname "$CURRENT_DIR")
done done
} }
function hg_prompt_vars { function hg_prompt_vars {
if [[ -n $(hg status 2> /dev/null) ]]; then if [[ -n $(hg status 2> /dev/null) ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
SCM_STATE=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY} SCM_STATE=${HG_THEME_PROMPT_DIRTY:-$SCM_THEME_PROMPT_DIRTY}
else else
SCM_DIRTY=0 SCM_DIRTY=0
SCM_STATE=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} SCM_STATE=${HG_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN}
fi fi
SCM_PREFIX=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${HG_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
SCM_SUFFIX=${HG_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} 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 if [ -f "$HG_ROOT/branch" ]; then
# Mercurial holds it's current branch in .hg/branch file # Mercurial holds it's current branch in .hg/branch file
SCM_BRANCH=$(cat "$HG_ROOT/branch") SCM_BRANCH=$(cat "$HG_ROOT/branch")
else else
SCM_BRANCH=$(hg summary 2> /dev/null | grep branch: | awk '{print $2}') SCM_BRANCH=$(hg summary 2> /dev/null | grep branch: | awk '{print $2}')
fi fi
if [ -f "$HG_ROOT/dirstate" ]; then 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 # 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) SCM_CHANGE=$(hexdump -vn 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12)
else else
SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}') SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}')
fi fi
} }
function nvm_version_prompt { function nvm_version_prompt {
local node local node
if declare -f -F nvm &> /dev/null; then if declare -f -F nvm &> /dev/null; then
node=$(nvm current 2> /dev/null) node=$(nvm current 2> /dev/null)
[[ "${node}" == "system" ]] && return [[ "${node}" == "system" ]] && return
echo -e "${NVM_THEME_PROMPT_PREFIX}${node}${NVM_THEME_PROMPT_SUFFIX}" echo -e "${NVM_THEME_PROMPT_PREFIX}${node}${NVM_THEME_PROMPT_SUFFIX}"
fi fi
} }
function node_version_prompt { function node_version_prompt {
echo -e "$(nvm_version_prompt)" echo -e "$(nvm_version_prompt)"
} }
function rvm_version_prompt { function rvm_version_prompt {
if which rvm &> /dev/null; then if which rvm &> /dev/null; then
rvm=$(rvm-prompt) || return rvm=$(rvm-prompt) || return
if [ -n "$rvm" ]; then if [ -n "$rvm" ]; then
echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX" echo -e "$RVM_THEME_PROMPT_PREFIX$rvm$RVM_THEME_PROMPT_SUFFIX"
fi fi
fi fi
} }
function rbenv_version_prompt { function rbenv_version_prompt {
if which rbenv &> /dev/null; then if which rbenv &> /dev/null; then
rbenv=$(rbenv version-name) || return rbenv=$(rbenv version-name) || return
$(rbenv commands | grep -q gemset) && gemset=$(rbenv gemset active 2> /dev/null) && rbenv="$rbenv@${gemset%% *}" rbenv commands | grep -q gemset && gemset=$(rbenv gemset active 2> /dev/null) && rbenv="$rbenv@${gemset%% *}"
if [ $rbenv != "system" ]; then if [ "$rbenv" != "system" ]; then
echo -e "$RBENV_THEME_PROMPT_PREFIX$rbenv$RBENV_THEME_PROMPT_SUFFIX" echo -e "$RBENV_THEME_PROMPT_PREFIX$rbenv$RBENV_THEME_PROMPT_SUFFIX"
fi fi
fi fi
} }
function rbfu_version_prompt { function rbfu_version_prompt {
if [[ $RBFU_RUBY_VERSION ]]; then if [[ $RBFU_RUBY_VERSION ]]; then
echo -e "${RBFU_THEME_PROMPT_PREFIX}${RBFU_RUBY_VERSION}${RBFU_THEME_PROMPT_SUFFIX}" echo -e "${RBFU_THEME_PROMPT_PREFIX}${RBFU_RUBY_VERSION}${RBFU_THEME_PROMPT_SUFFIX}"
fi fi
} }
function chruby_version_prompt { function chruby_version_prompt {
if declare -f -F chruby &> /dev/null; then if declare -f -F chruby &> /dev/null; then
if declare -f -F chruby_auto &> /dev/null; then if declare -f -F chruby_auto &> /dev/null; then
chruby_auto chruby_auto
fi fi
ruby_version=$(ruby --version | awk '{print $1, $2;}') || return ruby_version=$(ruby --version | awk '{print $1, $2;}') || return
if [[ ! $(chruby | grep '\*') ]]; then if ! chruby | grep -q '\*'; then
ruby_version="${ruby_version} (system)" ruby_version="${ruby_version} (system)"
fi fi
echo -e "${CHRUBY_THEME_PROMPT_PREFIX}${ruby_version}${CHRUBY_THEME_PROMPT_SUFFIX}" echo -e "${CHRUBY_THEME_PROMPT_PREFIX}${ruby_version}${CHRUBY_THEME_PROMPT_SUFFIX}"
fi fi
} }
function ruby_version_prompt { function ruby_version_prompt {
if [[ "${THEME_SHOW_RUBY_PROMPT}" = "true" ]]; then if [[ "${THEME_SHOW_RUBY_PROMPT}" = "true" ]]; then
echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)" echo -e "$(rbfu_version_prompt)$(rbenv_version_prompt)$(rvm_version_prompt)$(chruby_version_prompt)"
fi fi
} }
function k8s_context_prompt { 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 { function virtualenv_prompt {
if [[ -n "$VIRTUAL_ENV" ]]; then if [[ -n "$VIRTUAL_ENV" ]]; then
virtualenv=`basename "$VIRTUAL_ENV"` virtualenv=$(basename "$VIRTUAL_ENV")
echo -e "$VIRTUALENV_THEME_PROMPT_PREFIX$virtualenv$VIRTUALENV_THEME_PROMPT_SUFFIX" echo -e "$VIRTUALENV_THEME_PROMPT_PREFIX$virtualenv$VIRTUALENV_THEME_PROMPT_SUFFIX"
fi fi
} }
function condaenv_prompt { function condaenv_prompt {
if [[ $CONDA_DEFAULT_ENV ]]; then if [[ $CONDA_DEFAULT_ENV ]]; then
echo -e "${CONDAENV_THEME_PROMPT_PREFIX}${CONDA_DEFAULT_ENV}${CONDAENV_THEME_PROMPT_SUFFIX}" echo -e "${CONDAENV_THEME_PROMPT_PREFIX}${CONDA_DEFAULT_ENV}${CONDAENV_THEME_PROMPT_SUFFIX}"
fi fi
} }
function py_interp_prompt { function py_interp_prompt {
py_version=$(python --version 2>&1 | awk 'NR==1{print "py-"$2;}') || return 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}" echo -e "${PYTHON_THEME_PROMPT_PREFIX}${py_version}${PYTHON_THEME_PROMPT_SUFFIX}"
} }
function python_version_prompt { 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 { function git_user_info {
# support two or more initials, set by 'git pair' plugin # support two or more initials, set by 'git pair' plugin
SCM_CURRENT_USER=$(git config user.initials | sed 's% %+%') SCM_CURRENT_USER=$(git config user.initials | sed 's% %+%')
# if `user.initials` weren't set, attempt to extract initials from `user.name` # 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)) [[ -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" [[ -n "${SCM_CURRENT_USER}" ]] && printf "%s" "$SCM_THEME_CURRENT_USER_PREFFIX$SCM_CURRENT_USER$SCM_THEME_CURRENT_USER_SUFFIX"
} }
function clock_char { function clock_char {
CLOCK_CHAR=${THEME_CLOCK_CHAR:-"⌚"} CLOCK_CHAR=${THEME_CLOCK_CHAR:-"⌚"}
CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$normal"} CLOCK_CHAR_COLOR=${THEME_CLOCK_CHAR_COLOR:-"$normal"}
SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"} SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"}
if [[ "${SHOW_CLOCK_CHAR}" = "true" ]]; then if [[ "${SHOW_CLOCK_CHAR}" = "true" ]]; then
echo -e "${CLOCK_CHAR_COLOR}${CLOCK_CHAR_THEME_PROMPT_PREFIX}${CLOCK_CHAR}${CLOCK_CHAR_THEME_PROMPT_SUFFIX}" echo -e "${CLOCK_CHAR_COLOR}${CLOCK_CHAR_THEME_PROMPT_PREFIX}${CLOCK_CHAR}${CLOCK_CHAR_THEME_PROMPT_SUFFIX}"
fi fi
} }
function clock_prompt { function clock_prompt {
CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$normal"} CLOCK_COLOR=${THEME_CLOCK_COLOR:-"$normal"}
CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"} CLOCK_FORMAT=${THEME_CLOCK_FORMAT:-"%H:%M:%S"}
[ -z $THEME_SHOW_CLOCK ] && THEME_SHOW_CLOCK=${THEME_CLOCK_CHECK:-"true"} [ -z "$THEME_SHOW_CLOCK" ] && THEME_SHOW_CLOCK=${THEME_CLOCK_CHECK:-"true"}
SHOW_CLOCK=$THEME_SHOW_CLOCK SHOW_CLOCK=$THEME_SHOW_CLOCK
if [[ "${SHOW_CLOCK}" = "true" ]]; then if [[ "${SHOW_CLOCK}" = "true" ]]; then
CLOCK_STRING=$(date +"${CLOCK_FORMAT}") CLOCK_STRING=$(date +"${CLOCK_FORMAT}")
echo -e "${CLOCK_COLOR}${CLOCK_THEME_PROMPT_PREFIX}${CLOCK_STRING}${CLOCK_THEME_PROMPT_SUFFIX}" echo -e "${CLOCK_COLOR}${CLOCK_THEME_PROMPT_PREFIX}${CLOCK_STRING}${CLOCK_THEME_PROMPT_SUFFIX}"
fi fi
} }
function user_host_prompt { function user_host_prompt {
if [[ "${THEME_SHOW_USER_HOST}" = "true" ]]; then if [[ "${THEME_SHOW_USER_HOST}" = "true" ]]; then
echo -e "${USER_HOST_THEME_PROMPT_PREFIX}\u@\h${USER_HOST_THEME_PROMPT_SUFFIX}" echo -e "${USER_HOST_THEME_PROMPT_PREFIX}\u@\h${USER_HOST_THEME_PROMPT_SUFFIX}"
fi fi
} }
# backwards-compatibility # backwards-compatibility
function git_prompt_info { function git_prompt_info {
_git-hide-status && return _git-hide-status && return
git_prompt_vars git_prompt_vars
echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}"
} }
function p4_prompt_info() { function p4_prompt_info() {
p4_prompt_vars p4_prompt_vars
echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE}${SCM_STATE}${SCM_SUFFIX}" echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE}${SCM_STATE}${SCM_SUFFIX}"
} }
function svn_prompt_info { function svn_prompt_info {
svn_prompt_vars svn_prompt_vars
echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}"
} }
function hg_prompt_info() { function hg_prompt_info() {
hg_prompt_vars hg_prompt_vars
echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE#*:}${SCM_STATE}${SCM_SUFFIX}" echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE#*:}${SCM_STATE}${SCM_SUFFIX}"
} }
function scm_char { function scm_char {
scm_prompt_char scm_prompt_char
echo -e "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}" echo -e "${SCM_THEME_CHAR_PREFIX}${SCM_CHAR}${SCM_THEME_CHAR_SUFFIX}"
} }
function prompt_char { function prompt_char {
scm_char scm_char
} }
function battery_char { function battery_char {
if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then if [[ "${THEME_BATTERY_PERCENTAGE_CHECK}" = true ]]; then
echo -e "${bold_red}$(battery_percentage)%" echo -e "${bold_red}$(battery_percentage)%"
fi fi
} }
if ! _command_exists battery_charge ; then if ! _command_exists battery_charge; then
# if user has installed battery plugin, skip this... # if user has installed battery plugin, skip this...
function battery_charge (){ function battery_charge() {
# no op # no op
echo -n echo -n
} }
fi fi
# The battery_char function depends on the presence of the battery_percentage function. # 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 battery_percentage is not defined, then define battery_char as a no-op.
if ! _command_exists battery_percentage ; then if ! _command_exists battery_percentage; then
function battery_char (){ function battery_char() {
# no op # no op
echo -n echo -n
} }
fi fi
function aws_profile { function aws_profile {
if [[ $AWS_DEFAULT_PROFILE ]]; then if [[ $AWS_DEFAULT_PROFILE ]]; then
echo -e "${AWS_DEFAULT_PROFILE}" echo -e "${AWS_DEFAULT_PROFILE}"
else else
echo -e "default" echo -e "default"
fi fi
} }
function __check_precmd_conflict() { function __check_precmd_conflict() {
local f local f
for f in "${precmd_functions[@]}"; do for f in "${precmd_functions[@]}"; do
if [[ "${f}" == "${1}" ]]; then if [[ "${f}" == "${1}" ]]; then
return 0 return 0
fi fi
done done
return 1 return 1
} }
function safe_append_prompt_command { function safe_append_prompt_command {
local prompt_re local prompt_re
if [ "${__bp_imported}" == "defined" ]; then if [ "${__bp_imported}" == "defined" ]; then
# We are using bash-preexec # We are using bash-preexec
if ! __check_precmd_conflict "${1}" ; then if ! __check_precmd_conflict "${1}"; then
precmd_functions+=("${1}") precmd_functions+=("${1}")
fi fi
else else
# Set OS dependent exact match regular expression # Set OS dependent exact match regular expression
if [[ ${OSTYPE} == darwin* ]]; then if [[ ${OSTYPE} == darwin* ]]; then
# macOS # macOS
prompt_re="[[:<:]]${1}[[:>:]]" prompt_re="[[:<:]]${1}[[:>:]]"
else else
# Linux, FreeBSD, etc. # Linux, FreeBSD, etc.
prompt_re="\<${1}\>" prompt_re="\<${1}\>"
fi fi
if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then if [[ ${PROMPT_COMMAND} =~ ${prompt_re} ]]; then
return return
elif [[ -z ${PROMPT_COMMAND} ]]; then elif [[ -z ${PROMPT_COMMAND} ]]; then
PROMPT_COMMAND="${1}" PROMPT_COMMAND="${1}"
else else
PROMPT_COMMAND="${1};${PROMPT_COMMAND}" PROMPT_COMMAND="${1};${PROMPT_COMMAND}"
fi fi
fi fi
} }
function _save-and-reload-history() { function _save-and-reload-history() {
local autosave=${1:-0} local autosave=${1:-0}
[[ $autosave -eq 1 ]] && history -a && history -c && history -r [[ $autosave -eq 1 ]] && history -a && history -c && history -r
} }

View File

@ -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

View File

@ -1,3 +1,4 @@
# shellcheck shell=bash
# Define this here so it can be used by all of the Powerline themes # Define this here so it can be used by all of the Powerline themes
THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true} THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash # shellcheck shell=bash
# shellcheck source=../../themes/powerline/powerline.base.bash # shellcheck source=../../themes/powerline/powerline.base.bash
. "$BASH_IT/themes/powerline/powerline.base.bash" . "$BASH_IT/themes/powerline/powerline.base.bash"