Merge branch 'feature/pre-commit-hook' into enforce-pre-commit

* feature/pre-commit-hook: (186 commits)
  added git alias to list remote branch creators with date and time
  Add Kind support
  Fix the commandline for gifski
  Add Terraform and Terragrunt aliases
  lib: helpers: Handle stable revert update
  lib: helpers: Rename Upgrading -> Updating
  lib: Fetch from remote before calculating latest tag in bash-it update
  test: Add completion test for -s --silent flag
  completion: Add --silent and -s completion
  doc: Add --silent flag documentation
  helpers: Add --slient option to bash-it update
  lib: Update no-op message in case of stable update
  lib: Add BASH_IT_DEVELOPMENT_BRANCH variable
  lib: Update to stable now correctly fails if no tags are present
  doc: Add stable/dev option to update section
  completion: Update completion for new bash-it update
  lib: Improve bash-it update so it can update to latest tag
  alias: git: Add new pretty git log alias (ggf)
  alias: git: Add git pull / git push --force aliases
  Add bash-it restart command
  ...
pull/1434/head
Ira Abramov 2020-10-17 12:22:07 +03:00
commit 388d632a1c
91 changed files with 2097 additions and 10186 deletions

View File

@ -1,14 +1,8 @@
# EditorConfig is awesome: http://EditorConfig.org
[*]
indent_style = tab
indent_size = 4
shell_variant = bash
binary_next_line = true # like -bn
switch_case_indent = true # like -ci
space_redirects = true # like -sr
keep_padding = true # like -kp
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
@ -17,16 +11,5 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.*sh]
[.git*]
indent_style = tab
indent_size = 4
shell_variant = bash
binary_next_line = true # like -bn
switch_case_indent = true # like -ci
space_redirects = true # like -sr
keep_padding = true # like -kp
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

10
.gitmodules vendored
View File

@ -1,12 +1,16 @@
[submodule "test_lib/bats-core"]
path = test_lib/bats-core
url = https://github.com/bats-core/bats-core
branch = tags/v1.2.0
[submodule "test_lib/bats-support"]
path = test_lib/bats-support
url = https://github.com/ztombol/bats-support
url = https://github.com/bats-core/bats-support
branch = tags/v0.3.0
[submodule "test_lib/bats-assert"]
path = test_lib/bats-assert
url = https://github.com/ztombol/bats-assert
url = https://github.com/bats-core/bats-assert
branch = tags/v2.0.0
[submodule "test_lib/bats-file"]
path = test_lib/bats-file
url = https://github.com/ztombol/bats-file
url = https://github.com/bats-core/bats-file
branch = tags/v0.3.0

View File

@ -1,6 +1,31 @@
sudo: false
script: test/run
language: c
os:
- linux
- osx
# YAML anchors need to appear first.
# Keys starting with an underscore are the custom ones, refer to
# https://docs.travis-ci.com/user/build-config-yaml#private-keys-as-yaml-anchors-and-aliases-and-external-tooling
_native_job: &native_job
script: |
test/run
language: shell
os: linux
dist: xenial
jobs:
- <<: *native_job
name: Ubuntu 16.04
- <<: *native_job
name: Ubuntu 18.04
dist: bionic
- <<: *native_job
name: MacOS xcode9.4
os: osx
osx_image: xcode9.4 # Default xcode on Travis.
- <<: *native_job
name: MacOS xcode11.5
os: osx
osx_image: xcode11.5 # Latest xcode on Travis.

View File

@ -2,6 +2,22 @@
This page summarizes a couple of rules to keep in mind when developing features or making changes in Bash-it.
## Debugging and Logging
### General Logging
While developing feature or making changes in general, you can log error/warning/debug
using `_log_error` `_log_warning` and `_log_debug`. This will help you solve problems quicker
and also propagate important notes to other users of Bash-it.
You can see the logs by using `bash-it doctor` command to reload and see the logs.
Alternatively, you can set `BASH_IT_LOG_LEVEL` to `BASH_IT_LOG_LEVEL_ERROR`, `BASH_IT_LOG_LEVEL_WARNING` or `BASH_IT_LOG_LEVEL_ALL`.
### Log Prefix/Context
You can define `BASH_IT_LOG_PREFIX` in your files in order to a have a constant prefix before your logs.
Note that we prefer to uses "tags" based logging, i.e `plugins: git: DEBUG: Loading git plugin`.
## Load Order
### General Load Order
@ -44,6 +60,11 @@ Having the order based on a numeric priority in a common directory allows for mo
These items are subject to change. When making changes to the internal functionality, this page needs to be updated as well.
## Plugin Disable Callbacks
Plugins can define a function that will be called when the plugin is being disabled.
The callback name should be `{PLUGIN_NAME}_on_disable`, you can see `gitstatus` for usage example.
## Using the pre-commit hook
Note the file .pre-commit-config.yaml at the top of the repo.

View File

@ -1,6 +1,7 @@
# Bash-it
[![Build Status](https://travis-ci.org/Bash-it/bash-it.svg?branch=master)](https://travis-ci.org/Bash-it/bash-it) [![Join the chat at https://gitter.im/Bash-it/bash-it](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Bash-it/bash-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.com/Bash-it/bash-it.svg?branch=master)](https://travis-ci.com/Bash-it/bash-it)
[![Join the chat at https://gitter.im/Bash-it/bash-it](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Bash-it/bash-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
**Bash-it** is a collection of community Bash commands and scripts for Bash 3.2+.
(And a shameless ripoff of [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) :smiley:)
@ -86,13 +87,24 @@ Have a look at our [bash-it-docker repository](https://github.com/Bash-it/bash-i
### Updating
To update Bash-it to the latest version, simply run:
To update Bash-it to the latest stable version, simply run:
```bash
bash-it update
bash-it update stable
```
that's all.
If you want to update to the latest dev version (directly from master), run:
```bash
bash-it update dev
```
If you want to update automatically and unattended, you can add the optional
`-s/--silent` flag, for example:
```bash
bash-it update dev --silent
```
If you are using an older version of Bash-it, it's possible that some functionality has changed, or that the internal structure of how Bash-it organizes its functionality has been updated.
For these cases, we provide a `migrate` command:
@ -394,6 +406,13 @@ $ git config --global --add bash-it.hide-status 1
Setting this flag globally has the same effect as `SCM_CHECK=true`, but only for Git repos.
### Speed up git status calculations
As an alternative to ignoring repo status entirely, you can try out the `gitstatus` plugin.
This plugin speeds up all `git status` calculations by up to 10x times!
**NOTE**: You will need to clone `gitstatus` repo from [here](https://github.com/romkatv/gitstatus).
### Pass function renamed to passgen
The Bash-it `pass` function has been renamed to `passgen` in order to avoid a naming conflict with the [pass password manager](https://www.passwordstore.org/).
@ -409,6 +428,20 @@ Unset `BASH_IT_LEGACY_PASS` to have Bash-it **return to default behavior**:
* `unset BASH_IT_LEGACY_PASS`
### Debugging
If you encounter problems with any part of Bash-it, run the following command:
```bash
bash-it doctor
```
This will reload your bash profile and print out logs of various parts in Bash-it.
Note that this command at default will print all logs, including debug logs.
You can call it like this:
```bash
bash-it doctor [errors/warnings/all]
```
In order to get wanted verbosity.
### Proxy Support
If you are working in a corporate environment where you have to go through a proxy server for internet access,

View File

@ -0,0 +1,23 @@
cite about-alias
about-alias 'Aliases for the bash-it command (these aliases are automatically included with the "general" aliases)'
# Common misspellings of bash-it
alias shit='bash-it'
alias batshit='bash-it'
alias bashit='bash-it'
alias batbsh='bash-it'
alias babsh='bash-it'
alias bash_it='bash-it'
alias bash_ti='bash-it'
# Additional bash-it aliases for help/show
alias bshsa='bash-it show aliases'
alias bshsc='bash-it show completions'
alias bshsp='bash-it show plugins'
alias bshha='bash-it help aliases'
alias bshhc='bash-it help completions'
alias bshhp='bash-it help plugins'
alias bshsch="bash-it search"
alias bshenp="bash-it enable plugin"
alias bshena="bash-it enable alias"
alias bshenc="bash-it enable completion"

View File

@ -28,7 +28,6 @@ alias vbpf="vim ~/.bash_profile"
if grep --color=auto "a" "${BASH_IT}/"*.md &> /dev/null
then
alias grep='grep --color=auto'
export GREP_COLOR='1;33'
fi
if which gshuf &> /dev/null
@ -75,27 +74,6 @@ fi
alias md='mkdir -p'
alias rd='rmdir'
# Common misspellings of bash-it
alias shit='bash-it'
alias batshit='bash-it'
alias bashit='bash-it'
alias batbsh='bash-it'
alias babsh='bash-it'
alias bash_it='bash-it'
alias bash_ti='bash-it'
# Additional bash-it aliases for help/show
alias bshsa='bash-it show aliases'
alias bshsc='bash-it show completions'
alias bshsp='bash-it show plugins'
alias bshha='bash-it help aliases'
alias bshhc='bash-it help completions'
alias bshhp='bash-it help plugins'
alias bshsch="bash-it search"
alias bshenp="bash-it enable plugin"
alias bshena="bash-it enable alias"
alias bshenc="bash-it enable completion"
# Shorten extract
alias xt="extract"
@ -113,3 +91,12 @@ catt() {
fi
done
}
# The Bash-it aliases were moved to the `bash-it.aliases.bash` file. The intent of this
# is to keep the script readable and less bloated. If you don't need to use
# the `general` aliases, but you want the Bash-it aliases, you can disable the `general`
# aliases and enable just the ones for Bash-it explicitly:
# bash-it disable alias general
# bash-it enable alias bash-it
# shellcheck source=./bash-it.aliases.bash
source "$BASH_IT/aliases/available/bash-it.aliases.bash"

View File

@ -22,6 +22,7 @@ alias gs='git status'
alias gss='git status -s'
alias gsu='git submodule update --init --recursive'
alias gl='git pull'
alias gpl='git pull'
alias glum='git pull upstream master'
alias gpr='git pull --rebase'
alias gpp='git pull && git push'
@ -35,8 +36,12 @@ alias gpom='git push origin master'
alias gr='git remote'
alias grv='git remote -v'
alias gra='git remote add'
alias grb='git rebase'
alias grm='git rebase master'
alias grmi='git rebase master -i'
alias gd='git diff'
alias gds='git diff --staged'
alias gdt='git difftool'
alias gdv='git diff -w "$@" | vim -R -'
alias gc='git commit -v'
alias gca='git commit -v -a'
@ -46,6 +51,8 @@ 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'
@ -64,7 +71,9 @@ 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"
@ -79,15 +88,36 @@ alias gnew="git log HEAD@{1}..HEAD@{0}"
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"
alias gh='cd "$(git rev-parse --show-toplevel)"'
# 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'

View File

@ -5,10 +5,9 @@
cite 'about-alias'
about-alias 'kubectl aliases'
# set apt aliases
function _set_pkg_aliases()
{
if [ -x $(which kubectl) ]; then
if _command_exists kubectl; then
alias kc='kubectl'
alias kcgp='kubectl get pods'
alias kcgd='kubectl get deployments'
@ -18,7 +17,8 @@ function _set_pkg_aliases()
alias kcdn='kubectl describe node'
alias kcgpan='kubectl get pods --all-namespaces'
alias kcgdan='kubectl get deployments --all-namespaces'
alias kcnetshoot='kubectl run --generator=run-pod/v1 netshoot-$(uuidgen | tr A-Z a-z | sed 's/-//g') --rm -i --tty --image nicolaka/netshoot -- /bin/bash'
# launches a disposable netshoot pod in the k8s cluster
alias kcnetshoot='kubectl run --generator=run-pod/v1 netshoot-$(date +%s) --rm -i --tty --image nicolaka/netshoot -- /bin/bash'
fi
}

View File

@ -0,0 +1,10 @@
# Aliases for Terraform and Terragrunt
cite 'about-alias'
about-alias 'Terraform abbreviations'
alias tf='terraform'
alias tfv='terraform validate'
alias tfp='terraform plan'
alias tfa='terraform apply'
alias tfd='terraform destory'

View File

@ -0,0 +1,15 @@
# Aliases for Terraform and Terragrunt
cite 'about-alias'
about-alias 'Terragrunt abbreviations'
alias tg='terragrunt'
alias tgv='terragrunt validate'
alias tgp='terragrunt plan'
alias tga='terragrunt apply'
alias tgd='terragrunt destroy'
alias tgva='terragrunt validate-all'
alias tgpa='terragrunt plan-all'
alias tgaa='terragrunt apply-all'
alias tgda='terragrunt destroy-all'

View File

@ -1,6 +1,11 @@
cite 'uuid-alias'
about-alias 'uuidgen aliases'
alias uuidu="uuidgen"
alias uuidl="uuidgen | tr '[:upper:]' '[:lower:]'"
alias uuid=uuidl # because upper case is like YELLING
if _command_exists uuid; then # Linux
alias uuidu="uuid | tr '[:lower:]' '[:upper:]'"
alias uuidl=uuid
elif _command_exists uuidgen; then # macOS/BSD
alias uuidu="uuidgen"
alias uuid="uuidgen | tr '[:upper:]' '[:lower:]'" # because upper case is like YELLING
alias uuidl=uuid
fi

View File

@ -1,37 +1,49 @@
#!/usr/bin/env bash
# Initialize Bash It
BASH_IT_LOG_PREFIX="core: main: "
# Only set $BASH_IT if it's not already set
if [ -z "$BASH_IT" ];
then
# Setting $BASH to maintain backwards compatibility
# TODO: warn users that they should upgrade their .bash_profile
export BASH_IT=$BASH
BASH="$(bash -c 'echo $BASH')"
export BASH
fi
# For backwards compatibility, look in old BASH_THEME location
if [ -z "$BASH_IT_THEME" ];
then
# TODO: warn users that they should upgrade their .bash_profile
export BASH_IT_THEME="$BASH_THEME";
unset BASH_THEME;
BASH_IT_OLD_BASH_SETUP=true
fi
# Load composure first, so we support function metadata
# shellcheck source=./lib/composure.bash
source "${BASH_IT}/lib/composure.bash"
# We need to load logging module first as well in order to be able to log
# shellcheck source=./lib/log.bash
source "${BASH_IT}/lib/log.bash"
# We can only log it now
[ -z "$BASH_IT_OLD_BASH_SETUP" ] || _log_warning "BASH_IT variable not initialized, please upgrade your bash-it version and reinstall it!"
# For backwards compatibility, look in old BASH_THEME location
if [ -z "$BASH_IT_THEME" ];
then
_log_warning "BASH_IT_THEME variable not initialized, please upgrade your bash-it version and reinstall it!"
export BASH_IT_THEME="$BASH_THEME";
unset BASH_THEME;
fi
# support 'plumbing' metadata
cite _about _param _example _group _author _version
# libraries, but skip appearance (themes) for now
_log_debug "Loading libraries(except appearance)..."
LIB="${BASH_IT}/lib/*.bash"
APPEARANCE_LIB="${BASH_IT}/lib/appearance.bash"
for _bash_it_config_file in $LIB
do
if [ "$_bash_it_config_file" != "$APPEARANCE_LIB" ]; then
filename=${_bash_it_config_file##*/}
filename=${filename%.bash}
BASH_IT_LOG_PREFIX="lib: ${filename}: "
_log_debug "Loading library file..."
# shellcheck disable=SC1090
source "$_bash_it_config_file"
fi
@ -51,36 +63,51 @@ done
# Load theme, if a theme was set
if [[ ! -z "${BASH_IT_THEME}" ]]; then
_log_debug "Loading \"${BASH_IT_THEME}\" theme..."
# Load colors and helpers first so they can be used in base theme
BASH_IT_LOG_PREFIX="themes: colors: "
# shellcheck source=./themes/colors.theme.bash
source "${BASH_IT}/themes/colors.theme.bash"
BASH_IT_LOG_PREFIX="themes: githelpers: "
# shellcheck source=./themes/githelpers.theme.bash
source "${BASH_IT}/themes/githelpers.theme.bash"
BASH_IT_LOG_PREFIX="themes: p4helpers: "
# shellcheck source=./themes/p4helpers.theme.bash
source "${BASH_IT}/themes/p4helpers.theme.bash"
BASH_IT_LOG_PREFIX="themes: base: "
# shellcheck source=./themes/base.theme.bash
source "${BASH_IT}/themes/base.theme.bash"
BASH_IT_LOG_PREFIX="lib: appearance: "
# appearance (themes) now, after all dependencies
# shellcheck source=./lib/appearance.bash
source "$APPEARANCE_LIB"
fi
# Load custom aliases, completion, plugins
BASH_IT_LOG_PREFIX="core: main: "
_log_debug "Loading custom aliases, completion, plugins..."
for file_type in "aliases" "completion" "plugins"
do
if [ -e "${BASH_IT}/${file_type}/custom.${file_type}.bash" ]
then
BASH_IT_LOG_PREFIX="${file_type}: custom: "
_log_debug "Loading component..."
# shellcheck disable=SC1090
source "${BASH_IT}/${file_type}/custom.${file_type}.bash"
fi
done
# Custom
BASH_IT_LOG_PREFIX="core: main: "
_log_debug "Loading general custom files..."
CUSTOM="${BASH_IT_CUSTOM:=${BASH_IT}/custom}/*.bash ${BASH_IT_CUSTOM:=${BASH_IT}/custom}/**/*.bash"
for _bash_it_config_file in $CUSTOM
do
if [ -e "${_bash_it_config_file}" ]; then
filename=$(basename "${_bash_it_config_file}")
filename=${filename%*.bash}
BASH_IT_LOG_PREFIX="custom: $filename: "
_log_debug "Loading custom file..."
# shellcheck disable=SC1090
source "$_bash_it_config_file"
fi

View File

@ -65,7 +65,7 @@ _bash-it-comp()
prev="${COMP_WORDS[COMP_CWORD-1]}"
chose_opt="${COMP_WORDS[1]}"
file_type="${COMP_WORDS[2]}"
opts="disable enable help migrate reload search show update version"
opts="disable enable help migrate reload restart doctor search show update version"
case "${chose_opt}" in
show)
local show_args="aliases completions plugins"
@ -82,7 +82,21 @@ _bash-it-comp()
return 0
fi
;;
migrate | reload | search | update | version)
doctor)
local doctor_args="errors warnings all"
COMPREPLY=( $(compgen -W "${doctor_args}" -- ${cur}) )
return 0
;;
update)
if [[ ${cur} == -* ]];then
local update_args="-s --silent"
else
local update_args="stable dev"
fi
COMPREPLY=( $(compgen -W "${update_args}" -- ${cur}) )
return 0
;;
migrate | reload | search | version)
return 0
;;
enable | disable)

View File

@ -1,13 +1,27 @@
if which brew >/dev/null 2>&1; then
BREW_PREFIX=$(brew --prefix)
if [ -f "$BREW_PREFIX"/etc/bash_completion.d/brew ]; then
. "$BREW_PREFIX"/etc/bash_completion.d/brew
elif [ -f "$BREW_PREFIX"/Library/Contributions/brew_bash_completion.sh ]; then
. "$BREW_PREFIX"/Library/Contributions/brew_bash_completion.sh
elif [ -f "$BREW_PREFIX"/completions/bash/brew ]; then
#!/usr/bin/env bash
# Load late to make sure `system` completion loads first
# BASH_IT_LOAD_PRIORITY: 375
if [[ "$(uname -s)" != 'Darwin' ]]; then
_log_warning "unsupported operating system - only 'Darwin' is supported"
return 0
fi
# Make sure brew is installed
_command_exists brew || return 0
BREW_PREFIX=${BREW_PREFIX:-$(brew --prefix)}
if [[ -r "$BREW_PREFIX"/etc/bash_completion.d/brew ]]; then
source "$BREW_PREFIX"/etc/bash_completion.d/brew
elif [[ -r "$BREW_PREFIX"/Library/Contributions/brew_bash_completion.sh ]]; then
source "$BREW_PREFIX"/Library/Contributions/brew_bash_completion.sh
elif [[ -f "$BREW_PREFIX"/completions/bash/brew ]]; then
# For the git-clone based installation, see here for more info:
# https://github.com/Bash-it/bash-it/issues/1458
# https://docs.brew.sh/Shell-Completion
. "$BREW_PREFIX"/completions/bash/brew
fi
source "$BREW_PREFIX"/completions/bash/brew
fi

View File

@ -1,11 +1 @@
if which crystal >/dev/null 2>&1; then
if which brew >/dev/null 2>&1; then
BREW_PREFIX=$(brew --prefix)
if [ -f "$BREW_PREFIX"/etc/bash_completion.d/crystal ]; then
. "$BREW_PREFIX"/etc/bash_completion.d/crystal
fi
fi
fi
_log_warning 'Bash completion for "crystal" is now covered by "system". This completion can be disabled.'

File diff suppressed because it is too large Load Diff

View File

@ -1,365 +0,0 @@
# hub tab-completion script for bash.
# This script complements the completion script that ships with git.
# Check that git tab completion is available
if declare -F _git > /dev/null; then
# Duplicate and rename the 'list_all_commands' function
eval "$(declare -f __git_list_all_commands | \
sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')"
# Wrap the 'list_all_commands' function with extra hub commands
__git_list_all_commands() {
cat <<-EOF
alias
pull-request
fork
create
browse
compare
ci-status
release
issue
update
EOF
__git_list_all_commands_without_hub
}
# Ensure cached commands are cleared
__git_all_commands=""
##########################
# hub command completions
##########################
# hub alias [-s] [SHELL]
_git_alias() {
local i c=2 s=-s sh shells="bash zsh sh ksh csh fish"
while [ $c -lt $cword ]; do
i="${words[c]}"
case "$i" in
-s)
unset s
;;
*)
for sh in $shells; do
if [ "$sh" = "$i" ]; then
unset shells
break
fi
done
;;
esac
((c++))
done
__gitcomp "$s $shells"
}
# hub browse [-u] [--|[USER/]REPOSITORY] [SUBPAGE]
_git_browse() {
local i c=2 u=-u repo subpage
local subpages_="commits issues tree wiki pulls branches stargazers
contributors network network/ graphs graphs/"
local subpages_network="members"
local subpages_graphs="commit-activity code-frequency punch-card"
while [ $c -lt $cword ]; do
i="${words[c]}"
case "$i" in
-u)
unset u
;;
*)
if [ -z "$repo" ]; then
repo=$i
else
subpage=$i
fi
;;
esac
((c++))
done
if [ -z "$repo" ]; then
__gitcomp "$u -- $(__hub_github_repos '\p')"
elif [ -z "$subpage" ]; then
case "$cur" in
*/*)
local pfx="${cur%/*}" cur_="${cur#*/}"
local subpages_var="subpages_$pfx"
__gitcomp "${!subpages_var}" "$pfx/" "$cur_"
;;
*)
__gitcomp "$u ${subpages_}"
;;
esac
else
__gitcomp "$u"
fi
}
# hub compare [-u] [USER[/REPOSITORY]] [[START...]END]
_git_compare() {
local i c=$((cword - 1)) u=-u user remote owner repo arg_repo rev
while [ $c -gt 1 ]; do
i="${words[c]}"
case "$i" in
-u)
unset u
;;
*)
if [ -z "$rev" ]; then
# Even though the logic below is able to complete both user/repo
# and revision in the right place, when there is only one argument
# (other than -u) in the command, that argument will be taken as
# revision. For example:
# $ hub compare -u upstream
# > https://github.com/USER/REPO/compare/upstream
if __hub_github_repos '\p' | grep -Eqx "^$i(/[^/]+)?"; then
arg_repo=$i
else
rev=$i
fi
elif [ -z "$arg_repo" ]; then
arg_repo=$i
fi
;;
esac
((c--))
done
# Here we want to find out the git remote name of user/repo, in order to
# generate an appropriate revision list
if [ -z "$arg_repo" ]; then
user=$(__hub_github_user)
if [ -z "$user" ]; then
for i in $(__hub_github_repos); do
remote=${i%%:*}
repo=${i#*:}
if [ "$remote" = origin ]; then
break
fi
done
else
for i in $(__hub_github_repos); do
remote=${i%%:*}
repo=${i#*:}
owner=${repo%%/*}
if [ "$user" = "$owner" ]; then
break
fi
done
fi
else
for i in $(__hub_github_repos); do
remote=${i%%:*}
repo=${i#*:}
owner=${repo%%/*}
case "$arg_repo" in
"$repo"|"$owner")
break
;;
esac
done
fi
local pfx cur_="$cur"
case "$cur_" in
*..*)
pfx="${cur_%%..*}..."
cur_="${cur_##*..}"
__gitcomp_nl "$(__hub_revlist $remote)" "$pfx" "$cur_"
;;
*)
if [ -z "${arg_repo}${rev}" ]; then
__gitcomp "$u $(__hub_github_repos '\o\n\p') $(__hub_revlist $remote)"
elif [ -z "$rev" ]; then
__gitcomp "$u $(__hub_revlist $remote)"
else
__gitcomp "$u"
fi
;;
esac
}
# hub create [NAME] [-p] [-d DESCRIPTION] [-h HOMEPAGE]
_git_create() {
local i c=2 name repo flags="-p -d -h"
while [ $c -lt $cword ]; do
i="${words[c]}"
case "$i" in
-d|-h)
((c++))
flags=${flags/$i/}
;;
-p)
flags=${flags/$i/}
;;
*)
name=$i
;;
esac
((c++))
done
if [ -z "$name" ]; then
repo=$(basename "$(pwd)")
fi
case "$prev" in
-d|-h)
COMPREPLY=()
;;
-p|*)
__gitcomp "$repo $flags"
;;
esac
}
# hub fork [--no-remote]
_git_fork() {
local i c=2 remote=yes
while [ $c -lt $cword ]; do
i="${words[c]}"
case "$i" in
--no-remote)
unset remote
;;
esac
((c++))
done
if [ -n "$remote" ]; then
__gitcomp "--no-remote"
fi
}
# hub pull-request [-f] [-m <MESSAGE>|-F <FILE>|-i <ISSUE>|<ISSUE-URL>] [-b <BASE>] [-h <HEAD>]
_git_pull_request() {
local i c=2 flags="-f -m -F -i -b -h"
while [ $c -lt $cword ]; do
i="${words[c]}"
case "$i" in
-m|-F|-i|-b|-h)
((c++))
flags=${flags/$i/}
;;
-f)
flags=${flags/$i/}
;;
esac
((c++))
done
case "$prev" in
-i)
COMPREPLY=()
;;
-b|-h)
# (Doesn't seem to need this...)
# Uncomment the following line when 'owner/repo:[TAB]' misbehaved
#_get_comp_words_by_ref -n : cur
__gitcomp_nl "$(__hub_heads)"
# __ltrim_colon_completions "$cur"
;;
-F)
COMPREPLY=( "$cur"* )
;;
-f|*)
__gitcomp "$flags"
;;
esac
}
###################
# Helper functions
###################
# __hub_github_user [HOST]
# Return $GITHUB_USER or the default github user defined in hub config
# HOST - Host to be looked-up in hub config. Default is "github.com"
__hub_github_user() {
if [ -n "$GITHUB_USER" ]; then
echo $GITHUB_USER
return
fi
local line h k v host=${1:-github.com} config=${HUB_CONFIG:-~/.config/gh}
if [ -f "$config" ]; then
while read line; do
if [ "$line" = "---" ]; then
continue
fi
k=${line%%:*}
v=${line#*:}
if [ -z "$v" ]; then
if [ "$h" = "$host" ]; then
break
fi
h=$k
continue
fi
k=${k#* }
v=${v#* }
if [ "$h" = "$host" ] && [ "$k" = "user" ]; then
echo "$v"
break
fi
done < "$config"
fi
}
# __hub_github_repos [FORMAT]
# List all github hosted repository
# FORMAT - Format string contains multiple of these:
# \m remote
# \p owner/repo
# \o owner
# escaped characters (\n, \t ...etc) work
# If omitted, prints all github repos in the format of "remote:owner/repo"
__hub_github_repos() {
local f format=$1
if [ -z "$(__gitdir)" ]; then
return
fi
if [ -z "$format" ]; then
format='\1:\2'
else
format=${format//\m/\1}
format=${format//\p/\2}
format=${format//\o/\3}
fi
command git config --get-regexp 'remote\.[^.]*\.url' |
grep -E ' ((https?|git)://|git@)github\.com[:/][^:/]+/[^/]+$' |
sed -E 's#^remote\.([^.]+)\.url +.+[:/](([^/]+)/[^.]+)(\.git)?$#'"$format"'#'
}
# __hub_heads
# List all local "branch", and remote "owner/repo:branch"
__hub_heads() {
local i remote repo branch dir=$(__gitdir)
if [ -d "$dir" ]; then
command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
"refs/heads/"
for i in $(__hub_github_repos); do
remote=${i%%:*}
repo=${i#*:}
command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
"refs/remotes/${remote}/" | while read branch; do
echo "${repo}:${branch#${remote}/}"
done
done
fi
}
# __hub_revlist [REMOTE]
# List all tags, and branches under REMOTE, without the "remote/" prefix
# REMOTE - Remote name to search branches from. Default is "origin"
__hub_revlist() {
local i remote=${1:-origin} dir=$(__gitdir)
if [ -d "$dir" ]; then
command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
"refs/remotes/${remote}/" | while read i; do
echo "${i#${remote}/}"
done
command git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
"refs/tags/"
fi
}
# Enable completion for hub even when not using the alias
complete -o bashdefault -o default -o nospace -F _git gh 2>/dev/null \
|| complete -o default -o nospace -F _git gh
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
cite "about-completion"
about-completion "GitHub CLI completion"
if _command_exists gh; then
if _command_exists brew; then
_log_warning "You don't need github-cli completion enabled if you have system completion enabled"
fi
eval "$(gh completion --shell=bash)"
fi

View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
if _command_exists kind; then
eval "$(kind completion bash)"
fi

View File

@ -0,0 +1 @@
_command_exists minishift && source <(minishift completion bash)

View File

@ -1,2 +1,8 @@
if _command_exists ng; then
# No longer supported, please see https://github.com/angular/angular-cli/issues/11043
# Fix courtesy of https://stackoverflow.com/questions/50194674/ng-completion-no-longer-exists
# . <(ng completion --bash)
. <(ng completion --bash)
NG_COMMANDS="add build config doc e2e generate help lint new run serve test update version xi18n"
complete -W "$NG_COMMANDS" ng
fi

View File

@ -1,3 +1 @@
#!/usr/bin/env bash
[ -x "$(which oc)" ] && eval "$(oc completion bash)"
_command_exists oc && source <(oc completion bash)

View File

@ -1,9 +1,17 @@
# Ensure that we log to doctor so the user can address these issues
_is_function _init_completion ||
_log_error '_init_completion not found. Ensure bash-completion 2.0 or newer is installed and configured properly.'
_is_function _rl_enabled ||
_log_error '_rl_enabled not found. Ensure bash-completion 2.0 or newer is installed and configured properly.'
_pj() {
[ -z "$PROJECT_PATHS" ] && return
_is_function _init_completion || return
_is_function _rl_enabled || return
[ -n "$PROJECT_PATHS" ] || return
shift
[ "$1" == "open" ] && shift
local cur prev words cword
local cur
_init_completion || return
local IFS=$'\n' i j k
@ -16,8 +24,8 @@ _pj() {
for i in ${PROJECT_PATHS//:/$'\n'}; do
# create an array of matched subdirs
k="${#COMPREPLY[@]}"
for j in $( compgen -d $i/$cur ); do
if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
for j in $(compgen -d "$i/$cur"); do
if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#$i/} ]]; then
j+="/"
fi
COMPREPLY[k++]=${j#$i/}

View File

@ -11,34 +11,32 @@
# TODO: cache results of some functions? where? how long?
# TODO: is it ok to use '--timeout 2' ?
_salt_get_grains(){
if [ "$1" = 'local' ] ; then
salt-call --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" |sed 's:\([a-z0-9]\) :\1\: :g'
_salt_get_grains() {
if [ "$1" = 'local' ]; then
salt-call --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" | sed 's:\([a-z0-9]\) :\1\: :g'
else
salt '*' --timeout 2 --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" |sed 's:\([a-z0-9]\) :\1\: :g'
salt '*' --timeout 2 --out=txt -- grains.ls | sed 's/^.*\[//' | tr -d ",']" | sed 's:\([a-z0-9]\) :\1\: :g'
fi
}
_salt_get_grain_values(){
if [ "$1" = 'local' ] ; then
salt-call --out=txt -- grains.item $1 |sed 's/^\S*:\s//' |grep -v '^\s*$'
_salt_get_grain_values() {
if [ "$1" = 'local' ]; then
salt-call --out=txt -- grains.item $1 | sed 's/^\S*:\s//' | grep -v '^\s*$'
else
salt '*' --timeout 2 --out=txt -- grains.item $1 |sed 's/^\S*:\s//' |grep -v '^\s*$'
salt '*' --timeout 2 --out=txt -- grains.item $1 | sed 's/^\S*:\s//' | grep -v '^\s*$'
fi
}
_salt(){
_salt() {
local cur prev opts _salt_grains _salt_coms pprev ppprev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
prev="${COMP_WORDS[COMP_CWORD - 1]}"
if [ ${COMP_CWORD} -gt 2 ]; then
pprev="${COMP_WORDS[COMP_CWORD-2]}"
pprev="${COMP_WORDS[COMP_CWORD - 2]}"
fi
if [ ${COMP_CWORD} -gt 3 ]; then
ppprev="${COMP_WORDS[COMP_CWORD-3]}"
ppprev="${COMP_WORDS[COMP_CWORD - 3]}"
fi
opts="-h --help -d --doc --documentation --version --versions-report -c \
@ -49,24 +47,24 @@ _salt(){
--ipcidr --out=pprint --out=yaml --out=overstatestage --out=json \
--out=raw --out=highstate --out=key --out=txt --no-color --out-indent= "
if [[ "${cur}" == -* ]] ; then
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
fi
# 2 special cases for filling up grain values
case "${pprev}" in
-G|--grain|--grain-pcre)
-G | --grain | --grain-pcre)
if [ "${cur}" = ":" ]; then
COMPREPLY=($(compgen -W "`_salt_get_grain_values ${prev}`" ))
COMPREPLY=($(compgen -W "$(_salt_get_grain_values ${prev})"))
return 0
fi
;;
esac
case "${ppprev}" in
-G|--grain|--grain-pcre)
-G | --grain | --grain-pcre)
if [ "${prev}" = ":" ]; then
COMPREPLY=( $(compgen -W "`_salt_get_grain_values ${pprev}`" -- ${cur}) )
COMPREPLY=($(compgen -W "$(_salt_get_grain_values ${pprev})" -- ${cur}))
return 0
fi
;;
@ -81,56 +79,55 @@ _salt(){
case "${prev}" in
-c|--config)
-c | --config)
COMPREPLY=($(compgen -f -- ${cur}))
return 0
;;
salt)
COMPREPLY=($(compgen -W "\'*\' ${opts} `salt-key --no-color -l acc`" -- ${cur}))
COMPREPLY=($(compgen -W "\'*\' ${opts} $(salt-key --no-color -l acc)" -- ${cur}))
return 0
;;
-E|--pcre)
COMPREPLY=($(compgen -W "`salt-key --no-color -l acc`" -- ${cur}))
-E | --pcre)
COMPREPLY=($(compgen -W "$(salt-key --no-color -l acc)" -- ${cur}))
return 0
;;
-G|--grain|--grain-pcre)
-G | --grain | --grain-pcre)
COMPREPLY=($(compgen -W "$(_salt_get_grains)" -- ${cur}))
return 0
;;
-C|--compound)
-C | --compound)
COMPREPLY=() # TODO: finish this one? how?
return 0
;;
-t|--timeout)
COMPREPLY=($( compgen -W "1 2 3 4 5 6 7 8 9 10 15 20 30 40 60 90 120 180" -- ${cur}))
-t | --timeout)
COMPREPLY=($(compgen -W "1 2 3 4 5 6 7 8 9 10 15 20 30 40 60 90 120 180" -- ${cur}))
return 0
;;
-b|--batch|--batch-size)
-b | --batch | --batch-size)
COMPREPLY=($(compgen -W "1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100 120 150 200"))
return 0
;;
-N|--nodegroup)
-N | --nodegroup)
MASTER_CONFIG='/etc/salt/master'
COMPREPLY=($(compgen -W "`awk -F ':' 'BEGIN {print_line = 0}; /^nodegroups/ {print_line = 1;getline } print_line && /^ */ {print $1} /^[^ ]/ {print_line = 0}' <${MASTER_CONFIG}`" -- ${cur}))
COMPREPLY=($(compgen -W "$(awk -F ':' 'BEGIN {print_line = 0}; /^nodegroups/ {print_line = 1;getline } print_line && /^ */ {print $1} /^[^ ]/ {print_line = 0}' <${MASTER_CONFIG})" -- ${cur}))
return 0
;;
esac
_salt_coms="$(salt '*' --timeout 2 --out=txt -- sys.list_functions | sed 's/^.*\[//' | tr -d ",']" )"
_salt_coms="$(salt '*' --timeout 2 --out=txt -- sys.list_functions | sed 's/^.*\[//' | tr -d ",']")"
all="${opts} ${_salt_coms}"
COMPREPLY=( $(compgen -W "${all}" -- ${cur}) )
COMPREPLY=($(compgen -W "${all}" -- ${cur}))
return 0
}
complete -F _salt salt
_saltkey(){
_saltkey() {
local cur prev opts prev pprev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
prev="${COMP_WORDS[COMP_CWORD - 1]}"
opts="-c --config-dir= -h --help --version --versions-report -q --quiet \
-y --yes --gen-keys= --gen-keys-dir= --keysize= --key-logfile= \
-l --list= -L --list-all -a --accept= -A --accept-all \
@ -139,12 +136,12 @@ _saltkey(){
--out=pprint --out=yaml --out=overstatestage --out=json --out=raw \
--out=highstate --out=key --out=txt --no-color --out-indent= "
if [ ${COMP_CWORD} -gt 2 ]; then
pprev="${COMP_WORDS[COMP_CWORD-2]}"
pprev="${COMP_WORDS[COMP_CWORD - 2]}"
fi
if [ ${COMP_CWORD} -gt 3 ]; then
ppprev="${COMP_WORDS[COMP_CWORD-3]}"
ppprev="${COMP_WORDS[COMP_CWORD - 3]}"
fi
if [[ "${cur}" == -* ]] ; then
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
fi
@ -157,19 +154,26 @@ _saltkey(){
fi
case "${prev}" in
-a|--accept)
COMPREPLY=($(compgen -W "$(salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur}))
-a | --accept)
COMPREPLY=($(compgen -W "$(
salt-key -l un --no-color
salt-key -l rej --no-color
)" -- ${cur}))
return 0
;;
-r|--reject)
-r | --reject)
COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color)" -- ${cur}))
return 0
;;
-d|--delete)
COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color; salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur}))
-d | --delete)
COMPREPLY=($(compgen -W "$(
salt-key -l acc --no-color
salt-key -l un --no-color
salt-key -l rej --no-color
)" -- ${cur}))
return 0
;;
-c|--config)
-c | --config)
COMPREPLY=($(compgen -f -- ${cur}))
return 0
;;
@ -184,11 +188,15 @@ _saltkey(){
COMPREPLY=($(compgen -d -- ${cur}))
return 0
;;
-p|--print)
COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color; salt-key -l un --no-color; salt-key -l rej --no-color)" -- ${cur}))
-p | --print)
COMPREPLY=($(compgen -W "$(
salt-key -l acc --no-color
salt-key -l un --no-color
salt-key -l rej --no-color
)" -- ${cur}))
return 0
;;
-l|--list)
-l | --list)
COMPREPLY=($(compgen -W "pre un acc accepted unaccepted rej rejected all" -- ${cur}))
return 0
;;
@ -202,22 +210,22 @@ _saltkey(){
complete -F _saltkey salt-key
_saltcall(){
_saltcall() {
local cur prev opts _salt_coms pprev ppprev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
prev="${COMP_WORDS[COMP_CWORD - 1]}"
opts="-h --help -d --doc --documentation --version --versions-report \
-m --module-dirs= -g --grains --return= --local -c --config-dir= -l --log-level= \
--out=pprint --out=yaml --out=overstatestage --out=json --out=raw \
--out=highstate --out=key --out=txt --no-color --out-indent= "
if [ ${COMP_CWORD} -gt 2 ]; then
pprev="${COMP_WORDS[COMP_CWORD-2]}"
pprev="${COMP_WORDS[COMP_CWORD - 2]}"
fi
if [ ${COMP_CWORD} -gt 3 ]; then
ppprev="${COMP_WORDS[COMP_CWORD-3]}"
ppprev="${COMP_WORDS[COMP_CWORD - 3]}"
fi
if [[ "${cur}" == -* ]] ; then
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
fi
@ -230,15 +238,15 @@ _saltcall(){
fi
case ${prev} in
-m|--module-dirs)
COMPREPLY=( $(compgen -d ${cur} ))
-m | --module-dirs)
COMPREPLY=($(compgen -d ${cur}))
return 0
;;
-l|--log-level)
COMPREPLY=( $(compgen -W "info none garbage trace warning error debug" -- ${cur}))
-l | --log-level)
COMPREPLY=($(compgen -W "info none garbage trace warning error debug" -- ${cur}))
return 0
;;
-g|grains)
-g | grains)
return 0
;;
salt-call)
@ -247,26 +255,25 @@ _saltcall(){
;;
esac
_salt_coms="$(salt-call --out=txt -- sys.list_functions|sed 's/^.*\[//' | tr -d ",']" )"
COMPREPLY=( $(compgen -W "${opts} ${_salt_coms}" -- ${cur} ))
_salt_coms="$(salt-call --out=txt -- sys.list_functions | sed 's/^.*\[//' | tr -d ",']")"
COMPREPLY=($(compgen -W "${opts} ${_salt_coms}" -- ${cur}))
return 0
}
complete -F _saltcall salt-call
_saltcp(){
_saltcp() {
local cur prev opts target prefpart postpart helper filt pprev ppprev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
prev="${COMP_WORDS[COMP_CWORD - 1]}"
opts="-t --timeout= -s --static -b --batch= --batch-size= \
-h --help --version --versions-report -c --config-dir= \
-E --pcre -L --list -G --grain --grain-pcre -N --nodegroup \
-R --range -C --compound -I --pillar \
--out=pprint --out=yaml --out=overstatestage --out=json --out=raw \
--out=highstate --out=key --out=txt --no-color --out-indent= "
if [[ "${cur}" == -* ]] ; then
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
fi
@ -280,49 +287,49 @@ _saltcp(){
case ${prev} in
salt-cp)
COMPREPLY=($(compgen -W "${opts} `salt-key -l acc --no-color`" -- ${cur}))
COMPREPLY=($(compgen -W "${opts} $(salt-key -l acc --no-color)" -- ${cur}))
return 0
;;
-t|--timeout)
-t | --timeout)
# those numbers are just a hint
COMPREPLY=($(compgen -W "2 3 4 8 10 15 20 25 30 40 60 90 120 180 240 300" -- ${cur} ))
COMPREPLY=($(compgen -W "2 3 4 8 10 15 20 25 30 40 60 90 120 180 240 300" -- ${cur}))
return 0
;;
-E|--pcre)
COMPREPLY=($(compgen -W "`salt-key -l acc --no-color`" -- ${cur}))
-E | --pcre)
COMPREPLY=($(compgen -W "$(salt-key -l acc --no-color)" -- ${cur}))
return 0
;;
-L|--list)
-L | --list)
# IMPROVEMENTS ARE WELCOME
prefpart="${cur%,*},"
postpart=${cur##*,}
filt="^\($(echo ${cur}| sed 's:,:\\|:g')\)$"
filt="^\($(echo ${cur} | sed 's:,:\\|:g')\)$"
helper=($(salt-key -l acc --no-color | grep -v "${filt}" | sed "s/^/${prefpart}/"))
COMPREPLY=($(compgen -W "${helper[*]}" -- ${cur}))
return 0
;;
-G|--grain|--grain-pcre)
-G | --grain | --grain-pcre)
COMPREPLY=($(compgen -W "$(_salt_get_grains)" -- ${cur}))
return 0
;;
# FIXME
-R|--range)
-R | --range)
# FIXME ??
return 0
;;
-C|--compound)
-C | --compound)
# FIXME ??
return 0
;;
-c|--config)
-c | --config)
COMPREPLY=($(compgen -f -- ${cur}))
return 0
;;
esac
# default is using opts:
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
}
complete -F _saltcp salt-cp

View File

@ -5,7 +5,7 @@ export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/}
_sshcomplete() {
local CURRENT_PROMPT="${COMP_WORDS[COMP_CWORD]}"
if [[ ${CURRENT_PROMPT} == *@* ]] ; then
if [[ ${CURRENT_PROMPT} == *@* ]]; then
local OPTIONS="-P ${CURRENT_PROMPT/@*/}@ -- ${CURRENT_PROMPT/*@/}"
else
local OPTIONS=" -- ${CURRENT_PROMPT}"
@ -15,26 +15,25 @@ _sshcomplete() {
for fl in "$HOME/.ssh/config" \
$(grep "^\s*Include" "$HOME/.ssh/config" |
awk '{for (i=2; i<=NF; i++) print $i}' |
sed -Ee "s|^([^/~])|$HOME/.ssh/\1|" -e "s|^~/|$HOME/|")
do
sed -Ee "s|^([^/~])|$HOME/.ssh/\1|" -e "s|^~/|$HOME/|"); do
if [ -r "$fl" ]; then
COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "$(grep -i ^Host "$fl" |grep -v '[*!]' | awk '{for (i=2; i<=NF; i++) print $i}' )" ${OPTIONS}) )
COMPREPLY=(${COMPREPLY[@]} $(compgen -W "$(grep -i ^Host "$fl" | grep -v '[*!]' | awk '{for (i=2; i<=NF; i++) print $i}')" ${OPTIONS}))
fi
done
# parse all hosts found in .ssh/known_hosts
if [ -r "$HOME/.ssh/known_hosts" ]; then
if grep -v -q -e '^ ssh-rsa' "$HOME/.ssh/known_hosts" ; then
COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "$( awk '{print $1}' "$HOME/.ssh/known_hosts" | grep -v ^\| | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" ${OPTIONS}) )
if grep -v -q -e '^ ssh-rsa' "$HOME/.ssh/known_hosts"; then
COMPREPLY=(${COMPREPLY[@]} $(compgen -W "$(awk '{print $1}' "$HOME/.ssh/known_hosts" | grep -v ^\| | cut -d, -f 1 | sed -e 's/\[//g' | sed -e 's/\]//g' | cut -d: -f1 | grep -v ssh-rsa)" ${OPTIONS}))
fi
fi
# parse hosts defined in /etc/hosts
if [ -r /etc/hosts ]; then
COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "$( grep -v '^[[:space:]]*$' /etc/hosts | grep -v '^#' | awk '{for (i=2; i<=NF; i++) print $i}' )" ${OPTIONS}) )
COMPREPLY=(${COMPREPLY[@]} $(compgen -W "$(grep -v '^[[:space:]]*$' /etc/hosts | grep -v '^#' | awk '{for (i=2; i<=NF; i++) print $i}')" ${OPTIONS}))
fi
return 0
}
complete -o default -o nospace -F _sshcomplete ssh scp slogin
complete -o default -o nospace -F _sshcomplete ssh scp slogin sftp

View File

@ -1,28 +1,25 @@
#!/usr/bin/env bash
# Loads the system's Bash completion modules.
# If Homebrew is installed (OS X), its Bash completion modules are loaded.
# If Homebrew is installed (OS X), it's Bash completion modules are loaded.
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
if [[ -r /etc/bash_completion ]] ; then
# shellcheck disable=SC1091
source /etc/bash_completion
# Some distribution makes use of a profile.d script to import completion.
if [ -f /etc/profile.d/bash_completion.sh ]; then
. /etc/profile.d/bash_completion.sh
elif [[ -r /etc/profile.d/bash_completion.sh ]] ; then
# shellcheck disable=SC1091
source /etc/profile.d/bash_completion.sh
fi
if [ $(uname) = "Darwin" ] && command -v brew &>/dev/null ; then
BREW_PREFIX=$(brew --prefix)
if [ -f "$BREW_PREFIX"/etc/bash_completion ]; then
. "$BREW_PREFIX"/etc/bash_completion
fi
if [[ "$(uname -s)" == 'Darwin' ]] && _command_exists brew ; then
BREW_PREFIX=${BREW_PREFIX:-$(brew --prefix)}
# homebrew/versions/bash-completion2 (required for projects.completion.bash) is installed to this path
if [ "${BASH_VERSINFO}" -ge 4 ] && [ -f "$BREW_PREFIX"/share/bash-completion/bash_completion ]; then
export BASH_COMPLETION_COMPAT_DIR="$BREW_PREFIX"/etc/bash_completion.d
. "$BREW_PREFIX"/share/bash-completion/bash_completion
if [[ -r "$BREW_PREFIX"/etc/profile.d/bash_completion.sh ]] ; then
# shellcheck disable=SC1090
source "$BREW_PREFIX"/etc/profile.d/bash_completion.sh
fi
fi

View File

@ -1,65 +1,10 @@
#!/usr/bin/env bash
#
# Bash completion for the terraform command
#
# Copyright (C) 2018 Vangelis Tasoulas
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
_terraform()
{
local cur prev words cword opts
_get_comp_words_by_ref -n : cur prev words cword
COMPREPLY=()
opts=""
# Make sure terraform is installed
_command_exists terraform || return
if [[ ${cword} -eq 1 ]] ; then
# Don't handle completion if it's already managed
complete -p terraform &>/dev/null && return
# Options that do not start with a hyphen, are always starting with four spaces.
opts="$(terraform --help | grep -E '^\s\s\s\s\S' | awk '{print $1}')"
opts="${opts} --help --version"
elif [[ ${cword} -gt 1 ]] ; then
if [[ ${cword} -eq 2 && ${prev} == '--help' ]] ; then
opts="$(terraform --help | grep -E '^\s\s\s\s\S' | awk '{print $1}')"
elif [[ ${words[1]} != "--help" && ${words[1]} != "--version" && ${words[1]} != "version" ]] ; then
# Some commands accept hyphened parameters, ...
opts="$(terraform --help "${words[1]}" | grep -E '^\s+-' | awk '{print $1}' | awk -F '=' '{ if ($0 ~ /=/) {print $1"="} else {print $1} }')"
# but some other commands accept non-hyphened parameters.
opts="${opts} $(terraform --help "${words[1]}" | grep -E '^\s\s\s\s\S' | awk '{print $1}')"
# All of the commands accept the --help parameter which is not listed
# by the 'terraform --help <command>
opts="${opts} --help"
fi
fi
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
if [[ ${#COMPREPLY[*]} -eq 1 ]] ; then
if [[ ${COMPREPLY[0]} == *= ]] ; then
# When only one completion is left, check if there is an equal sign.
# If an equal sign, then add no space after the autocompleted word.
compopt -o nospace
fi
fi
return 0
}
complete -F _terraform terraform
# Terraform completes itself
complete -C terraform terraform

View File

@ -1,6 +1,6 @@
#!/usr/bin/bash
_vboxmanage_realopts() {
echo $(vboxmanage|grep -i vboxmanage|cut -d' ' -f2|grep '\['|tr -s '[\[\|\]\n' ' ')
echo $(vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | grep '\[' | tr -s '[\[\|\]\n' ' ')
echo " "
}
@ -10,13 +10,13 @@ __vboxmanage_startvm() {
AVAILABLE=""
for VM in $TOTAL; do
MATCH=0;
MATCH=0
for RUN in $RUNNING "x"; do
if [ "$VM" == "$RUN" ]; then
MATCH=1
fi
done
(( $MATCH == 0 )) && AVAILABLE="$AVAILABLE $VM "
(($MATCH == 0)) && AVAILABLE="$AVAILABLE $VM "
done
echo $AVAILABLE
}
@ -27,8 +27,8 @@ __vboxmanage_list() {
PRUNED=""
if [ "$1" == "long" ]; then
for WORD in $INPUT; do
[ "$WORD" == "-l" ] && continue;
[ "$WORD" == "--long" ] && continue;
[ "$WORD" == "-l" ] && continue
[ "$WORD" == "--long" ] && continue
PRUNED="$PRUNED $WORD"
done
@ -39,7 +39,6 @@ __vboxmanage_list() {
echo $PRUNED
}
__vboxmanage_list_vms() {
VMS=""
if [ "x$1" == "x" ]; then
@ -81,9 +80,9 @@ __vboxmanage_controlvm() {
echo "screenshotpng setcredentials teleport plugcpu unplugcpu"
echo "cpuexecutioncap"
# setlinkstate<1-N>
# nic<1-N> null|nat|bridged|intnet|hostonly|generic
# [<devicename>] |
# setlinkstate<1-N>
# nic<1-N> null|nat|bridged|intnet|hostonly|generic
# [<devicename>] |
# nictrace<1-N> on|off
# nictracefile<1-N> <filename>
# nicproperty<1-N> name=[value]
@ -107,7 +106,7 @@ __vboxmanage_default() {
# COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
;;
esac;
esac
for WORD in $opts; do
MATCH=0
@ -115,26 +114,26 @@ __vboxmanage_default() {
# opts=$(echo ${opts} | grep -v $OPT);
if [ "$OPT" == "$WORD" ]; then
MATCH=1
break;
break
fi
if [ "$OPT" == "-v" ] && [ "$WORD" == "--version" ]; then
MATCH=1
break;
break
fi
if [ "$OPT" == "--version" ] && [ "$WORD" == "-v" ]; then
MATCH=1
break;
break
fi
if [ "$OPT" == "-q" ] && [ "$WORD" == "--nologo" ]; then
MATCH=1
break;
break
fi
if [ "$OPT" == "--nologo" ] && [ "$WORD" == "-q" ]; then
MATCH=1
break;
break
fi
done
(( $MATCH == 1 )) && continue;
(($MATCH == 1)) && continue
pruned="$pruned $WORD"
done
@ -149,30 +148,30 @@ _vboxmanage() {
local cur p1 p2 p3 p4 opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
prev="${COMP_WORDS[COMP_CWORD - 1]}"
# echo "cur: |$cur|"
# echo "prev: |$prev|"
# In case current is complete command
case $cur in
startvm|list|controlvm)
startvm | list | controlvm)
COMPREPLY=($(compgen -W "$cur "))
return 0
;;
esac
case $prev in
-v|--version)
-v | --version)
return 0
;;
-l|--long)
-l | --long)
opts=$(__vboxmanage_list "long")
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
;;
startvm|list)
startvm | list)
opts=$(__vboxmanage_$prev)
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
@ -181,11 +180,11 @@ _vboxmanage() {
COMPREPLY=($(compgen -W "gui headless" -- ${cur}))
return 0
;;
gui|headless)
gui | headless)
# Done. no more completion possible
return 0
;;
vboxmanage|-q|--nologo)
vboxmanage | -q | --nologo)
# echo "Got vboxmanage"
opts=$(__vboxmanage_default)
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
@ -200,7 +199,7 @@ _vboxmanage() {
for VM in $(__vboxmanage_list_vms); do
if [ "$VM" == "$prev" ]; then
pprev=${COMP_WORDS[COMP_CWORD-2]}
pprev=${COMP_WORDS[COMP_CWORD - 2]}
# echo "previous: $pprev"
case $pprev in
startvm)
@ -211,7 +210,7 @@ _vboxmanage() {
controlvm)
opts=$(__vboxmanage_controlvm)
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0;
return 0
;;
esac
fi

View File

@ -19,9 +19,11 @@ function _command_exists ()
{
_about 'checks for existence of a command'
_param '1: command to check'
_param '2: (optional) log message to include when command not found'
_example '$ _command_exists ls && echo exists'
_group 'lib'
type "$1" &> /dev/null ;
local msg="${2:-Command '$1' does not exist!}"
type "$1" &> /dev/null || (_log_warning "$msg" && return 1) ;
}
function _make_reload_alias() {
@ -43,7 +45,7 @@ alias reload_plugins="$(_make_reload_alias plugin plugins)"
bash-it ()
{
about 'Bash-it help and maintenance'
param '1: verb [one of: help | show | enable | disable | migrate | update | search | version | reload ] '
param '1: verb [one of: help | show | enable | disable | migrate | update | search | version | reload | restart | doctor ] '
param '2: component type [one of: alias(es) | completion(s) | plugin(s) ] or search term(s)'
param '3: specific component [optional]'
example '$ bash-it show plugins'
@ -55,6 +57,8 @@ bash-it ()
example '$ bash-it search [-|@]term1 [-|@]term2 ... [ -e/--enable ] [ -d/--disable ] [ -r/--refresh ] [ -c/--no-color ]'
example '$ bash-it version'
example '$ bash-it reload'
example '$ bash-it restart'
example '$ bash-it doctor errors|warnings|all'
typeset verb=${1:-}
shift
typeset component=${1:-}
@ -70,15 +74,19 @@ bash-it ()
func=_disable-$component;;
help)
func=_help-$component;;
doctor)
func=_bash-it-doctor-$component;;
search)
_bash-it-search $component "$@"
return;;
update)
func=_bash-it_update;;
func=_bash-it_update-$component;;
migrate)
func=_bash-it-migrate;;
version)
func=_bash-it-version;;
restart)
func=_bash-it-restart;;
reload)
func=_bash-it-reload;;
*)
@ -109,6 +117,10 @@ bash-it ()
do
$func $arg
done
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
_bash-it-reload
fi
else
$func "$@"
fi
@ -146,43 +158,26 @@ _bash-it-plugins ()
_bash-it-describe "plugins" "a" "plugin" "Plugin"
}
_bash-it_update() {
_about 'updates Bash-it'
_bash-it_update-dev() {
_about 'updates Bash-it to the latest master'
_group 'lib'
local old_pwd="${PWD}"
_bash-it_update- dev "$@"
}
cd "${BASH_IT}" || return
_bash-it_update-stable() {
_about 'updates Bash-it to the latest tag'
_group 'lib'
if [ -z $BASH_IT_REMOTE ]; then
BASH_IT_REMOTE="origin"
fi
_bash-it_update- stable "$@"
}
git fetch &> /dev/null
declare status
status="$(git rev-list master..${BASH_IT_REMOTE}/master 2> /dev/null)"
if [[ -n "${status}" ]]; then
for i in $(git rev-list --merges --first-parent master..${BASH_IT_REMOTE}); do
num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l)
if [ $num_of_lines -eq 1 ]; then
description="%s"
else
description="%b"
fi
git log --format="%h: $description (%an)" -1 $i
done
echo ""
read -e -n 1 -p "Would you like to update to $(git log -1 --format=%h origin/master)? [Y/n] " RESP
case $RESP in
[yY]|"")
git pull --rebase &> /dev/null
_bash-it_pull_and_update_inner() {
git checkout "$1" &> /dev/null
if [[ $? -eq 0 ]]; then
echo "Bash-it successfully updated."
echo ""
echo "Migrating your installation to the latest version now..."
echo "Migrating your installation to the latest $2 version now..."
_bash-it-migrate
echo ""
echo "All done, enjoy!"
@ -190,17 +185,101 @@ _bash-it_update() {
else
echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean."
fi
}
_bash-it_update-() {
_about 'updates Bash-it'
_param '1: What kind of update to do (stable|dev)'
_group 'lib'
declare silent
for word in $@; do
if [[ ${word} == "--silent" || ${word} == "-s" ]]; then
silent=true
fi
done
local old_pwd="${PWD}"
cd "${BASH_IT}" || return
if [ -z "$BASH_IT_REMOTE" ]; then
BASH_IT_REMOTE="origin"
fi
git fetch $BASH_IT_REMOTE --tags &> /dev/null
if [ -z "$BASH_IT_DEVELOPMENT_BRANCH" ]; then
BASH_IT_DEVELOPMENT_BRANCH="master"
fi
# Defaults to stable update
if [ -z "$1" ] || [ "$1" == "stable" ]; then
version="stable"
TARGET=$(git describe --tags "$(git rev-list --tags --max-count=1)" 2> /dev/null)
if [[ -z "$TARGET" ]]; then
echo "Can not find tags, so can not update to latest stable version..."
return
fi
else
version="dev"
TARGET=${BASH_IT_REMOTE}/${BASH_IT_DEVELOPMENT_BRANCH}
fi
declare revision
revision="HEAD..${TARGET}"
declare status
status="$(git rev-list ${revision} 2> /dev/null)"
declare revert
if [[ -z "${status}" && ${version} == "stable" ]]; then
revision="${TARGET}..HEAD"
status="$(git rev-list ${revision} 2> /dev/null)"
revert=true
fi
if [[ -n "${status}" ]]; then
if [[ $revert ]]; then
echo "Your version is a more recent development version ($(git log -1 --format=%h HEAD))"
echo "You can continue in order to revert and update to the latest stable version"
echo ""
log_color="%Cred"
fi
for i in $(git rev-list --merges --first-parent ${revision}); do
num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l)
if [ $num_of_lines -eq 1 ]; then
description="%s"
else
description="%b"
fi
git log --format="${log_color}%h: $description (%an)" -1 $i
done
echo ""
if [[ $silent ]]; then
echo "Updating to ${TARGET}($(git log -1 --format=%h "${TARGET}"))..."
_bash-it_pull_and_update_inner $TARGET $version
else
read -e -n 1 -p "Would you like to update to ${TARGET}($(git log -1 --format=%h "${TARGET}"))? [Y/n] " RESP
case $RESP in
[yY]|"")
_bash-it_pull_and_update_inner $TARGET $version
;;
[nN])
echo "Not upgrading…"
echo "Not updating…"
;;
*)
echo -e "\033[91mPlease choose y or n.\033[m"
;;
esac
fi
else
if [[ ${version} == "stable" ]]; then
echo "You're on the latest stable version. If you want to check out the latest 'dev' version, please run \"bash-it update dev\""
else
echo "Bash-it is up to date, nothing to do!"
fi
fi
cd "${old_pwd}" &> /dev/null || return
}
@ -234,6 +313,10 @@ _bash-it-migrate() {
done
done
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
_bash-it-reload
fi
if [ "$migrated_something" = "true" ]; then
echo ""
echo "If any migration errors were reported, please try the following: reload && bash-it migrate"
@ -263,6 +346,61 @@ _bash-it-version() {
cd - &> /dev/null || return
}
_bash-it-doctor() {
_about 'reloads a profile file with a BASH_IT_LOG_LEVEL set'
_param '1: BASH_IT_LOG_LEVEL argument: "errors" "warnings" "all"'
_group 'lib'
BASH_IT_LOG_LEVEL=$1
_bash-it-reload
unset BASH_IT_LOG_LEVEL
}
_bash-it-doctor-all() {
_about 'reloads a profile file with error, warning and debug logs'
_group 'lib'
_bash-it-doctor $BASH_IT_LOG_LEVEL_ALL
}
_bash-it-doctor-warnings() {
_about 'reloads a profile file with error and warning logs'
_group 'lib'
_bash-it-doctor $BASH_IT_LOG_LEVEL_WARNING
}
_bash-it-doctor-errors() {
_about 'reloads a profile file with error logs'
_group 'lib'
_bash-it-doctor $BASH_IT_LOG_LEVEL_ERROR
}
_bash-it-doctor-() {
_about 'default bash-it doctor behavior, behaves like bash-it doctor all'
_group 'lib'
_bash-it-doctor-all
}
_bash-it-restart() {
_about 'restarts the shell in order to fully reload it'
_group 'lib'
saved_pwd=$(pwd)
case $OSTYPE in
darwin*)
init_file=.bash_profile
;;
*)
init_file=.bashrc
;;
esac
exec "${0/-/}" --rcfile <(echo "source \"$HOME/$init_file\"; cd \"$saved_pwd\"")
}
_bash-it-reload() {
_about 'reloads a profile file'
_group 'lib'
@ -318,6 +456,17 @@ _bash-it-describe ()
printf '%s\n' "$ bash-it disable $file_type <$file_type name> [$file_type name]... -or- $ bash-it disable $file_type all"
}
_on-disable-callback()
{
_about 'Calls the disabled plugin destructor, if present'
_param '1: plugin name'
_example '$ _on-disable-callback gitstatus'
_group 'lib'
callback=$1_on_disable
_command_exists $callback && $callback
}
_disable-plugin ()
{
_about 'disables bash_it plugin'
@ -326,6 +475,7 @@ _disable-plugin ()
_group 'lib'
_disable-thing "plugins" "plugin" $1
_on-disable-callback $1
}
_disable-alias ()
@ -400,10 +550,6 @@ _disable-thing ()
_bash-it-clean-component-cache "${file_type}"
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
exec ${0/-/}
fi
printf '%s\n' "$file_entity disabled."
}
@ -500,10 +646,6 @@ _enable-thing ()
_bash-it-clean-component-cache "${file_type}"
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
exec ${0/-/}
fi
printf '%s\n' "$file_entity enabled with priority $use_load_priority."
}

60
lib/log.bash 100644
View File

@ -0,0 +1,60 @@
#!/usr/bin/env bash
export BASH_IT_LOG_LEVEL_ERROR=1
export BASH_IT_LOG_LEVEL_WARNING=2
export BASH_IT_LOG_LEVEL_ALL=3
function _has_colors()
{
# Check that stdout is a terminal
test -t 1 || return 1
ncolors=$(tput colors)
test -n "$ncolors" && test "$ncolors" -ge 8 || return 1
return 0
}
function _log_general()
{
about 'Internal function used for logging, uses BASH_IT_LOG_PREFIX as a prefix'
param '1: color of the message'
param '2: log level to print before the prefix'
param '3: message to log'
group 'log'
message=$2${BASH_IT_LOG_PREFIX}$3
_has_colors && echo -e "$1${message}${echo_normal}" || echo -e "${message}"
}
function _log_debug()
{
about 'log a debug message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_ALL'
param '1: message to log'
example '$ _log_debug "Loading plugin git..."'
group 'log'
[[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_ALL ]] || return 0
_log_general "${echo_green}" "DEBUG: " "$1"
}
function _log_warning()
{
about 'log a message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_WARNING'
param '1: message to log'
example '$ _log_warning "git binary not found, disabling git plugin..."'
group 'log'
[[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_WARNING ]] || return 0
_log_general "${echo_yellow}" " WARN: " "$1"
}
function _log_error()
{
about 'log a message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_ERROR'
param '1: message to log'
example '$ _log_error "Failed to load git plugin..."'
group 'log'
[[ "$BASH_IT_LOG_LEVEL" -ge $BASH_IT_LOG_LEVEL_ERROR ]] || return 0
_log_general "${echo_red}" "ERROR: " "$1"
}

View File

@ -6,6 +6,24 @@
# Generic utilies
###########################################################################
_bash-it-get-component-name-from-path() {
# filename without path
filename=${1##*/}
# filename without path or priority
filename=${filename##*---}
# filename without path, priority or extension
echo ${filename%.*.bash}
}
_bash-it-get-component-type-from-path() {
# filename without path
filename=${1##*/}
# filename without path or priority
filename=${filename##*---}
# extension
echo ${filename} | cut -d '.' -f 2
}
# This function searches an array for an exact match against the term passed
# as the first argument to the function. This function exits as soon as
# a match is found.

View File

@ -71,7 +71,7 @@ function alias_completion {
# with the last word in the unaliased form, i.e.,
# alias_cmd + ' ' + alias_args.
if [[ \$COMP_LINE == \"\$prec_word \$compl_word\" ]]; then
prec_word=\"$alias_cmd $alias_args\"
prec_word='$alias_cmd $alias_args'
prec_word=\${prec_word#* }
fi
(( COMP_CWORD += ${#alias_arg_words[@]} ))

View File

@ -40,7 +40,8 @@ function __awskeys_help {
function __awskeys_get {
local ln=$(grep -n "\[ *$1 *\]" "${AWS_SHARED_CREDENTIALS_FILE}" | cut -d ":" -f 1)
if [[ -n "${ln}" ]]; then
tail -n +${ln} "${AWS_SHARED_CREDENTIALS_FILE}" | egrep -m 3 "aws_access_key_id|aws_secret_access_key|aws_session_token"
tail -n +${ln} "${AWS_SHARED_CREDENTIALS_FILE}" | egrep -m 2 "aws_access_key_id|aws_secret_access_key"
tail -n +${ln} "${AWS_SHARED_CREDENTIALS_FILE}" | egrep -m 1 "aws_session_token"
fi
}

View File

@ -32,7 +32,7 @@ function myip ()
list=("http://myip.dnsomatic.com/" "http://checkip.dyndns.com/" "http://checkip.dyndns.org/")
for url in ${list[*]}
do
res=$(curl -s "${url}")
res=$(curl -fs "${url}")
if [ $? -eq 0 ];then
break;
fi

View File

@ -29,12 +29,28 @@ End-Of-Usage
[ $# -eq 0 ] && extract -h && return 1
while [ $# -gt 0 ]; do
if [[ ! -f "$1" ]]; then
echo "extract: '$1' is not a valid file" >&2
shift
continue
fi
local -r filename=$(basename -- $1)
local -r filedirname=$(dirname -- $1)
local targetdirname=$(sed 's/\(\.tar\.bz2$\|\.tbz$\|\.tbz2$\|\.tar\.gz$\|\.tgz$\|\.tar$\|\.tar\.xz$\|\.txz$\|\.tar\.Z$\|\.7z$\)//g' <<< $filename)
if [ "$filename" = "$targetdirname" ]; then
# archive type either not supported or it doesn't need dir creation
targetdirname=""
else
mkdir -v "$filedirname/$targetdirname"
fi
if [ -f "$1" ]; then
case "$1" in
*.tar.bz2|*.tbz|*.tbz2) tar "x${verbose}jf" "$1" ;;
*.tar.gz|*.tgz) tar "x${verbose}zf" "$1" ;;
*.tar.xz) xz --decompress "$1"; set -- "$@" "${1:0:-3}" ;;
*.tar.Z) uncompress "$1"; set -- "$@" "${1:0:-2}" ;;
*.tar.bz2|*.tbz|*.tbz2) tar "x${verbose}jf" "$1" -C "$filedirname/$targetdirname" ;;
*.tar.gz|*.tgz) tar "x${verbose}zf" "$1" -C "$filedirname/$targetdirname" ;;
*.tar.xz|*.txz) tar "x${verbose}Jf" "$1" -C "$filedirname/$targetdirname" ;;
*.tar.Z) tar "x${verbose}Zf" "$1" -C "$filedirname/$targetdirname" ;;
*.bz2) bunzip2 "$1" ;;
*.deb) dpkg-deb -x${verbose} "$1" "${1:0:-4}" ;;
*.pax.gz) gunzip "$1"; set -- "$@" "${1:0:-3}" ;;
@ -43,17 +59,15 @@ End-Of-Usage
*.pkg) pkgutil --expand "$1" "${1:0:-4}" ;;
*.rar) unrar x "$1" ;;
*.rpm) rpm2cpio "$1" | cpio -idm${verbose} ;;
*.tar) tar "x${verbose}f" "$1" ;;
*.txz) mv "$1" "${1:0:-4}.tar.xz"; set -- "$@" "${1:0:-4}.tar.xz" ;;
*.tar) tar "x${verbose}f" "$1" -C "$filedirname/$targetdirname" ;;
*.xz) xz --decompress "$1" ;;
*.zip|*.war|*.jar) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7za x "$1" ;;
*) echo "'$1' cannot be extracted via extract" >&2;;
esac
else
echo "extract: '$1' is not a valid file" >&2
fi
shift
done
}

View File

@ -0,0 +1,6 @@
cite about-plugin
about-plugin 'load fasd, if you are using it'
_command_exists fasd || return
eval "$(fasd --init auto)"

View File

@ -4,14 +4,16 @@
cite about-plugin
about-plugin 'load fzf, if you are using it'
if [ -f ~/.fzf.bash ]; then
_command_exists fzf || return
if [ -r ~/.fzf.bash ] ; then
source ~/.fzf.bash
elif [ -f "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash ]; then
elif [ -r "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash ] ; then
source "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash
fi
if [ -z ${FZF_DEFAULT_COMMAND+x} ]; then
command -v fd &> /dev/null && export FZF_DEFAULT_COMMAND='fd --type f'
if [ -z ${FZF_DEFAULT_COMMAND+x} ] && _command_exists fd ; then
export FZF_DEFAULT_COMMAND='fd --type f'
fi
fe() {

View File

@ -1,4 +0,0 @@
cite about-plugin
about-plugin 'load gh, if you are using it (DEPRECATED, use hub instead)'
command -v gh 2> /dev/null && eval "$(gh alias -s)"

View File

@ -162,7 +162,7 @@ function v2gif {
if [[ "$use_gifski" = "true" ]] ; then
# I trust @pornel to do his own resizing optimization choices
$ffmpeg -loglevel panic -i "$file" -r $fps -vcodec png v2gif-tmp-%05d.png && \
$gifski $maxwidthski --fps $(printf "%.0f" $fps) -o "$output_file" v2gif-tmp-*.png || return 2
$gifski v2gif-tmp-*.png $maxwidthski --fps $(printf "%.0f" $fps) -o "$output_file" || return 2
else
$ffmpeg -loglevel panic -i "$file" $maxsize -r $fps -vcodec png v2gif-tmp-%05d.png && \
$convert +dither -layers Optimize v2gif-tmp-*.png GIF:- | \

View File

@ -0,0 +1,26 @@
cite about-plugin
about-plugin 'speeds up your life by using gitstatus for git status calculations. install from https://github.com/romkatv/gitstatus'
function gitstatus_on_disable() {
about 'Destructor of gitstatus plugin'
group 'gitstatus'
unset SCM_GIT_USE_GITSTATUS
_command_exists gitstatus_stop && gitstatus_stop
}
# No scm-check
[[ $SCM_CHECK == "true" ]] || return
# non-interactive shell
[[ $- == *i* ]] || return
: "${SCM_GIT_GITSTATUS_DIR:="$HOME/gitstatus"}"
if [[ -d ${SCM_GIT_GITSTATUS_DIR} ]]; then
source "${SCM_GIT_GITSTATUS_DIR}/gitstatus.plugin.sh"
# Start the actual gitstatus binary
gitstatus_stop && gitstatus_start -s -1 -u -1 -c -1 -d -1
export SCM_GIT_USE_GITSTATUS=true
else
_log_warning "Could not find gitstatus directory in ${SCM_GIT_GITSTATUS_DIR}. Please specify directory location using SCM_GIT_GITSTATUS_DIR."
fi

View File

@ -0,0 +1,20 @@
cite about-plugin
about-plugin 'load goenv, if you are using it'
# Don't modify the environment if we can't find the tool:
# - Check if in $PATH already
# - Check if installed manually to $GOENV_ROOT
# - Check if installed manually to $HOME
_command_exists goenv ||
[[ -n "$GOENV_ROOT" && -x "$GOENV_ROOT/bin/goenv" ]] ||
[[ -x "$HOME/.goenv/bin/goenv" ]] ||
return
# Set GOENV_ROOT, if not already set
export GOENV_ROOT="${GOENV_ROOT:-$HOME/.goenv}"
# Add GOENV_ROOT/bin to PATH, if that's where it's installed
! _command_exists goenv && [[ -x "$GOENV_ROOT/bin/goenv" ]] && pathmunge "$GOENV_ROOT/bin"
# Initialize goenv
eval "$(goenv init - bash)"

View File

@ -1,7 +1,22 @@
cite about-plugin
about-plugin 'load jenv, if you are using it'
export JENV_ROOT="$HOME/.jenv"
pathmunge "$JENV_ROOT/bin"
# Don't modify the environment if we can't find the tool:
# - Check if in $PATH already
# - Check if installed manually to $JENV_ROOT
# - Check if installed manually to $HOME
_command_exists jenv ||
[[ -n "$JENV_ROOT" && -x "$JENV_ROOT/bin/jenv" ]] ||
[[ -x "$HOME/.jenv/bin/jenv" ]] ||
return
if which jenv > /dev/null; then eval "$(jenv init - bash)"; fi
# Set JENV_ROOT, if not already set
export JENV_ROOT="${JENV_ROOT:-$HOME/.jenv}"
# Add JENV_ROOT/bin to PATH, if that's where it's installed
! _command_exists jenv &&
[[ -x "$JENV_ROOT/bin/jenv" ]] &&
pathmunge "$JENV_ROOT/bin"
# Initialize jenv
eval "$(jenv init - bash)"

View File

@ -1,7 +1,13 @@
cite about-plugin
about-plugin 'Node.js helper functions'
# Ensure local modules are preferred in PATH
pathmunge "./node_modules/.bin" "after"
# Make sure the global npm prefix is on the path
[[ `which npm 2>/dev/null` ]] && pathmunge "$(npm config get prefix)/bin" "after"
# Check that we have npm
out=$(command -v npm 2>&1) || return
# If not using nodenv, ensure global modules are in PATH
if [[ ! $out == *"nodenv/shims"* ]] ; then
pathmunge "$(npm config get prefix)/bin" "after"
fi

View File

@ -1,5 +1,5 @@
cite about-plugin
about-plugin 'add "export PROJECT_PATHS=~/projects:~/intertrode/projects" to navigate quickly to your project directories with `pj` and `pjo`'
about-plugin 'quickly navigate configured paths with `pj` and `pjo`. example: "export PROJECT_PATHS=~/projects:~/work/projects"'
function pj {
about 'navigate quickly to your various project directories'

View File

@ -94,7 +94,6 @@ function _ensure_valid_sshagent_env() {
return
fi
echo "There's a dead ssh-agent at the landing..."
ssh-agent > "${SSH_AGENT_ENV}"
return
}

View File

@ -0,0 +1,22 @@
cite about-plugin
about-plugin 'Toggle sudo at the beginning of the current or the previous command by hitting the ESC key twice'
function sudo-command-line() {
about "toggle sudo at the beginning of the current or the previous command by hitting the ESC key twice"
group "sudo"
[[ ${#READLINE_LINE} -eq 0 ]] && READLINE_LINE=$(fc -l -n -1 | xargs)
if [[ $READLINE_LINE == sudo\ * ]]; then
READLINE_LINE="${READLINE_LINE#sudo }"
else
READLINE_LINE="sudo $READLINE_LINE"
fi
READLINE_POINT=${#READLINE_LINE}
}
# Define shortcut keys: [Esc] [Esc]
# Readline library requires bash version 4 or later
if [ "${BASH_VERSINFO}" -ge 4 ]; then
bind -x '"\e\e": sudo-command-line'
fi

View File

@ -1,12 +0,0 @@
cite about-plugin
about-plugin 'Defines the `code` executable for Visual Studio Code on OS X'
# Based on https://code.visualstudio.com/Docs/editor/setup
if [[ `uname -s` == "Darwin" ]]; then
function code () {
about 'Starts Visual Studio Code in the provided directory'
group 'visual-studio-code'
VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" --args $* ;
}
fi

View File

@ -3,7 +3,7 @@ about-plugin 'automatically set your xterm title with host and location info'
_short-dirname () {
local dir_name=`dirs -0`
local dir_name=`dirs +0`
[ "$SHORT_TERM_LINE" = true ] && [ ${#dir_name} -gt 8 ] && echo ${dir_name##*/} || echo $dir_name
}

View File

@ -1,15 +1,26 @@
#!/bin/bash
BASH_IT_LOG_PREFIX="core: reloader: "
pushd "${BASH_IT}" >/dev/null || exit 1
# TODO: Add debugging output
function _set-prefix-based-on-path()
{
filename=$(_bash-it-get-component-name-from-path "$1")
extension=$(_bash-it-get-component-type-from-path "$1")
BASH_IT_LOG_PREFIX="$extension: $filename: "
}
if [ "$1" != "skip" ] && [ -d "./enabled" ]; then
_bash_it_config_type=""
if [[ "${1}" =~ ^(alias|completion|plugin)$ ]]; then
_bash_it_config_type=$1
_log_debug "Loading enabled $1 components..."
else
_log_debug "Loading all enabled components..."
fi
for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${_bash_it_config_type}.bash")); do
if [ -e "${_bash_it_config_file}" ]; then
_set-prefix-based-on-path "${_bash_it_config_file}"
_log_debug "Loading component..."
# shellcheck source=/dev/null
source $_bash_it_config_file
else
@ -20,9 +31,11 @@ fi
if [ ! -z "${2}" ] && [[ "${2}" =~ ^(aliases|completion|plugins)$ ]] && [ -d "${2}/enabled" ]; then
# TODO: We should warn users they're using legacy enabling
_log_warning "Using legacy enabling for $2, please update your bash-it version and migrate"
for _bash_it_config_file in $(sort <(compgen -G "./${2}/enabled/*.bash")); do
if [ -e "$_bash_it_config_file" ]; then
_set-prefix-based-on-path "${_bash_it_config_file}"
_log_debug "Loading component..."
# shellcheck source=/dev/null
source "$_bash_it_config_file"
else

View File

@ -18,6 +18,10 @@ export BASH_IT_THEME='bobby'
# cloned bash-it with a remote other than origin such as `bash-it`.
# export BASH_IT_REMOTE='bash-it'
# (Advanced): Change this to the name of the main development branch if
# you renamed it or if it was changed for some reason
# export BASH_IT_DEVELOPMENT_BRANCH='master'
# Your place for hosting Git repos. I use this for private repos.
export GIT_HOSTING='git@git.domain.com'
@ -32,6 +36,10 @@ export TODO="t"
# Set this to false to turn off version control status checking within the prompt for all themes
export SCM_CHECK=true
# Set to actual location of gitstatus directory if installed
#export SCM_GIT_GITSTATUS_DIR="$HOME/gitstatus"
# per default gitstatus uses 2 times as many threads as CPU cores, you can change this here if you must
#export GITSTATUS_NUM_THREADS=8
# Set Xterm/screen/Tmux title with only a short hostname.
# Uncomment this (or set SHORT_HOSTNAME to something else),

View File

@ -1,4 +1,13 @@
## Testing with [Bats](https://github.com/sstephenson/bats#installing-bats-from-source)
# Testing with Bats
## Overview
The Bash-it unit tests leverage the [Bats unit test framework for Bash](https://github.com/bats-core/bats-core).
There is no need to install Bats explicitly, the test run script will automatically download and install Bats and its dependencies.
When making changes to Bash-it, the tests are automatically executed in a test build environment on [Travis CI](https://travis-ci.com).
## Test Execution
To execute the unit tests, please run the `run` script:
@ -10,4 +19,22 @@ To execute the unit tests, please run the `run` script:
test/run
```
The `run` script will automatically install [Bats](https://github.com/sstephenson/bats#installing-bats-from-source) if it is not already present, and will then run all tests found under the `test` directory, including subdirectories.
The `run` script will automatically install if it is not already present, and will then run all tests found under the `test` directory, including subdirectories.
To run only a subset of the tests, you can provide the name of the test subdirectory that you want to run, e.g. like this for the tests in the `test/themes` directory:
```bash
# If you are in the root `.bash_it` directory:
test/run test/themes
```
By default, the tests run in single-threaded mode.
If you want to speed up the test execution, you can install the [GNU `parallel` tool](https://www.gnu.org/software/parallel/), which is supported by Bats.
When using `parallel`, the `test/run` script will use a number of threads in parallel, depending on the available CPU cores of your system.
This can speed up test execution significantly.
## Writing Tests
When adding or modifying tests, please stick to the format and conventions of the existing test cases.
The `test_helper.bash` script provides a couple of reusable helper functions that you should use when writing a test case,
for example for setting up an isolated test environment.

View File

@ -4,36 +4,17 @@ load ../test_helper
load ../../lib/composure
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
echo "Bi : $BASH_IT"
echo "Lib: $lib_directory"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
setup_test_fixture
# Copy the test fixture to the Bash-it folder
if command -v rsync &> /dev/null
then
rsync -a "$BASH_IT/test/fixtures/bash_it/" "$BASH_IT/"
# Don't pollute the user's actual $HOME directory
# Use a test home directory instead
export BASH_IT_TEST_CURRENT_HOME="${HOME}"
export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME"
mkdir -p "${BASH_IT_TEST_HOME}"
export HOME="${BASH_IT_TEST_HOME}"
}
function local_teardown {
export HOME="${BASH_IT_TEST_CURRENT_HOME}"
rm -rf "${BASH_IT_TEST_HOME}"
assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}"
else
find "$BASH_IT/test/fixtures/bash_it" \
-mindepth 1 -maxdepth 1 \
-exec cp -r {} "$BASH_IT/" \;
fi
}
@test "bash-it: verify that the test fixture is available" {

View File

@ -5,36 +5,7 @@ load ../../lib/composure
load ../../completion/available/bash-it.completion
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
# Don't pollute the user's actual $HOME directory
# Use a test home directory instead
export BASH_IT_TEST_CURRENT_HOME="${HOME}"
export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME"
mkdir -p "${BASH_IT_TEST_HOME}"
export HOME="${BASH_IT_TEST_HOME}"
}
function local_teardown {
export HOME="${BASH_IT_TEST_CURRENT_HOME}"
rm -rf "${BASH_IT_TEST_HOME}"
assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}"
setup_test_fixture
}
@test "completion bash-it: ensure that the _bash-it-comp function is available" {
@ -72,6 +43,11 @@ function __check_completion () {
echo "${COMPREPLY[@]}"
}
@test "completion bash-it: doctor - show options" {
run __check_completion 'bash-it doctor '
assert_line -n 0 "errors warnings all"
}
@test "completion bash-it: help - show options" {
run __check_completion 'bash-it help '
assert_line -n 0 "aliases completions migrate plugins update"
@ -82,9 +58,14 @@ function __check_completion () {
assert_line -n 0 "vagrant vault vim"
}
@test "completion bash-it: update - show no options" {
@test "completion bash-it: update - show options" {
run __check_completion 'bash-it update '
assert_line -n 0 ""
assert_line -n 0 "stable dev"
}
@test "completion bash-it: update - show optional flags" {
run __check_completion 'bash-it update -'
assert_line -n 0 "-s --silent"
}
@test "completion bash-it: search - show no options" {
@ -99,32 +80,32 @@ function __check_completion () {
@test "completion bash-it: show options" {
run __check_completion 'bash-it '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: bash-ti - show options" {
run __check_completion 'bash-ti '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: shit - show options" {
run __check_completion 'shit '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: bashit - show options" {
run __check_completion 'bashit '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: batshit - show options" {
run __check_completion 'batshit '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: bash_it - show options" {
run __check_completion 'bash_it '
assert_line -n 0 "disable enable help migrate reload search show update version"
assert_line -n 0 "disable enable help migrate reload restart doctor search show update version"
}
@test "completion bash-it: show - show options" {

4
test/fixtures/svn/broken/svn vendored 100755
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Simply return an error code to simulate a broken SVN installation
exit 72

10
test/fixtures/svn/working/svn vendored 100755
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# If the info command is called
# AND the parent folder contains the .svn folder
# THEN return the current path, similar to what `svn info` does
if [[ "$1" == "info" ]] && [[ -d "../.svn" ]]; then
echo "$PWD"
fi
exit 0

View File

@ -14,31 +14,7 @@ case $OSTYPE in
esac
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
# Don't pollute the user's actual $HOME directory
# Use a test home directory instead
export BASH_IT_TEST_CURRENT_HOME="${HOME}"
export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME"
mkdir -p "${BASH_IT_TEST_HOME}"
export HOME="${BASH_IT_TEST_HOME}"
}
function local_teardown {
export HOME="${BASH_IT_TEST_CURRENT_HOME}"
rm -rf "${BASH_IT_TEST_HOME}"
assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}"
setup_test_fixture
}
@test "install: verify that the install script exists" {

View File

@ -14,31 +14,7 @@ case $OSTYPE in
esac
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
# Don't pollute the user's actual $HOME directory
# Use a test home directory instead
export BASH_IT_TEST_CURRENT_HOME="${HOME}"
export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME"
mkdir -p "${BASH_IT_TEST_HOME}"
export HOME="${BASH_IT_TEST_HOME}"
}
function local_teardown {
export HOME="${BASH_IT_TEST_CURRENT_HOME}"
rm -rf "${BASH_IT_TEST_HOME}"
assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}"
setup_test_fixture
}
@test "uninstall: verify that the uninstall script exists" {

View File

@ -2,6 +2,7 @@
load ../test_helper
load ../../lib/composure
load ../../lib/log
load ../../lib/utilities
load ../../lib/search
load ../../plugins/available/base.plugin
@ -11,21 +12,7 @@ cite _about _param _example _group _author _version
load ../../lib/helpers
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
setup_test_fixture
}
# TODO Create global __is_enabled function
@ -33,7 +20,7 @@ function local_setup {
# TODO Create global __get_enabled_name function
@test "helpers: _command_exists function exists" {
type -a _command_exists &> /dev/null
run type -a _command_exists &> /dev/null
assert_success
}
@ -141,8 +128,8 @@ function local_setup {
@test "helpers: enable the brew completion" {
run _enable-completion "brew"
assert_line -n 0 'brew enabled with priority 350.'
assert_link_exist "$BASH_IT/enabled/350---brew.completion.bash"
assert_line -n 0 'brew enabled with priority 375.'
assert_link_exist "$BASH_IT/enabled/375---brew.completion.bash"
}
@test "helpers: enable the node plugin" {

86
test/lib/log.bats 100644
View File

@ -0,0 +1,86 @@
#!/usr/bin/env bats
load ../test_helper
load ../../lib/composure
load ../../lib/appearance
load ../../plugins/available/base.plugin
cite _about _param _example _group _author _version
load ../../lib/log
@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_ALL" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL
run _log_debug "test test test"
assert_output "DEBUG: test test test"
}
@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_ALL" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL
run _log_warning "test test test"
assert_output " WARN: test test test"
}
@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_ALL" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL
run _log_error "test test test"
assert_output "ERROR: test test test"
}
@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_WARNING" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING
run _log_debug "test test test"
refute_output
}
@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_WARNING" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING
run _log_warning "test test test"
assert_output " WARN: test test test"
}
@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_WARNING" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_WARNING
run _log_error "test test test"
assert_output "ERROR: test test test"
}
@test "lib log: basic debug logging with BASH_IT_LOG_LEVEL_ERROR" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR
run _log_debug "test test test"
refute_output
}
@test "lib log: basic warning logging with BASH_IT_LOG_LEVEL_ERROR" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR
run _log_warning "test test test"
refute_output
}
@test "lib log: basic error logging with BASH_IT_LOG_LEVEL_ERROR" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ERROR
run _log_error "test test test"
assert_output "ERROR: test test test"
}
@test "lib log: basic debug silent logging" {
run _log_debug "test test test"
refute_output
}
@test "lib log: basic warning silent logging" {
run _log_warning "test test test"
refute_output
}
@test "lib log: basic error silent logging" {
run _log_error "test test test"
refute_output
}
@test "lib log: logging with prefix" {
BASH_IT_LOG_LEVEL=$BASH_IT_LOG_LEVEL_ALL
BASH_IT_LOG_PREFIX="nice: prefix: "
run _log_debug "test test test"
assert_output "DEBUG: nice: prefix: test test test"
}

View File

@ -2,9 +2,13 @@
load ../test_helper
load ../../lib/composure
load ../../lib/log
load ../../lib/helpers
load ../../lib/utilities
load ../../lib/search
cite _about _param _example _group _author _version
load ../../plugins/available/base.plugin
load ../../aliases/available/git.aliases
load ../../plugins/available/ruby.plugin
@ -13,27 +17,10 @@ load ../../completion/available/bundler.completion
load ../../completion/available/gem.completion
load ../../completion/available/rake.completion
cite _about _param _example _group _author _version
load ../../lib/helpers
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
rm -rf "$BASH_IT"/tmp/cache
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
setup_test_fixture
export OLD_PATH="$PATH"
export PATH="/usr/bin:/bin:/usr/sbin"
@ -53,8 +40,13 @@ function local_teardown {
@test "search: git" {
run _bash-it-search 'git' --no-color
assert_line -n 0 ' aliases: git gitsvn '
assert_line -n 1 ' plugins: autojump git git-subrepo jgitflow jump '
assert_line -n 2 ' completions: git git_flow git_flow_avh '
assert_line -n 1 -p ' plugins:'
for plugin in "autojump" "git" "gitstatus" "git-subrepo" "jgitflow" "jump"
do
echo $plugin
assert_line -n 1 -p $plugin
done
assert_line -n 2 ' completions: git git_flow git_flow_avh github-cli '
}
@test "search: ruby gem bundle rake rails" {

View File

@ -9,22 +9,7 @@ load ../../lib/search
cite _about _param _example _group _author _version
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
rm -rf "$BASH_IT"/tmp/cache
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
setup_test_fixture
}
function has_match() {

View File

@ -0,0 +1,24 @@
#!/usr/bin/env bats
load ../test_helper
load ../../lib/composure
load ../../lib/log
load ../../lib/helpers
cite _about _param _example _group _author _version
load ../../completion/available/git.completion
@test "alias-completion: See that aliases with double quotes and brackets do not break the plugin" {
alias gtest="git log --graph --pretty=format:'%C(bold)%h%Creset%C(magenta)%d%Creset %s %C(yellow)<%an> %C(cyan)(%cr)%Creset' --abbrev-commit --date=relative"
load ../../plugins/available/alias-completion.plugin
assert_success
}
@test "alias-completion: See that aliases with single 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'
load ../../plugins/available/alias-completion.plugin
assert_success
}

View File

@ -16,10 +16,6 @@ load ../../plugins/available/base.plugin
}
@test 'plugins base: myip()' {
if [[ ! $SLOW_TESTS ]]; then
skip 'myip is slow - run only with SLOW_TESTS=true'
fi
run myip
assert_success
declare -r mask_ip=$(echo $output | tr -s '[0-9]' '?')
@ -43,7 +39,7 @@ load ../../plugins/available/base.plugin
mkcd "${dir_name}"
assert_success
assert_file_exist "${BASH_IT_ROOT}/${dir_name}"
assert_dir_exist "${BASH_IT_ROOT}/${dir_name}"
assert_equal $(pwd) "${BASH_IT_ROOT}/${dir_name}"
}

View File

@ -5,12 +5,14 @@ load ../../lib/helpers
load ../../lib/composure
@test 'ensure _go_pathmunge_wrap is defined' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
load ../../plugins/available/go.plugin
run type -t _go_pathmunge_wrap
assert_line 'function'
}
@test 'plugins go: single entry in GOPATH' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo"
export GOROOT="/baz"
load ../../plugins/available/go.plugin
@ -18,6 +20,7 @@ load ../../lib/composure
}
@test 'plugins go: single entry in GOPATH, with space' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo bar"
export GOROOT="/baz"
load ../../plugins/available/go.plugin
@ -25,6 +28,7 @@ load ../../lib/composure
}
@test 'plugins go: single entry in GOPATH, with escaped space' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo\ bar"
export GOROOT="/baz"
load ../../plugins/available/go.plugin
@ -32,6 +36,7 @@ load ../../lib/composure
}
@test 'plugins go: multiple entries in GOPATH' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo:/bar"
export GOROOT="/baz"
load ../../plugins/available/go.plugin
@ -39,6 +44,7 @@ load ../../lib/composure
}
@test 'plugins go: multiple entries in GOPATH, with space' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo:/foo bar"
export GOROOT="/baz"
load ../../plugins/available/go.plugin
@ -46,6 +52,7 @@ load ../../lib/composure
}
@test 'plugins go: multiple entries in GOPATH, with escaped space' {
{ [[ $CI ]] || _command_exists go; } || skip 'golang not found'
export GOPATH="/foo:/foo\ bar"
export GOROOT="/baz"
load ../../plugins/available/go.plugin

View File

@ -6,21 +6,7 @@ load ../../lib/composure
load ../../plugins/available/ruby.plugin
function local_setup {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
setup_test_fixture
export OLD_PATH="$PATH"
export PATH="/usr/bin:/bin:/usr/sbin"

View File

@ -16,4 +16,33 @@ else
test_dirs=( "$1" )
fi
exec $bats_executable ${CI:+--tap} "${test_dirs[@]}"
# Make sure that the `parallel` command is installed,
# AND that it is the GNU version of `parallel`.
# If that is the case, try to guess the number of CPU cores,
# so we can run `bats` in parallel processing mode, which is a lot faster.
if command -v parallel &> /dev/null \
&& parallel -V &> /dev/null \
&& { parallel -V 2> /dev/null | grep -q '^GNU\>'; }
then
# Expect to run at least on a dual-core CPU; slightly degraded performance
# shouldn't matter otherwise.
declare -i -r test_jobs_default=2
declare -i -r test_jobs_effective="$(
if [ "${TEST_JOBS:-detect}" = "detect" ] \
&& command -v nproc &> /dev/null
then
nproc
elif [ -n "${TEST_JOBS}" ] \
&& [ "${TEST_JOBS}" != "detect" ]
then
echo "${TEST_JOBS}"
else
echo ${test_jobs_default}
fi
)"
exec "$bats_executable" ${CI:+--tap} --jobs ${test_jobs_effective} \
"${test_dirs[@]}"
else
# Run `bats` in single-threaded mode.
exec "$bats_executable" ${CI:+--tap} "${test_dirs[@]}"
fi

View File

@ -6,17 +6,12 @@ unset TODO
unset SCM_CHECK
unset BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE
BASH_IT_TEST_DIR="${BATS_TMPDIR}/.bash_it"
# guard against executing this block twice due to bats internals
if [ "$BASH_IT_ROOT" != "${BASH_IT_TEST_DIR}/root" ]; then
export BASH_IT_ROOT="${BASH_IT_TEST_DIR}/root"
export BASH_IT=$BASH_IT_TEST_DIR
fi
export TEST_MAIN_DIR="${BATS_TEST_DIRNAME}/.."
export TEST_DEPS_DIR="${TEST_DEPS_DIR-${TEST_MAIN_DIR}/../test_lib}"
# be independent of git's system configuration
export GIT_CONFIG_NOSYSTEM
load "${TEST_DEPS_DIR}/bats-support/load.bash"
load "${TEST_DEPS_DIR}/bats-assert/load.bash"
load "${TEST_DEPS_DIR}/bats-file/load.bash"
@ -29,9 +24,70 @@ local_teardown() {
true
}
# This function sets up a local test fixture, i.e. a completely
# fresh and isolated Bash-it directory. This is done to avoid
# messing with your own Bash-it source directory.
# If you need this, call it in your .bats file's `local_setup` function.
setup_test_fixture() {
mkdir -p "$BASH_IT"
lib_directory="$(cd "$(dirname "$0")" && pwd)"
local src_topdir="$lib_directory/../../../.."
if command -v rsync &> /dev/null
then
# Use rsync to copy Bash-it to the temp folder
rsync -qavrKL -d --delete-excluded --exclude=.git --exclude=enabled "$src_topdir" "$BASH_IT"
else
rm -rf "$BASH_IT"
mkdir -p "$BASH_IT"
find "$src_topdir" \
-mindepth 1 -maxdepth 1 \
-not -name .git \
-exec cp -r {} "$BASH_IT" \;
fi
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
# Some tests use the BASH_IT_TEST_HOME variable, e.g. install/uninstall
export BASH_IT_TEST_HOME="$TEST_TEMP_DIR"
}
setup() {
# The `temp_make` function from "bats-file" requires the tralston/bats-file fork,
# since the original ztombol/bats-file's `temp_make` does not work on macOS.
TEST_TEMP_DIR="$(temp_make --prefix 'bash-it-test-')"
export TEST_TEMP_DIR
export BASH_IT_TEST_DIR="${TEST_TEMP_DIR}/.bash_it"
export BASH_IT_ROOT="${BASH_IT_TEST_DIR}/root"
export BASH_IT=$BASH_IT_TEST_DIR
mkdir -p -- "${BASH_IT_ROOT}"
# Some tools, e.g. `git` use configuration files from the $HOME directory,
# which interferes with our tests. The only way to keep `git` from doing this
# seems to set HOME explicitly to a separate location.
# Refer to https://git-scm.com/docs/git-config#FILES.
unset XDG_CONFIG_HOME
export HOME="${TEST_TEMP_DIR}"
mkdir -p "${HOME}"
# For `git` tests to run well, user name and email need to be set.
# Refer to https://git-scm.com/docs/git-commit#_commit_information.
# This goes to the test-specific config, due to the $HOME overridden above.
git config --global user.name "John Doe"
git config --global user.email "johndoe@example.com"
local_setup
}
@ -39,49 +95,5 @@ teardown() {
local_teardown
rm -rf "${BASH_IT_TEST_DIR}"
}
# Fail and display path of the link if it does not exist. Also fails
# if the path exists, but is not a link.
# This function is the logical complement of `assert_file_not_exist'.
# There is no dedicated function for checking that a link does not exist.
#
# Globals:
# BATSLIB_FILE_PATH_REM
# BATSLIB_FILE_PATH_ADD
# Arguments:
# $1 - path
# Returns:
# 0 - link exists and is a link
# 1 - otherwise
# Outputs:
# STDERR - details, on failure
assert_link_exist() {
local -r file="$1"
local -r target="$2"
if [[ ! -L "$file" ]]; then
local -r rem="$BATSLIB_FILE_PATH_REM"
local -r add="$BATSLIB_FILE_PATH_ADD"
if [[ -e "$file" ]]; then
batslib_print_kv_single 4 'path' "${file/$rem/$add}" \
| batslib_decorate 'exists, but is not a link' \
| fail
else
batslib_print_kv_single 4 'path' "${file/$rem/$add}" \
| batslib_decorate 'link does not exist' \
| fail
fi
else
if [ -n "$target" ]; then
local link_target=''
link_target=$(readlink "$file")
if [[ "$link_target" != "$target" ]]; then
batslib_print_kv_single_or_multi 8 'path' "${file/$rem/$add}" \
'expected' "$target" \
'actual' "$link_target" \
| batslib_decorate 'link exists, but does not point to target file' \
| fail
fi
fi
fi
temp_del "${TEST_TEMP_DIR}"
}

View File

@ -2,6 +2,7 @@
load ../test_helper
load ../../lib/composure
load ../../lib/log
cite _about _param _example _group _author _version

View File

@ -2,6 +2,7 @@
load ../test_helper
load ../../lib/composure
load ../../lib/log
cite _about _param _example _group _author _version

View File

@ -0,0 +1,129 @@
#!/usr/bin/env bats
load ../test_helper
load ../../lib/composure
load ../../lib/log
cite _about _param _example _group _author _version
load ../../lib/helpers
load ../../themes/base.theme
function local_setup {
setup_test_fixture
# Copy the test fixture to the Bash-it folder
if command -v rsync &> /dev/null
then
rsync -a "$BASH_IT/test/fixtures/bash_it/" "$BASH_IT/"
else
find "$BASH_IT/test/fixtures/bash_it" \
-mindepth 1 -maxdepth 1 \
-exec cp -r {} "$BASH_IT/" \;
fi
export OLD_PATH="$PATH"
}
function local_teardown {
export PATH="$OLD_PATH"
unset OLD_PATH
}
function setup_repo {
upstream="$(mktemp -d)"
pushd "$upstream" > /dev/null
# Create a dummy SVN folder - this will not work with an actual `svn` command,
# but will be enough to trigger the SVN check in the base theme.
mkdir .svn
echo "$upstream"
}
function setup_svn_path {
local svn_path="$1"
# Make sure that the requested SVN script is available
assert_file_exist "$svn_path/svn"
# Make sure that the requested SVN script is on the path
export PATH="$svn_path:/usr/bin:/bin:/usr/sbin"
}
@test 'themes base: SVN: detect SVN repo' {
repo="$(setup_repo)"
pushd "$repo"
setup_svn_path "$BASH_IT/test/fixtures/svn/working"
# Load the base theme again so that the working SVN script is detected
load ../../themes/base.theme
scm
# Make sure that the SVN command is used
assert_equal "$SCM" "$SCM_SVN"
}
@test 'themes base: SVN: detect SVN repo even from a subfolder' {
repo="$(setup_repo)"
pushd "$repo"
mkdir foo
pushd foo
setup_svn_path "$BASH_IT/test/fixtures/svn/working"
# Load the base theme again so that the working SVN script is detected
load ../../themes/base.theme
scm
# Make sure that the SVN command is used
assert_equal "$SCM" "$SCM_SVN"
}
@test 'themes base: SVN: no SCM if no .svn folder can be found' {
repo="$(setup_repo)"
pushd "$repo"
rm -rf .svn
setup_svn_path "$BASH_IT/test/fixtures/svn/working"
# Load the base theme again so that the working SVN script is detected
load ../../themes/base.theme
scm
# Make sure that no SVN command is used
assert_equal "$SCM" "$SCM_NONE"
}
@test 'themes base: SVN: ignore SVN repo when using broken SVN command' {
repo="$(setup_repo)"
pushd "$repo"
setup_svn_path "$BASH_IT/test/fixtures/svn/broken"
# Load the base theme again so that the broken SVN script is detected
load ../../themes/base.theme
scm
# Make sure that no SVN command is not used
assert_equal "$SCM" "$SCM_NONE"
}
@test 'themes base: SVN: ignore SVN repo even from a subfolder when using a broken SVN' {
repo="$(setup_repo)"
pushd "$repo"
mkdir foo
pushd foo
setup_svn_path "$BASH_IT/test/fixtures/svn/broken"
# Load the base theme again so that the broken SVN script is detected
load ../../themes/base.theme
scm
# Make sure that no SVN command is used
assert_equal "$SCM" "$SCM_NONE"
}

@ -1 +1 @@
Subproject commit 9f88b4207da750093baabc4e3f41bf68f0dd3630
Subproject commit d750c5a1b44bf6fc96726aea76f4621db5fd602f

@ -1 +1 @@
Subproject commit 85388685632f85d5a1c32e6bca2deec401964cf7
Subproject commit 73b8d2f95513207b319efe34685553b75c0b214e

@ -1 +1 @@
Subproject commit 2fddb2b831d65cdf2e411f3b47f4677fbb15729c
Subproject commit c128a1de53ba4a811835af410ce427f1049e2d7f

@ -1 +1 @@
Subproject commit 004e707638eedd62e0481e8cdc9223ad471f12ee
Subproject commit 24a72e14349690bcbf7c151b9d2d1cdd32d36eb1

View File

@ -30,7 +30,7 @@ Face="\342\230\273"
____atomic_top_left_parse() {
ifs_old="${IFS}"
IFS="|"
args=( $1 )
args=($1)
IFS="${ifs_old}"
if [ -n "${args[3]}" ]; then
_TOP_LEFT+="${args[2]}${args[3]}"
@ -45,7 +45,7 @@ ____atomic_top_left_parse() {
____atomic_top_right_parse() {
ifs_old="${IFS}"
IFS="|"
args=( $1 )
args=($1)
IFS="${ifs_old}"
_TOP_RIGHT+=" "
if [ -n "${args[3]}" ]; then
@ -55,14 +55,14 @@ ____atomic_top_right_parse() {
if [ -n "${args[4]}" ]; then
_TOP_RIGHT+="${args[2]}${args[4]}"
fi
__TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1 ))
(( __SEG_AT_RIGHT += 1 ))
__TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1))
((__SEG_AT_RIGHT += 1))
}
____atomic_bottom_parse() {
ifs_old="${IFS}"
IFS="|"
args=( $1 )
args=($1)
IFS="${ifs_old}"
_BOTTOM+="${args[0]}${args[1]}"
[ ${#args[1]} -gt 0 ] && _BOTTOM+=" "
@ -87,7 +87,7 @@ ____atomic_top() {
[ -n "${info}" ] && ____atomic_top_right_parse "${info}"
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"
_TOP_LEFT+="${___cursor_adjust}"
@ -151,7 +151,7 @@ ___atomic_prompt_todo() {
[ -z "$(which todo.sh)" ] && return
color=$bold_white
box="[|]"
info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }' )"
info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }')"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}"
}
@ -194,7 +194,7 @@ ___atomic_prompt_char() {
color=$white
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}"
if [ "${THEME_SHOW_SUDO}" == "true" ]; then
if [ $(sudo -n id -u 2>&1 | grep 0) ]; then
if sudo -vn 1>/dev/null 2>&1; then
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}"
fi
fi
@ -226,16 +226,16 @@ _atomic_completion() {
segments="battery clock exitcode python ruby scm sudo todo"
case "${_action}" in
show)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") )
COMPREPLY=($(compgen -W "${segments}" -- "${cur}"))
return 0
;;
hide)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") )
COMPREPLY=($(compgen -W "${segments}" -- "${cur}"))
return 0
;;
esac
COMPREPLY=( $(compgen -W "${actions}" -- "${cur}") )
COMPREPLY=($(compgen -W "${actions}" -- "${cur}"))
return 0
}
@ -246,9 +246,11 @@ atomic() {
typeset func
case $action in
show)
func=__atomic_show;;
func=__atomic_show
;;
hide)
func=__atomic_hide;;
func=__atomic_hide
;;
esac
for seg in ${segs}; do
seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]')

View File

@ -8,6 +8,75 @@ A minimal theme with a clean git prompt
* Current path (red when user is root)
* Current git info
* Last command exit code (only shown when the exit code is greater than 0)
* user@hostname for ssh connection
## Fonts and glyphs
A font with SCM glyphs is required to display the default tool/host logos.
You can use a font from https://www.nerdfonts.com/ or patch your own font with the tool
provided by https://github.com/ryanoasis/nerd-fonts.
You can also override the default variables if you want to use different glyphs or standard ASCII characters.
### Default theme glyphs
```bash
BARBUK_GITLAB_CHAR=' '
BARBUK_BITBUCKET_CHAR=' '
BARBUK_GITHUB_CHAR=' '
BARBUK_GIT_DEFAULT_CHAR=' '
BARBUK_GIT_BRANCH_ICON=''
BARBUK_HG_CHAR='☿ '
BARBUK_SVN_CHAR='⑆ '
BARBUK_EXIT_CODE_ICON=' '
```
### Customize glyphs
Define your custom glyphs before sourcing bash-it:
```bash
export BARBUK_GITHUB_CHAR='•'
source "$BASH_IT"/bash_it.sh
```
## SSH prompt
### Usage
When using a ssh session, the theme will display `user@hostname`.
You can disable this information with `BARBUK_SSH_INFO`.
The hostname is displayed in the FQDN format by default. You
can use the short hostname format with `BARBUK_HOST_INFO`.
```bash
# short or long
export BARBUK_HOST_INFO=short
# true or false
export BARBUK_SSH_INFO=false
source "$BASH_IT"/bash_it.sh
```
### Keep theme with sudoer
If you want the theme to persist using `sudo -s` in a ssh session, you need to configure sudo to keep the `HOME` and `SSH_CONNECTION` environment variables.
`HOME` contains the path to the home directory of the current user. Keeping it will allow to use your user dotfiles when elevating privileges.
Keeping `SSH_CONNECTION` env is necessary for ssh detection in the theme.
Please refer to the following documentation for more information:
- [sudo manual](https://www.sudo.ws/man/1.8.13/sudoers.man.html) for `env_keep` configuration
- [openssh manual](https://linux.die.net/man/1/ssh) for information about `SSH_CONNECTION` environment
```bash
cat << EOF > /etc/sudoers.d/keepenv
Defaults env_keep += HOME
Defaults env_keep += SSH_CONNECTION
EOF
chmod 400 /etc/sudoers.d/keepenv
```
## Examples
@ -21,4 +90,10 @@ A minimal theme with a clean git prompt
```bash
 ~/.dotfiles on  master ⤏ origin ↑2 •7 ✗
```
```
### Ssh
```bash
user@hostname in  ~/bash-it on  master ✓
```

View File

@ -1,13 +1,21 @@
#!/usr/bin/env bash
# shellcheck disable=2034,2154
SCM_GIT_CHAR_GITLAB=' '
SCM_GIT_CHAR_BITBUCKET=' '
SCM_GIT_CHAR_GITHUB=' '
SCM_GIT_CHAR_DEFAULT=' '
SCM_GIT_CHAR_ICON_BRANCH=''
SCM_HG_CHAR='☿ '
SCM_SVN_CHAR='⑆ '
# Theme custom glyphs
SCM_GIT_CHAR_GITLAB=${BARBUK_GITLAB_CHAR:=' '}
SCM_GIT_CHAR_BITBUCKET=${BARBUK_BITBUCKET_CHAR:=' '}
SCM_GIT_CHAR_GITHUB=${BARBUK_GITHUB_CHAR:=' '}
SCM_GIT_CHAR_DEFAULT=${BARBUK_GIT_DEFAULT_CHAR:=' '}
SCM_GIT_CHAR_ICON_BRANCH=${BARBUK_GIT_BRANCH_ICON:=''}
SCM_HG_CHAR=${BARBUK_HG_CHAR:='☿ '}
SCM_SVN_CHAR=${BARBUK_SVN_CHAR:='⑆ '}
EXIT_CODE_ICON=${BARBUK_EXIT_CODE_ICON:=' '}
# Ssh user and hostname display
SSH_INFO=${BARBUK_SSH_INFO:=true}
HOST_INFO=${BARBUK_HOST_INFO:=long}
# Bash-it default glyphs customization
SCM_NONE_CHAR=
SCM_THEME_PROMPT_DIRTY=" ${bold_red}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}"
@ -25,10 +33,9 @@ GIT_THEME_PROMPT_SUFFIX="${cyan}"
SCM_THEME_BRANCH_TRACK_PREFIX="${normal}${cyan}"
SCM_THEME_CURRENT_USER_PREFFIX='  '
SCM_GIT_SHOW_CURRENT_USER=false
EXIT_CODE_ICON=' '
function _git-uptream-remote-logo {
[[ "$(_git-upstream)" == "" ]] && return
[[ "$(_git-upstream)" == "" ]] && SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT"
local remote remote_domain
remote=$(_git-upstream-remote)
@ -59,7 +66,7 @@ function _exit-code {
}
function _prompt {
local exit_code="$?" wrap_char=' ' dir_color=$green
local exit_code="$?" wrap_char=' ' dir_color=$green ssh_info='' python_venv='' host
_exit-code exit_code
_git-uptream-remote-logo
@ -71,7 +78,24 @@ function _prompt {
dir_color=$red
fi
PS1="\\n ${purple}$(scm_char)${dir_color}\\w${normal}$(scm_prompt_info)${exit_code}"
# Detect ssh
if [[ -n "${SSH_CONNECTION}" ]] && [ "$SSH_INFO" = true ]; then
if [ "$HOST_INFO" = long ]; then
host="\H"
else
host="\h"
fi
ssh_info="${bold_blue}\u${bold_orange}@${cyan}$host ${bold_orange}in"
fi
# Detect python venv
if [[ -n "${CONDA_DEFAULT_ENV}" ]]; then
python_venv="${CONDA_DEFAULT_ENV}"
elif [[ -n "${VIRTUAL_ENV}" ]]; then
python_venv=$(basename "${VIRTUAL_ENV}")
fi
PS1="\\n${ssh_info} ${python_venv} ${purple}$(scm_char)${dir_color}\\w${normal}$(scm_prompt_info)${exit_code}"
[[ ${#PS1} -gt $((COLUMNS*3)) ]] && wrap_char="\\n"
PS1="${PS1}${wrap_char}${normal} "

View File

@ -34,6 +34,8 @@ SCM_GIT_SHOW_CURRENT_USER=${SCM_GIT_SHOW_CURRENT_USER:=false}
SCM_GIT_SHOW_MINIMAL_INFO=${SCM_GIT_SHOW_MINIMAL_INFO:=false}
SCM_GIT_SHOW_STASH_INFO=${SCM_GIT_SHOW_STASH_INFO:=true}
SCM_GIT_SHOW_COMMIT_COUNT=${SCM_GIT_SHOW_COMMIT_COUNT:=true}
SCM_GIT_USE_GITSTATUS=${SCM_GIT_USE_GITSTATUS:=false}
SCM_GIT_GITSTATUS_RAN=${SCM_GIT_GITSTATUS_RAN:=false}
SCM_GIT='git'
SCM_GIT_CHAR='±'
@ -74,8 +76,6 @@ THEME_SHOW_USER_HOST=${THEME_SHOW_USER_HOST:=false}
USER_HOST_THEME_PROMPT_PREFIX=''
USER_HOST_THEME_PROMPT_SUFFIX=''
VIRTUAL_ENV=
VIRTUALENV_THEME_PROMPT_PREFIX=' |'
VIRTUALENV_THEME_PROMPT_SUFFIX='|'
@ -85,10 +85,19 @@ RBENV_THEME_PROMPT_SUFFIX='|'
RBFU_THEME_PROMPT_PREFIX=' |'
RBFU_THEME_PROMPT_SUFFIX='|'
GIT_EXE=`which git 2> /dev/null || true`
P4_EXE=`which p4 2> /dev/null || true`
HG_EXE=`which hg 2> /dev/null || true`
SVN_EXE=`which svn 2> /dev/null || true`
GIT_EXE=$(which git 2> /dev/null || true)
P4_EXE=$(which p4 2> /dev/null || true)
HG_EXE=$(which hg 2> /dev/null || true)
SVN_EXE=$(which svn 2> /dev/null || true)
# Check for broken SVN exe that is caused by some versions of Xcode.
# See https://github.com/Bash-it/bash-it/issues/1612 for more details.
if [[ -x "$SVN_EXE" ]] ; then
if ! "$SVN_EXE" --version > /dev/null 2>&1 ; then
# Unset the SVN exe variable so that SVN commands are avoided.
SVN_EXE=""
fi
fi
function scm {
if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE
@ -184,6 +193,12 @@ function git_prompt_minimal_info {
}
function git_prompt_vars {
if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then # use faster gitstatus
SCM_GIT_GITSTATUS_RAN=true # use this in githelpers and below to choose gitstatus output
else
SCM_GIT_GITSTATUS_RAN=false
fi
if _git-branch &> /dev/null; then
SCM_GIT_DETACHED="false"
SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)"
@ -199,7 +214,12 @@ function git_prompt_vars {
SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)"
fi
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
commits_behind=${VCS_STATUS_COMMITS_BEHIND}
commits_ahead=${VCS_STATUS_COMMITS_AHEAD}
else
IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)"
fi
if [[ "${commits_ahead}" -gt 0 ]]; then
SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}"
[[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}"
@ -211,13 +231,23 @@ function git_prompt_vars {
if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then
local stash_count
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
stash_count=${VCS_STATUS_STASHES}
else
stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')"
fi
[[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}"
fi
SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN}
if ! _git-hide-status; then
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
untracked_count=${VCS_STATUS_NUM_UNTRACKED}
unstaged_count=${VCS_STATUS_NUM_UNSTAGED}
staged_count=${VCS_STATUS_NUM_STAGED}
else
IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)"
fi
if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then
SCM_DIRTY=1
if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then
@ -229,6 +259,7 @@ function git_prompt_vars {
fi
fi
# no if for gitstatus here, user extraction is not supported by it
[[ "${SCM_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)"
SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
@ -313,7 +344,7 @@ function hg_prompt_vars {
if [ -f "$HG_ROOT/dirstate" ]; then
# Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState
SCM_CHANGE=$(hexdump -n 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12)
SCM_CHANGE=$(hexdump -vn 10 -e '1/1 "%02x"' "$HG_ROOT/dirstate" | cut -c-12)
else
SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}')
fi

View File

@ -12,8 +12,13 @@ GIT_THEME_PROMPT_SUFFIX="${green}|"
CONDAENV_THEME_PROMPT_SUFFIX="|"
function prompt_command() {
#PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} "
PS1="\n${yellow}$(python_version_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_char)${green}$(scm_prompt_info) ${green}${reset_color} "
PS1="\n${yellow}$(python_version_prompt) " # Name of virtual env followed by python version
PS1+="${purple}\h "
PS1+="${reset_color}in "
PS1+="${green}\w\n"
PS1+="${bold_cyan}$(scm_char)"
PS1+="${green}$(scm_prompt_info) "
PS1+="${green}${reset_color} "
}
safe_append_prompt_command prompt_command

View File

@ -22,8 +22,13 @@ __bobby_clock() {
}
function prompt_command() {
#PS1="${bold_cyan}$(scm_char)${green}$(scm_prompt_info)${purple}$(ruby_version_prompt) ${yellow}\h ${reset_color}in ${green}\w ${reset_color}\n${green}→${reset_color} "
PS1="\n$(battery_char) $(__bobby_clock)${yellow}$(ruby_version_prompt) ${purple}\h ${reset_color}in ${green}\w\n${bold_cyan}$(scm_prompt_char_info) ${green}${reset_color} "
PS1="\n$(battery_char) $(__bobby_clock)"
PS1+="${yellow}$(ruby_version_prompt) "
PS1+="${purple}\h "
PS1+="${reset_color}in "
PS1+="${green}\w\n"
PS1+="${bold_cyan}$(scm_prompt_char_info) "
PS1+="${green}${reset_color} "
}
THEME_SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"}

View File

@ -90,7 +90,7 @@ ____brainy_bottom() {
___brainy_prompt_user_info() {
color=$bold_blue
if [ "${THEME_SHOW_SUDO}" == "true" ]; then
if [ $(sudo -n id -u 2>&1 | grep 0) ]; then
if sudo -vn 1>/dev/null 2>&1; then
color=$bold_red
fi
fi

View File

@ -109,7 +109,7 @@ function __color_white {
function __color_rgb {
r=$1 && g=$2 && b=$3
[[ r == g && g == b ]] && echo $(( $r / 11 + 232 )) && return # gray range above 232
[[ $r == $g && $g == $b ]] && echo $(( $r / 11 + 232 )) && return # gray range above 232
echo "8;5;$(( ($r * 36 + $b * 6 + $g) / 51 + 16 ))"
}

View File

@ -1,45 +1,61 @@
#!/usr/bin/env bash
function _git-symbolic-ref {
git symbolic-ref -q HEAD 2> /dev/null
function _git-symbolic-ref() {
git symbolic-ref -q HEAD 2>/dev/null
}
# When on a branch, this is often the same as _git-commit-description,
# but this can be different when two branches are pointing to the
# same commit. _git-branch is used to explicitly choose the checked-out
# branch.
function _git-branch {
git symbolic-ref -q --short HEAD 2> /dev/null || return 1
function _git-branch() {
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
test -n "${VCS_STATUS_LOCAL_BRANCH}" && echo "${VCS_STATUS_LOCAL_BRANCH}" || return 1
else
git symbolic-ref -q --short HEAD 2>/dev/null || return 1
fi
}
function _git-tag {
git describe --tags --exact-match 2> /dev/null
function _git-tag() {
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
test -n "${VCS_STATUS_TAG}" && echo "${VCS_STATUS_TAG}"
else
git describe --tags --exact-match 2>/dev/null
fi
}
function _git-commit-description {
git describe --contains --all 2> /dev/null
function _git-commit-description() {
git describe --contains --all 2>/dev/null
}
function _git-short-sha {
function _git-short-sha() {
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
echo ${VCS_STATUS_COMMIT:0:7}
else
git rev-parse --short HEAD
fi
}
# Try the checked-out branch first to avoid collision with branches pointing to the same ref.
function _git-friendly-ref {
function _git-friendly-ref() {
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
_git-branch || _git-tag || _git-short-sha # there is no tag based describe output in gitstatus
else
_git-branch || _git-tag || _git-commit-description || _git-short-sha
fi
}
function _git-num-remotes {
function _git-num-remotes() {
git remote | wc -l
}
function _git-upstream {
function _git-upstream() {
local ref
ref="$(_git-symbolic-ref)" || return 1
git for-each-ref --format="%(upstream:short)" "${ref}"
}
function _git-upstream-remote {
function _git-upstream-remote() {
local upstream
upstream="$(_git-upstream)" || return 1
@ -48,35 +64,35 @@ function _git-upstream-remote {
echo "${upstream%"/${branch}"}"
}
function _git-upstream-branch {
function _git-upstream-branch() {
local ref
ref="$(_git-symbolic-ref)" || return 1
# git versions < 2.13.0 do not support "strip" for upstream format
# regex replacement gives the wrong result for any remotes with slashes in the name,
# so only use when the strip format fails.
git for-each-ref --format="%(upstream:strip=3)" "${ref}" 2> /dev/null || git for-each-ref --format="%(upstream)" "${ref}" | sed -e "s/.*\/.*\/.*\///"
git for-each-ref --format="%(upstream:strip=3)" "${ref}" 2>/dev/null || git for-each-ref --format="%(upstream)" "${ref}" | sed -e "s/.*\/.*\/.*\///"
}
function _git-upstream-behind-ahead {
git rev-list --left-right --count "$(_git-upstream)...HEAD" 2> /dev/null
function _git-upstream-behind-ahead() {
git rev-list --left-right --count "$(_git-upstream)...HEAD" 2>/dev/null
}
function _git-upstream-branch-gone {
function _git-upstream-branch-gone() {
[[ "$(git status -s -b | sed -e 's/.* //')" == "[gone]" ]]
}
function _git-hide-status {
function _git-hide-status() {
[[ "$(git config --get bash-it.hide-status)" == "1" ]]
}
function _git-status {
function _git-status() {
local git_status_flags=
[[ "${SCM_GIT_IGNORE_UNTRACKED}" = "true" ]] && git_status_flags='-uno' || true
git status --porcelain ${git_status_flags} 2> /dev/null
git status --porcelain ${git_status_flags} 2>/dev/null
}
function _git-status-counts {
function _git-status-counts() {
_git-status | awk '
BEGIN {
untracked=0;
@ -100,14 +116,37 @@ function _git-status-counts {
}'
}
function _git-remote-info {
[[ "$(_git-upstream)" == "" ]] && return || true
function _git-remote-info() {
[[ "$(_git-branch)" == "$(_git-upstream-branch)" ]] && local same_branch_name=true || true
# prompt handling only, reimplement because patching the routine below gets ugly
if [[ "${SCM_GIT_GITSTATUS_RAN}" == "true" ]]; then
[[ "${VCS_STATUS_REMOTE_NAME}" == "" ]] && return
[[ "${VCS_STATUS_LOCAL_BRANCH}" == "${VCS_STATUS_REMOTE_BRANCH}" ]] && local same_branch_name=true
local same_branch_name=
[[ "${VCS_STATUS_LOCAL_BRANCH}" == "${VCS_STATUS_REMOTE_BRANCH}" ]] && same_branch_name=true
# no multiple remote support in gitstatusd
if [[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "true" || "${SCM_GIT_SHOW_REMOTE_INFO}" = "auto" ]]; then
if [[ "${same_branch_name}" != "true" ]]; then
remote_info="${VCS_STATUS_REMOTE_NAME}/${VCS_STATUS_REMOTE_BRANCH}"
else
remote_info="${VCS_STATUS_REMOTE_NAME}"
fi
elif [[ ${same_branch_name} != "true" ]]; then
remote_info="${VCS_STATUS_REMOTE_BRANCH}"
fi
if [[ -n "${remote_info}" ]]; then
# no support for gone remote branches in gitstatusd
local branch_prefix="${SCM_THEME_BRANCH_TRACK_PREFIX}"
echo "${branch_prefix}${remote_info}"
fi
else
[[ "$(_git-upstream)" == "" ]] && return
[[ "$(_git-branch)" == "$(_git-upstream-branch)" ]] && local same_branch_name=true
local same_branch_name=
[[ "$(_git-branch)" == "$(_git-upstream-branch)" ]] && same_branch_name=true
if ([[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "auto" ]] && [[ "$(_git-num-remotes)" -ge 2 ]]) ||
[[ "${SCM_GIT_SHOW_REMOTE_INFO}" = "true" ]]; then
if [[ ("${SCM_GIT_SHOW_REMOTE_INFO}" = "auto" && "$(_git-num-remotes)" -ge 2) || \
"${SCM_GIT_SHOW_REMOTE_INFO}" = "true" ]]; then
if [[ "${same_branch_name}" != "true" ]]; then
remote_info="\$(_git-upstream)"
else
@ -116,7 +155,7 @@ function _git-remote-info {
elif [[ ${same_branch_name} != "true" ]]; then
remote_info="\$(_git-upstream-branch)"
fi
if [[ -n "${remote_info}" ]];then
if [[ -n "${remote_info}" ]]; then
local branch_prefix
if _git-upstream-branch-gone; then
branch_prefix="${SCM_THEME_BRANCH_GONE_PREFIX}"
@ -125,10 +164,11 @@ function _git-remote-info {
fi
echo "${branch_prefix}${remote_info}"
fi
fi
}
# Unused by bash-it, present for API compatibility
function git_status_summary {
function git_status_summary() {
awk '
BEGIN {
untracked=0;

View File

@ -1,12 +1,10 @@
# git branch parser
function parse_git_branch() {
echo -e "\033[1;34m$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')\033[0m"
echo -e "\033[1;34m$(git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')\033[0m"
}
function parse_git_branch_no_color() {
echo -e "$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')"
echo -e "$(git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/')"
}
function prompt() {

View File

@ -85,5 +85,6 @@ You can configure various aspects of the prompt to use less whitespace. Supporte
|POWERLINE_COMPACT_AFTER_LAST_SEGMENT | Removes the trailing space on the last segment
|POWERLINE_COMPACT_PROMPT | Removes the space after the prompt character
|POWERLINE_COMPACT | Enable all Compact settings (you can still override individual settings)
|POWERLINE_PROMPT_AFTER | Adds characters after the prompt
The default value for all settings is `0` (disabled). Use `1` to enable.

View File

@ -32,6 +32,7 @@ function __powerline_prompt_command {
LEFT_PROMPT=""
SEGMENTS_AT_LEFT=0
LAST_SEGMENT_COLOR=""
PROMPT_AFTER="${POWERLINE_PROMPT_AFTER}"
_save-and-reload-history "${HISTORY_AUTOSAVE:-0}"
@ -51,7 +52,7 @@ function __powerline_prompt_command {
LEFT_PROMPT+=" "
fi
PS1="${LEFT_PROMPT}"
PS1="${LEFT_PROMPT}${PROMPT_AFTER}"
## cleanup ##
unset LAST_SEGMENT_COLOR \

View File

@ -12,6 +12,7 @@ POWERLINE_COMPACT_AFTER_SEPARATOR=${POWERLINE_COMPACT_AFTER_SEPARATOR:=${POWERLI
POWERLINE_COMPACT_BEFOR_FIRST_SEGMENT=${POWERLINE_COMPACT_BEFORE_FIRST_SEGMENT:=${POWERLINE_COMPACT}}
POWERLINE_COMPACT_AFTER_LAST_SEGMENT=${POWERLINE_COMPACT_AFTER_LAST_SEGMENT:=${POWERLINE_COMPACT}}
POWERLINE_COMPACT_PROMPT=${POWERLINE_COMPACT_PROMPT:=${POWERLINE_COMPACT}}
POWERLINE_PROMPT_AFTER=${POWERLINE_PROMPT_AFTER:-""}
PYTHON_VENV_CHAR=${POWERLINE_PYTHON_VENV_CHAR:="ⓔ "}
CONDA_PYTHON_VENV_CHAR=${POWERLINE_CONDA_PYTHON_VENV_CHAR:="ⓔ "}

View File

@ -1,7 +1,7 @@
# Define this here so it can be used by all of the Powerline themes
THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true}
function set_color {
function set_color() {
set +u
if [[ "${1}" != "-" ]]; then
fg="38;5;${1}"
@ -13,14 +13,12 @@ function set_color {
echo -e "\[\033[${fg}${bg}m\]"
}
function __powerline_user_info_prompt {
function __powerline_user_info_prompt() {
local user_info=""
local color=${USER_INFO_THEME_PROMPT_COLOR}
if [[ "${THEME_CHECK_SUDO}" = true ]]; then
if sudo -n uptime 2>&1 | grep -q "load"; then
color=${USER_INFO_THEME_PROMPT_COLOR_SUDO}
fi
sudo -vn 1>/dev/null 2>&1 && color=${USER_INFO_THEME_PROMPT_COLOR_SUDO}
fi
case "${POWERLINE_PROMPT_USER_INFO_MODE}" in
@ -41,7 +39,7 @@ function __powerline_user_info_prompt {
[[ -n "${user_info}" ]] && echo "${user_info}|${color}"
}
function __powerline_terraform_prompt {
function __powerline_terraform_prompt() {
local terraform_workspace=""
if [ -d .terraform ]; then
@ -50,14 +48,14 @@ function __powerline_terraform_prompt {
fi
}
function __powerline_node_prompt {
function __powerline_node_prompt() {
local node_version=""
node_version="$(node_version_prompt)"
[[ -n "${node_version}" ]] && echo "${NODE_CHAR}${node_version}|${NODE_THEME_PROMPT_COLOR}"
}
function __powerline_ruby_prompt {
function __powerline_ruby_prompt() {
local ruby_version=""
if _command_exists rvm; then
@ -69,7 +67,7 @@ function __powerline_ruby_prompt {
[[ -n "${ruby_version}" ]] && echo "${RUBY_CHAR}${ruby_version}|${RUBY_THEME_PROMPT_COLOR}"
}
function __powerline_k8s_context_prompt {
function __powerline_k8s_context_prompt() {
local kubernetes_context=""
if _command_exists kubectl; then
@ -79,7 +77,7 @@ function __powerline_k8s_context_prompt {
[[ -n "${kubernetes_context}" ]] && echo "${KUBERNETES_CONTEXT_THEME_CHAR}${kubernetes_context}|${KUBERNETES_CONTEXT_THEME_PROMPT_COLOR}"
}
function __powerline_python_venv_prompt {
function __powerline_python_venv_prompt() {
set +u
local python_venv=""
@ -93,7 +91,7 @@ function __powerline_python_venv_prompt {
[[ -n "${python_venv}" ]] && echo "${PYTHON_VENV_CHAR}${python_venv}|${PYTHON_VENV_THEME_PROMPT_COLOR}"
}
function __powerline_scm_prompt {
function __powerline_scm_prompt() {
local color=""
local scm_prompt=""
@ -122,27 +120,27 @@ function __powerline_scm_prompt {
fi
}
function __powerline_cwd_prompt {
function __powerline_cwd_prompt() {
local cwd=$(pwd | sed "s|^${HOME}|~|")
echo "${cwd}|${CWD_THEME_PROMPT_COLOR}"
}
function __powerline_hostname_prompt {
function __powerline_hostname_prompt() {
echo "${SHORT_HOSTNAME:-$(hostname -s)}|${HOST_THEME_PROMPT_COLOR}"
}
function __powerline_wd_prompt {
function __powerline_wd_prompt() {
echo "\W|${CWD_THEME_PROMPT_COLOR}"
}
function __powerline_clock_prompt {
function __powerline_clock_prompt() {
echo "$(date +"${THEME_CLOCK_FORMAT}")|${CLOCK_THEME_PROMPT_COLOR}"
}
function __powerline_battery_prompt {
function __powerline_battery_prompt() {
local color=""
local battery_status="$(battery_percentage 2> /dev/null)"
local battery_status="$(battery_percentage 2>/dev/null)"
if [[ -z "${battery_status}" ]] || [[ "${battery_status}" = "-1" ]] || [[ "${battery_status}" = "no" ]]; then
true
@ -159,29 +157,29 @@ function __powerline_battery_prompt {
fi
}
function __powerline_in_vim_prompt {
function __powerline_in_vim_prompt() {
if [ -n "$VIMRUNTIME" ]; then
echo "${IN_VIM_THEME_PROMPT_TEXT}|${IN_VIM_THEME_PROMPT_COLOR}"
fi
}
function __powerline_aws_profile_prompt {
function __powerline_aws_profile_prompt() {
if [[ -n "${AWS_PROFILE}" ]]; then
echo "${AWS_PROFILE_CHAR}${AWS_PROFILE}|${AWS_PROFILE_PROMPT_COLOR}"
fi
}
function __powerline_shlvl_prompt {
function __powerline_shlvl_prompt() {
if [[ "${SHLVL}" -gt 1 ]]; then
local prompt="${SHLVL_THEME_PROMPT_CHAR}"
local level=$(( ${SHLVL} - 1))
local level=$((${SHLVL} - 1))
echo "${prompt}${level}|${SHLVL_THEME_PROMPT_COLOR}"
fi
}
function __powerline_dirstack_prompt {
function __powerline_dirstack_prompt() {
if [[ "${#DIRSTACK[@]}" -gt 1 ]]; then
local depth=$(( ${#DIRSTACK[@]} - 1 ))
local depth=$((${#DIRSTACK[@]} - 1))
local prompt="${DIRSTACK_THEME_PROMPT_CHAR}"
if [[ "${depth}" -ge 2 ]]; then
prompt+="${depth}"
@ -190,17 +188,18 @@ function __powerline_dirstack_prompt {
fi
}
function __powerline_history_number_prompt {
function __powerline_history_number_prompt() {
echo "${HISTORY_NUMBER_THEME_PROMPT_CHAR}\!|${HISTORY_NUMBER_THEME_PROMPT_COLOR}"
}
function __powerline_command_number_prompt {
function __powerline_command_number_prompt() {
echo "${COMMAND_NUMBER_THEME_PROMPT_CHAR}\#|${COMMAND_NUMBER_THEME_PROMPT_COLOR}"
}
function __powerline_left_segment {
local OLD_IFS="${IFS}"; IFS="|"
local params=( $1 )
function __powerline_left_segment() {
local OLD_IFS="${IFS}"
IFS="|"
local params=($1)
IFS="${OLD_IFS}"
local pad_before_segment=" "
@ -226,18 +225,18 @@ function __powerline_left_segment {
LEFT_PROMPT+="$(set_color - ${params[1]})${pad_before_segment}${params[0]}${normal}"
LAST_SEGMENT_COLOR=${params[1]}
(( SEGMENTS_AT_LEFT += 1 ))
((SEGMENTS_AT_LEFT += 1))
}
function __powerline_left_last_segment_padding {
function __powerline_left_last_segment_padding() {
LEFT_PROMPT+="$(set_color - ${LAST_SEGMENT_COLOR}) ${normal}"
}
function __powerline_last_status_prompt {
function __powerline_last_status_prompt() {
[[ "$1" -ne 0 ]] && echo "${1}|${LAST_STATUS_THEME_PROMPT_COLOR}"
}
function __powerline_prompt_command {
function __powerline_prompt_command() {
local last_status="$?" ## always the first
local separator_char="${POWERLINE_PROMPT_CHAR}"
@ -245,7 +244,6 @@ function __powerline_prompt_command {
SEGMENTS_AT_LEFT=0
LAST_SEGMENT_COLOR=""
if [[ -n "${POWERLINE_PROMPT_DISTRO_LOGO}" ]]; then
LEFT_PROMPT+="$(set_color ${PROMPT_DISTRO_LOGO_COLOR} ${PROMPT_DISTRO_LOGO_COLORBG})${PROMPT_DISTRO_LOGO}$(set_color - -)"
fi

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
SCM_THEME_PROMPT_DIRTY=" ${bold_yellow}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}"
SCM_THEME_PROMPT_PREFIX=" ${bold_blue}scm:("
SCM_THEME_PROMPT_SUFFIX="${bold_blue})"
GIT_THEME_PROMPT_DIRTY=" ${bold_yellow}"
GIT_THEME_PROMPT_CLEAN=" ${bold_green}"
GIT_THEME_PROMPT_PREFIX=" ${bold_blue}git:("
GIT_THEME_PROMPT_SUFFIX="${bold_blue})"
RVM_THEME_PROMPT_PREFIX="|"
RVM_THEME_PROMPT_SUFFIX="|"
function git_prompt_info() {
git_prompt_vars
echo -e "$SCM_PREFIX${bold_red}$SCM_BRANCH$SCM_STATE$SCM_SUFFIX"
}
function prompt_command() {
PS1="${bold_green}${bold_cyan}\W${reset_color}$(scm_prompt_info)${normal} "
}
PROMPT_COMMAND=prompt_command