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,32 +1,15 @@
# EditorConfig is awesome: http://EditorConfig.org # EditorConfig is awesome: http://EditorConfig.org
[*] [*]
indent_style = tab indent_style = space
indent_size = 4 indent_size = 2
end_of_line = lf
shell_variant = bash charset = utf-8
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 trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[*.*sh] [.git*]
indent_style = tab 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"] [submodule "test_lib/bats-core"]
path = test_lib/bats-core path = test_lib/bats-core
url = https://github.com/bats-core/bats-core url = https://github.com/bats-core/bats-core
branch = tags/v1.2.0
[submodule "test_lib/bats-support"] [submodule "test_lib/bats-support"]
path = 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"] [submodule "test_lib/bats-assert"]
path = 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"] [submodule "test_lib/bats-file"]
path = 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 # YAML anchors need to appear first.
script: test/run # Keys starting with an underscore are the custom ones, refer to
language: c # https://docs.travis-ci.com/user/build-config-yaml#private-keys-as-yaml-anchors-and-aliases-and-external-tooling
os:
- linux _native_job: &native_job
- osx 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. 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 ## Load Order
### General 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. 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 ## Using the pre-commit hook
Note the file .pre-commit-config.yaml at the top of the repo. Note the file .pre-commit-config.yaml at the top of the repo.

View File

@ -1,6 +1,7 @@
# Bash-it # 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+. **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:) (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 ### Updating
To update Bash-it to the latest version, simply run: To update Bash-it to the latest stable version, simply run:
```bash ```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. 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: 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. 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 ### 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/). 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` * `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 ### Proxy Support
If you are working in a corporate environment where you have to go through a proxy server for internet access, 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 if grep --color=auto "a" "${BASH_IT}/"*.md &> /dev/null
then then
alias grep='grep --color=auto' alias grep='grep --color=auto'
export GREP_COLOR='1;33'
fi fi
if which gshuf &> /dev/null if which gshuf &> /dev/null
@ -75,27 +74,6 @@ fi
alias md='mkdir -p' alias md='mkdir -p'
alias rd='rmdir' 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 # Shorten extract
alias xt="extract" alias xt="extract"
@ -113,3 +91,12 @@ catt() {
fi fi
done 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 gss='git status -s'
alias gsu='git submodule update --init --recursive' alias gsu='git submodule update --init --recursive'
alias gl='git pull' alias gl='git pull'
alias gpl='git pull'
alias glum='git pull upstream master' alias glum='git pull upstream master'
alias gpr='git pull --rebase' alias gpr='git pull --rebase'
alias gpp='git pull && git push' alias gpp='git pull && git push'
@ -35,8 +36,12 @@ alias gpom='git push origin master'
alias gr='git remote' alias gr='git remote'
alias grv='git remote -v' alias grv='git remote -v'
alias gra='git remote add' 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 gd='git diff'
alias gds='git diff --staged' alias gds='git diff --staged'
alias gdt='git difftool'
alias gdv='git diff -w "$@" | vim -R -' alias gdv='git diff -w "$@" | vim -R -'
alias gc='git commit -v' alias gc='git commit -v'
alias gca='git commit -v -a' alias gca='git commit -v -a'
@ -46,6 +51,8 @@ alias gci='git commit --interactive'
alias gcamd='git commit --amend' alias gcamd='git commit --amend'
alias gb='git branch' alias gb='git branch'
alias gba='git branch -a' 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 gbt='git branch --track'
alias gbm='git branch -m' alias gbm='git branch -m'
alias gbd='git branch -d' 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 gmu='git fetch origin -v; git fetch upstream -v; git merge upstream/master'
alias gll='git log --graph --pretty=oneline --abbrev-commit' 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 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 ggs="gg --stat"
alias gsh="git show"
alias gsl="git shortlog -sn" alias gsl="git shortlog -sn"
alias gwc="git whatchanged" alias gwc="git whatchanged"
alias gt="git tag" alias gt="git tag"
@ -79,15 +88,36 @@ alias gnew="git log HEAD@{1}..HEAD@{0}"
alias gcaa="git commit -a --amend -C HEAD" alias gcaa="git commit -a --amend -C HEAD"
# Rebase with latest remote master # Rebase with latest remote master
alias gprom="git fetch origin master && git rebase origin/master && git update-ref refs/heads/master origin/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 gpunch="git push --force-with-lease"
alias ggui="git gui" alias ggui="git gui"
alias gcsam="git commit -S -am" alias gcsam="git commit -S -am"
# Stash aliases
alias gst="git stash" alias gst="git stash"
alias gstb="git stash branch" alias gstb="git stash branch"
alias gstd="git stash drop" alias gstd="git stash drop"
alias gstl="git stash list" 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 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 # Show untracked files
alias gu='git ls-files . --exclude-standard --others' alias gu='git ls-files . --exclude-standard --others'

View File

@ -5,12 +5,11 @@
cite 'about-alias' cite 'about-alias'
about-alias 'kubectl aliases' about-alias 'kubectl aliases'
# set apt aliases
function _set_pkg_aliases() function _set_pkg_aliases()
{ {
if [ -x $(which kubectl) ]; then if _command_exists kubectl; then
alias kc='kubectl' alias kc='kubectl'
alias kcgp='kubectl get pods' alias kcgp='kubectl get pods'
alias kcgd='kubectl get deployments' alias kcgd='kubectl get deployments'
alias kcgn='kubectl get nodes' alias kcgn='kubectl get nodes'
alias kcdp='kubectl describe pod' alias kcdp='kubectl describe pod'
@ -18,8 +17,9 @@ function _set_pkg_aliases()
alias kcdn='kubectl describe node' alias kcdn='kubectl describe node'
alias kcgpan='kubectl get pods --all-namespaces' alias kcgpan='kubectl get pods --all-namespaces'
alias kcgdan='kubectl get deployments --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
fi alias kcnetshoot='kubectl run --generator=run-pod/v1 netshoot-$(date +%s) --rm -i --tty --image nicolaka/netshoot -- /bin/bash'
fi
} }
_set_pkg_aliases _set_pkg_aliases

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' cite 'uuid-alias'
about-alias 'uuidgen aliases' about-alias 'uuidgen aliases'
alias uuidu="uuidgen" if _command_exists uuid; then # Linux
alias uuidl="uuidgen | tr '[:upper:]' '[:lower:]'" alias uuidu="uuid | tr '[:lower:]' '[:upper:]'"
alias uuid=uuidl # because upper case is like YELLING 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 #!/usr/bin/env bash
# Initialize Bash It # Initialize Bash It
BASH_IT_LOG_PREFIX="core: main: "
# Only set $BASH_IT if it's not already set # Only set $BASH_IT if it's not already set
if [ -z "$BASH_IT" ]; if [ -z "$BASH_IT" ];
then then
# Setting $BASH to maintain backwards compatibility # Setting $BASH to maintain backwards compatibility
# TODO: warn users that they should upgrade their .bash_profile
export BASH_IT=$BASH export BASH_IT=$BASH
BASH="$(bash -c 'echo $BASH')" BASH="$(bash -c 'echo $BASH')"
export BASH export BASH
fi BASH_IT_OLD_BASH_SETUP=true
# 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;
fi fi
# Load composure first, so we support function metadata # Load composure first, so we support function metadata
# shellcheck source=./lib/composure.bash # shellcheck source=./lib/composure.bash
source "${BASH_IT}/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 # support 'plumbing' metadata
cite _about _param _example _group _author _version cite _about _param _example _group _author _version
# libraries, but skip appearance (themes) for now # libraries, but skip appearance (themes) for now
_log_debug "Loading libraries(except appearance)..."
LIB="${BASH_IT}/lib/*.bash" LIB="${BASH_IT}/lib/*.bash"
APPEARANCE_LIB="${BASH_IT}/lib/appearance.bash" APPEARANCE_LIB="${BASH_IT}/lib/appearance.bash"
for _bash_it_config_file in $LIB for _bash_it_config_file in $LIB
do do
if [ "$_bash_it_config_file" != "$APPEARANCE_LIB" ]; then 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 # shellcheck disable=SC1090
source "$_bash_it_config_file" source "$_bash_it_config_file"
fi fi
@ -51,36 +63,51 @@ done
# Load theme, if a theme was set # Load theme, if a theme was set
if [[ ! -z "${BASH_IT_THEME}" ]]; then 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 # 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 # shellcheck source=./themes/colors.theme.bash
source "${BASH_IT}/themes/colors.theme.bash" source "${BASH_IT}/themes/colors.theme.bash"
BASH_IT_LOG_PREFIX="themes: githelpers: "
# shellcheck source=./themes/githelpers.theme.bash # shellcheck source=./themes/githelpers.theme.bash
source "${BASH_IT}/themes/githelpers.theme.bash" source "${BASH_IT}/themes/githelpers.theme.bash"
BASH_IT_LOG_PREFIX="themes: p4helpers: "
# shellcheck source=./themes/p4helpers.theme.bash # shellcheck source=./themes/p4helpers.theme.bash
source "${BASH_IT}/themes/p4helpers.theme.bash" source "${BASH_IT}/themes/p4helpers.theme.bash"
BASH_IT_LOG_PREFIX="themes: base: "
# shellcheck source=./themes/base.theme.bash # shellcheck source=./themes/base.theme.bash
source "${BASH_IT}/themes/base.theme.bash" source "${BASH_IT}/themes/base.theme.bash"
BASH_IT_LOG_PREFIX="lib: appearance: "
# appearance (themes) now, after all dependencies # appearance (themes) now, after all dependencies
# shellcheck source=./lib/appearance.bash # shellcheck source=./lib/appearance.bash
source "$APPEARANCE_LIB" source "$APPEARANCE_LIB"
fi 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" for file_type in "aliases" "completion" "plugins"
do do
if [ -e "${BASH_IT}/${file_type}/custom.${file_type}.bash" ] if [ -e "${BASH_IT}/${file_type}/custom.${file_type}.bash" ]
then then
BASH_IT_LOG_PREFIX="${file_type}: custom: "
_log_debug "Loading component..."
# shellcheck disable=SC1090 # shellcheck disable=SC1090
source "${BASH_IT}/${file_type}/custom.${file_type}.bash" source "${BASH_IT}/${file_type}/custom.${file_type}.bash"
fi fi
done done
# Custom # 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" CUSTOM="${BASH_IT_CUSTOM:=${BASH_IT}/custom}/*.bash ${BASH_IT_CUSTOM:=${BASH_IT}/custom}/**/*.bash"
for _bash_it_config_file in $CUSTOM for _bash_it_config_file in $CUSTOM
do do
if [ -e "${_bash_it_config_file}" ]; then 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 # shellcheck disable=SC1090
source "$_bash_it_config_file" source "$_bash_it_config_file"
fi fi

View File

@ -65,7 +65,7 @@ _bash-it-comp()
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD-1]}"
chose_opt="${COMP_WORDS[1]}" chose_opt="${COMP_WORDS[1]}"
file_type="${COMP_WORDS[2]}" 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 case "${chose_opt}" in
show) show)
local show_args="aliases completions plugins" local show_args="aliases completions plugins"
@ -82,7 +82,21 @@ _bash-it-comp()
return 0 return 0
fi 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 return 0
;; ;;
enable | disable) enable | disable)

View File

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

View File

@ -1,11 +1 @@
if which crystal >/dev/null 2>&1; then _log_warning 'Bash completion for "crystal" is now covered by "system". This completion can be disabled.'
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

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 _command_exists oc && source <(oc completion bash)
[ -x "$(which oc)" ] && eval "$(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() { _pj() {
[ -z "$PROJECT_PATHS" ] && return _is_function _init_completion || return
_is_function _rl_enabled || return
[ -n "$PROJECT_PATHS" ] || return
shift shift
[ "$1" == "open" ] && shift [ "$1" == "open" ] && shift
local cur prev words cword local cur
_init_completion || return _init_completion || return
local IFS=$'\n' i j k local IFS=$'\n' i j k
@ -16,8 +24,8 @@ _pj() {
for i in ${PROJECT_PATHS//:/$'\n'}; do for i in ${PROJECT_PATHS//:/$'\n'}; do
# create an array of matched subdirs # create an array of matched subdirs
k="${#COMPREPLY[@]}" k="${#COMPREPLY[@]}"
for j in $( compgen -d $i/$cur ); do for j in $(compgen -d "$i/$cur"); do
if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#$i/} ]]; then
j+="/" j+="/"
fi fi
COMPREPLY[k++]=${j#$i/} COMPREPLY[k++]=${j#$i/}

View File

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

View File

@ -4,37 +4,36 @@
export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/}
_sshcomplete() { _sshcomplete() {
local CURRENT_PROMPT="${COMP_WORDS[COMP_CWORD]}" local CURRENT_PROMPT="${COMP_WORDS[COMP_CWORD]}"
if [[ ${CURRENT_PROMPT} == *@* ]] ; then if [[ ${CURRENT_PROMPT} == *@* ]]; then
local OPTIONS="-P ${CURRENT_PROMPT/@*/}@ -- ${CURRENT_PROMPT/*@/}" local OPTIONS="-P ${CURRENT_PROMPT/@*/}@ -- ${CURRENT_PROMPT/*@/}"
else else
local OPTIONS=" -- ${CURRENT_PROMPT}" local OPTIONS=" -- ${CURRENT_PROMPT}"
fi
# parse all defined hosts from .ssh/config and files included there
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
if [ -r "$fl" ]; then
COMPREPLY=(${COMPREPLY[@]} $(compgen -W "$(grep -i ^Host "$fl" | grep -v '[*!]' | awk '{for (i=2; i<=NF; i++) print $i}')" ${OPTIONS}))
fi fi
done
# parse all defined hosts from .ssh/config and files included there # parse all hosts found in .ssh/known_hosts
for fl in "$HOME/.ssh/config" \ if [ -r "$HOME/.ssh/known_hosts" ]; then
$(grep "^\s*Include" "$HOME/.ssh/config" | if grep -v -q -e '^ ssh-rsa' "$HOME/.ssh/known_hosts"; then
awk '{for (i=2; i<=NF; i++) print $i}' | 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}))
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}) )
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}) )
fi
fi fi
fi
# parse hosts defined in /etc/hosts # parse hosts defined in /etc/hosts
if [ -r /etc/hosts ]; then 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 fi
return 0 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 #!/usr/bin/env bash
# Loads the system's Bash completion modules. # 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 if [[ -r /etc/bash_completion ]] ; then
. /etc/bash_completion # shellcheck disable=SC1091
fi source /etc/bash_completion
# Some distribution makes use of a profile.d script to import completion. # Some distribution makes use of a profile.d script to import completion.
if [ -f /etc/profile.d/bash_completion.sh ]; then elif [[ -r /etc/profile.d/bash_completion.sh ]] ; then
. /etc/profile.d/bash_completion.sh # shellcheck disable=SC1091
source /etc/profile.d/bash_completion.sh
fi fi
if [[ "$(uname -s)" == 'Darwin' ]] && _command_exists brew ; then
BREW_PREFIX=${BREW_PREFIX:-$(brew --prefix)}
if [ $(uname) = "Darwin" ] && command -v brew &>/dev/null ; then # homebrew/versions/bash-completion2 (required for projects.completion.bash) is installed to this path
BREW_PREFIX=$(brew --prefix) if [[ -r "$BREW_PREFIX"/etc/profile.d/bash_completion.sh ]] ; then
# shellcheck disable=SC1090
if [ -f "$BREW_PREFIX"/etc/bash_completion ]; then source "$BREW_PREFIX"/etc/profile.d/bash_completion.sh
. "$BREW_PREFIX"/etc/bash_completion
fi
# 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
fi fi
fi fi

View File

@ -1,65 +1,10 @@
#!/usr/bin/env bash #!/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() # Make sure terraform is installed
{ _command_exists terraform || return
local cur prev words cword opts
_get_comp_words_by_ref -n : cur prev words cword
COMPREPLY=()
opts=""
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. # Terraform completes itself
opts="$(terraform --help | grep -E '^\s\s\s\s\S' | awk '{print $1}')" complete -C terraform terraform
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

View File

@ -1,222 +1,221 @@
#!/usr/bin/bash #!/usr/bin/bash
_vboxmanage_realopts() { _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 " " echo " "
} }
__vboxmanage_startvm() { __vboxmanage_startvm() {
RUNNING=$(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"') RUNNING=$(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"')
TOTAL=$(vboxmanage list vms | cut -d' ' -f1 | tr -d '"') TOTAL=$(vboxmanage list vms | cut -d' ' -f1 | tr -d '"')
AVAILABLE="" AVAILABLE=""
for VM in $TOTAL; do for VM in $TOTAL; do
MATCH=0; MATCH=0
for RUN in $RUNNING "x"; do for RUN in $RUNNING "x"; do
if [ "$VM" == "$RUN" ]; then if [ "$VM" == "$RUN" ]; then
MATCH=1 MATCH=1
fi fi
done
(( $MATCH == 0 )) && AVAILABLE="$AVAILABLE $VM "
done done
echo $AVAILABLE (($MATCH == 0)) && AVAILABLE="$AVAILABLE $VM "
done
echo $AVAILABLE
} }
__vboxmanage_list() { __vboxmanage_list() {
INPUT=$(vboxmanage list | tr -s '[\[\]\|\n]' ' ' | cut -d' ' -f4-) INPUT=$(vboxmanage list | tr -s '[\[\]\|\n]' ' ' | cut -d' ' -f4-)
PRUNED="" PRUNED=""
if [ "$1" == "long" ]; then if [ "$1" == "long" ]; then
for WORD in $INPUT; do for WORD in $INPUT; do
[ "$WORD" == "-l" ] && continue; [ "$WORD" == "-l" ] && continue
[ "$WORD" == "--long" ] && continue; [ "$WORD" == "--long" ] && continue
PRUNED="$PRUNED $WORD" PRUNED="$PRUNED $WORD"
done done
else else
PRUNED=$INPUT PRUNED=$INPUT
fi fi
echo $PRUNED echo $PRUNED
} }
__vboxmanage_list_vms() { __vboxmanage_list_vms() {
VMS="" VMS=""
if [ "x$1" == "x" ]; then if [ "x$1" == "x" ]; then
SEPARATOR=" " SEPARATOR=" "
else else
SEPARATOR=$1 SEPARATOR=$1
fi fi
for VM in $(vboxmanage list vms | cut -d' ' -f1 | tr -d '"'); do for VM in $(vboxmanage list vms | cut -d' ' -f1 | tr -d '"'); do
[ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}" [ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}"
VMS="${VMS}${VM}" VMS="${VMS}${VM}"
done done
echo $VMS echo $VMS
} }
__vboxmanage_list_runningvms() { __vboxmanage_list_runningvms() {
VMS="" VMS=""
if [ "$1" == "" ]; then if [ "$1" == "" ]; then
SEPARATOR=" " SEPARATOR=" "
else else
SEPARATOR=$1 SEPARATOR=$1
fi fi
for VM in $(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"'); do for VM in $(vboxmanage list runningvms | cut -d' ' -f1 | tr -d '"'); do
[ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}" [ "$VMS" != "" ] && VMS="${VMS}${SEPARATOR}"
VMS="${VMS}${VM}" VMS="${VMS}${VM}"
done done
echo $VMS echo $VMS
} }
__vboxmanage_controlvm() { __vboxmanage_controlvm() {
echo "pause resume reset poweroff savestate acpipowerbutton" echo "pause resume reset poweroff savestate acpipowerbutton"
echo "acpisleepbutton keyboardputscancode guestmemoryballoon" echo "acpisleepbutton keyboardputscancode guestmemoryballoon"
echo "gueststatisticsinterval usbattach usbdetach vrde vrdeport" echo "gueststatisticsinterval usbattach usbdetach vrde vrdeport"
echo "vrdeproperty vrdevideochannelquality setvideomodehint" echo "vrdeproperty vrdevideochannelquality setvideomodehint"
echo "screenshotpng setcredentials teleport plugcpu unplugcpu" echo "screenshotpng setcredentials teleport plugcpu unplugcpu"
echo "cpuexecutioncap" echo "cpuexecutioncap"
# setlinkstate<1-N> # setlinkstate<1-N>
# nic<1-N> null|nat|bridged|intnet|hostonly|generic # nic<1-N> null|nat|bridged|intnet|hostonly|generic
# [<devicename>] | # [<devicename>] |
# nictrace<1-N> on|off # nictrace<1-N> on|off
# nictracefile<1-N> <filename> # nictracefile<1-N> <filename>
# nicproperty<1-N> name=[value] # nicproperty<1-N> name=[value]
# natpf<1-N> [<rulename>],tcp|udp,[<hostip>], # natpf<1-N> [<rulename>],tcp|udp,[<hostip>],
# <hostport>,[<guestip>],<guestport> # <hostport>,[<guestip>],<guestport>
# natpf<1-N> delete <rulename> # natpf<1-N> delete <rulename>
} }
__vboxmanage_default() { __vboxmanage_default() {
realopts=$(_vboxmanage_realopts) realopts=$(_vboxmanage_realopts)
opts=$realopts$(vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | grep -v '\[' | sort | uniq) opts=$realopts$(vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | grep -v '\[' | sort | uniq)
pruned="" pruned=""
# echo "" # echo ""
# echo "DEBUG: cur: $cur, prev: $prev" # echo "DEBUG: cur: $cur, prev: $prev"
# echo "DEBUG: default: |$p1|$p2|$p3|$p4|" # echo "DEBUG: default: |$p1|$p2|$p3|$p4|"
case ${cur} in case ${cur} in
-*) -*)
echo $opts echo $opts
# COMPREPLY=($(compgen -W "${opts}" -- ${cur})) # COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
esac; esac
for WORD in $opts; do
MATCH=0
for OPT in "${COMP_WORDS[@]}"; do
# opts=$(echo ${opts} | grep -v $OPT);
if [ "$OPT" == "$WORD" ]; then
MATCH=1
break;
fi
if [ "$OPT" == "-v" ] && [ "$WORD" == "--version" ]; then
MATCH=1
break;
fi
if [ "$OPT" == "--version" ] && [ "$WORD" == "-v" ]; then
MATCH=1
break;
fi
if [ "$OPT" == "-q" ] && [ "$WORD" == "--nologo" ]; then
MATCH=1
break;
fi
if [ "$OPT" == "--nologo" ] && [ "$WORD" == "-q" ]; then
MATCH=1
break;
fi
done
(( $MATCH == 1 )) && continue;
pruned="$pruned $WORD"
for WORD in $opts; do
MATCH=0
for OPT in "${COMP_WORDS[@]}"; do
# opts=$(echo ${opts} | grep -v $OPT);
if [ "$OPT" == "$WORD" ]; then
MATCH=1
break
fi
if [ "$OPT" == "-v" ] && [ "$WORD" == "--version" ]; then
MATCH=1
break
fi
if [ "$OPT" == "--version" ] && [ "$WORD" == "-v" ]; then
MATCH=1
break
fi
if [ "$OPT" == "-q" ] && [ "$WORD" == "--nologo" ]; then
MATCH=1
break
fi
if [ "$OPT" == "--nologo" ] && [ "$WORD" == "-q" ]; then
MATCH=1
break
fi
done done
(($MATCH == 1)) && continue
pruned="$pruned $WORD"
# COMPREPLY=($(compgen -W "${pruned}" -- ${cur})) done
echo $pruned
return 0 # COMPREPLY=($(compgen -W "${pruned}" -- ${cur}))
echo $pruned
return 0
} }
_vboxmanage() { _vboxmanage() {
# vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | sort | uniq # vboxmanage | grep -i vboxmanage | cut -d' ' -f2 | sort | uniq
local cur p1 p2 p3 p4 opts local cur p1 p2 p3 p4 opts
COMPREPLY=() COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}" prev="${COMP_WORDS[COMP_CWORD - 1]}"
# echo "cur: |$cur|" # echo "cur: |$cur|"
# echo "prev: |$prev|" # echo "prev: |$prev|"
# In case current is complete command # In case current is complete command
case $cur in case $cur in
startvm|list|controlvm) startvm | list | controlvm)
COMPREPLY=($(compgen -W "$cur ")) COMPREPLY=($(compgen -W "$cur "))
return 0 return 0
;; ;;
esac esac
case $prev in case $prev in
-v|--version) -v | --version)
return 0 return 0
;; ;;
-l|--long) -l | --long)
opts=$(__vboxmanage_list "long") opts=$(__vboxmanage_list "long")
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
startvm|list) startvm | list)
opts=$(__vboxmanage_$prev) opts=$(__vboxmanage_$prev)
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
--type) --type)
COMPREPLY=($(compgen -W "gui headless" -- ${cur})) COMPREPLY=($(compgen -W "gui headless" -- ${cur}))
return 0 return 0
;; ;;
gui|headless) gui | headless)
# Done. no more completion possible # Done. no more completion possible
return 0 return 0
;; ;;
vboxmanage|-q|--nologo) vboxmanage | -q | --nologo)
# echo "Got vboxmanage" # echo "Got vboxmanage"
opts=$(__vboxmanage_default) opts=$(__vboxmanage_default)
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
controlvm) controlvm)
opts=$(__vboxmanage_list_vms) opts=$(__vboxmanage_list_vms)
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
esac esac
for VM in $(__vboxmanage_list_vms); do for VM in $(__vboxmanage_list_vms); do
if [ "$VM" == "$prev" ]; then if [ "$VM" == "$prev" ]; then
pprev=${COMP_WORDS[COMP_CWORD-2]} pprev=${COMP_WORDS[COMP_CWORD - 2]}
# echo "previous: $pprev" # echo "previous: $pprev"
case $pprev in case $pprev in
startvm) startvm)
opts="--type" opts="--type"
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0 return 0
;; ;;
controlvm) controlvm)
opts=$(__vboxmanage_controlvm) opts=$(__vboxmanage_controlvm)
COMPREPLY=($(compgen -W "${opts}" -- ${cur})) COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0; return 0
;; ;;
esac esac
fi fi
done done
# echo "Got to end withoug completion" # echo "Got to end withoug completion"
} }
complete -F _vboxmanage vboxmanage complete -F _vboxmanage vboxmanage

View File

@ -19,9 +19,11 @@ function _command_exists ()
{ {
_about 'checks for existence of a command' _about 'checks for existence of a command'
_param '1: command to check' _param '1: command to check'
_param '2: (optional) log message to include when command not found'
_example '$ _command_exists ls && echo exists' _example '$ _command_exists ls && echo exists'
_group 'lib' _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() { function _make_reload_alias() {
@ -43,7 +45,7 @@ alias reload_plugins="$(_make_reload_alias plugin plugins)"
bash-it () bash-it ()
{ {
about 'Bash-it help and maintenance' 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 '2: component type [one of: alias(es) | completion(s) | plugin(s) ] or search term(s)'
param '3: specific component [optional]' param '3: specific component [optional]'
example '$ bash-it show plugins' 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 search [-|@]term1 [-|@]term2 ... [ -e/--enable ] [ -d/--disable ] [ -r/--refresh ] [ -c/--no-color ]'
example '$ bash-it version' example '$ bash-it version'
example '$ bash-it reload' example '$ bash-it reload'
example '$ bash-it restart'
example '$ bash-it doctor errors|warnings|all'
typeset verb=${1:-} typeset verb=${1:-}
shift shift
typeset component=${1:-} typeset component=${1:-}
@ -70,15 +74,19 @@ bash-it ()
func=_disable-$component;; func=_disable-$component;;
help) help)
func=_help-$component;; func=_help-$component;;
doctor)
func=_bash-it-doctor-$component;;
search) search)
_bash-it-search $component "$@" _bash-it-search $component "$@"
return;; return;;
update) update)
func=_bash-it_update;; func=_bash-it_update-$component;;
migrate) migrate)
func=_bash-it-migrate;; func=_bash-it-migrate;;
version) version)
func=_bash-it-version;; func=_bash-it-version;;
restart)
func=_bash-it-restart;;
reload) reload)
func=_bash-it-reload;; func=_bash-it-reload;;
*) *)
@ -109,6 +117,10 @@ bash-it ()
do do
$func $arg $func $arg
done done
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
_bash-it-reload
fi
else else
$func "$@" $func "$@"
fi fi
@ -146,60 +158,127 @@ _bash-it-plugins ()
_bash-it-describe "plugins" "a" "plugin" "Plugin" _bash-it-describe "plugins" "a" "plugin" "Plugin"
} }
_bash-it_update() { _bash-it_update-dev() {
_about 'updates Bash-it' _about 'updates Bash-it to the latest master'
_group 'lib' _group 'lib'
_bash-it_update- dev "$@"
}
_bash-it_update-stable() {
_about 'updates Bash-it to the latest tag'
_group 'lib'
_bash-it_update- stable "$@"
}
_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 $2 version now..."
_bash-it-migrate
echo ""
echo "All done, enjoy!"
bash-it reload
else
echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean."
fi
}
_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}" local old_pwd="${PWD}"
cd "${BASH_IT}" || return cd "${BASH_IT}" || return
if [ -z $BASH_IT_REMOTE ]; then if [ -z "$BASH_IT_REMOTE" ]; then
BASH_IT_REMOTE="origin" BASH_IT_REMOTE="origin"
fi fi
git fetch &> /dev/null 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 declare status
status="$(git rev-list master..${BASH_IT_REMOTE}/master 2> /dev/null)" 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 [[ -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 master..${BASH_IT_REMOTE}); do for i in $(git rev-list --merges --first-parent ${revision}); do
num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l) num_of_lines=$(git log -1 --format=%B $i | awk 'NF' | wc -l)
if [ $num_of_lines -eq 1 ]; then if [ $num_of_lines -eq 1 ]; then
description="%s" description="%s"
else else
description="%b" description="%b"
fi fi
git log --format="%h: $description (%an)" -1 $i git log --format="${log_color}%h: $description (%an)" -1 $i
done done
echo "" 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 if [[ $silent ]]; then
[yY]|"") echo "Updating to ${TARGET}($(git log -1 --format=%h "${TARGET}"))..."
git pull --rebase &> /dev/null _bash-it_pull_and_update_inner $TARGET $version
if [[ $? -eq 0 ]]; then else
echo "Bash-it successfully updated." read -e -n 1 -p "Would you like to update to ${TARGET}($(git log -1 --format=%h "${TARGET}"))? [Y/n] " RESP
echo "" case $RESP in
echo "Migrating your installation to the latest version now..." [yY]|"")
_bash-it-migrate _bash-it_pull_and_update_inner $TARGET $version
echo "" ;;
echo "All done, enjoy!" [nN])
bash-it reload echo "Not updating…"
else ;;
echo "Error updating Bash-it, please, check if your Bash-it installation folder (${BASH_IT}) is clean." *)
fi echo -e "\033[91mPlease choose y or n.\033[m"
;; ;;
[nN]) esac
echo "Not upgrading…" fi
;;
*)
echo -e "\033[91mPlease choose y or n.\033[m"
;;
esac
else else
echo "Bash-it is up to date, nothing to do!" 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 fi
cd "${old_pwd}" &> /dev/null || return cd "${old_pwd}" &> /dev/null || return
} }
@ -234,6 +313,10 @@ _bash-it-migrate() {
done done
done done
if [ -n "$BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE" ]; then
_bash-it-reload
fi
if [ "$migrated_something" = "true" ]; then if [ "$migrated_something" = "true" ]; then
echo "" echo ""
echo "If any migration errors were reported, please try the following: reload && bash-it migrate" 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 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() { _bash-it-reload() {
_about 'reloads a profile file' _about 'reloads a profile file'
_group 'lib' _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" 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 () _disable-plugin ()
{ {
_about 'disables bash_it plugin' _about 'disables bash_it plugin'
@ -326,6 +475,7 @@ _disable-plugin ()
_group 'lib' _group 'lib'
_disable-thing "plugins" "plugin" $1 _disable-thing "plugins" "plugin" $1
_on-disable-callback $1
} }
_disable-alias () _disable-alias ()
@ -400,10 +550,6 @@ _disable-thing ()
_bash-it-clean-component-cache "${file_type}" _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." printf '%s\n' "$file_entity disabled."
} }
@ -500,10 +646,6 @@ _enable-thing ()
_bash-it-clean-component-cache "${file_type}" _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." 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 # 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 # 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 # as the first argument to the function. This function exits as soon as
# a match is found. # a match is found.

View File

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

View File

@ -40,7 +40,8 @@ function __awskeys_help {
function __awskeys_get { function __awskeys_get {
local ln=$(grep -n "\[ *$1 *\]" "${AWS_SHARED_CREDENTIALS_FILE}" | cut -d ":" -f 1) local ln=$(grep -n "\[ *$1 *\]" "${AWS_SHARED_CREDENTIALS_FILE}" | cut -d ":" -f 1)
if [[ -n "${ln}" ]]; then 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 fi
} }

View File

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

View File

@ -29,12 +29,28 @@ End-Of-Usage
[ $# -eq 0 ] && extract -h && return 1 [ $# -eq 0 ] && extract -h && return 1
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
if [ -f "$1" ]; then if [[ ! -f "$1" ]]; then
case "$1" in echo "extract: '$1' is not a valid file" >&2
*.tar.bz2|*.tbz|*.tbz2) tar "x${verbose}jf" "$1" ;; shift
*.tar.gz|*.tgz) tar "x${verbose}zf" "$1" ;; continue
*.tar.xz) xz --decompress "$1"; set -- "$@" "${1:0:-3}" ;; fi
*.tar.Z) uncompress "$1"; set -- "$@" "${1:0:-2}" ;;
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" -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" ;; *.bz2) bunzip2 "$1" ;;
*.deb) dpkg-deb -x${verbose} "$1" "${1:0:-4}" ;; *.deb) dpkg-deb -x${verbose} "$1" "${1:0:-4}" ;;
*.pax.gz) gunzip "$1"; set -- "$@" "${1:0:-3}" ;; *.pax.gz) gunzip "$1"; set -- "$@" "${1:0:-3}" ;;
@ -43,17 +59,15 @@ End-Of-Usage
*.pkg) pkgutil --expand "$1" "${1:0:-4}" ;; *.pkg) pkgutil --expand "$1" "${1:0:-4}" ;;
*.rar) unrar x "$1" ;; *.rar) unrar x "$1" ;;
*.rpm) rpm2cpio "$1" | cpio -idm${verbose} ;; *.rpm) rpm2cpio "$1" | cpio -idm${verbose} ;;
*.tar) tar "x${verbose}f" "$1" ;; *.tar) tar "x${verbose}f" "$1" -C "$filedirname/$targetdirname" ;;
*.txz) mv "$1" "${1:0:-4}.tar.xz"; set -- "$@" "${1:0:-4}.tar.xz" ;;
*.xz) xz --decompress "$1" ;; *.xz) xz --decompress "$1" ;;
*.zip|*.war|*.jar) unzip "$1" ;; *.zip|*.war|*.jar) unzip "$1" ;;
*.Z) uncompress "$1" ;; *.Z) uncompress "$1" ;;
*.7z) 7za x "$1" ;; *.7z) 7za x "$1" ;;
*) echo "'$1' cannot be extracted via extract" >&2;; *) echo "'$1' cannot be extracted via extract" >&2;;
esac esac
else fi
echo "extract: '$1' is not a valid file" >&2
fi
shift shift
done 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 cite about-plugin
about-plugin 'load fzf, if you are using it' 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 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 source "${XDG_CONFIG_HOME:-$HOME/.config}"/fzf/fzf.bash
fi fi
if [ -z ${FZF_DEFAULT_COMMAND+x} ]; then if [ -z ${FZF_DEFAULT_COMMAND+x} ] && _command_exists fd ; then
command -v fd &> /dev/null && export FZF_DEFAULT_COMMAND='fd --type f' export FZF_DEFAULT_COMMAND='fd --type f'
fi fi
fe() { 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 if [[ "$use_gifski" = "true" ]] ; then
# I trust @pornel to do his own resizing optimization choices # I trust @pornel to do his own resizing optimization choices
$ffmpeg -loglevel panic -i "$file" -r $fps -vcodec png v2gif-tmp-%05d.png && \ $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 else
$ffmpeg -loglevel panic -i "$file" $maxsize -r $fps -vcodec png v2gif-tmp-%05d.png && \ $ffmpeg -loglevel panic -i "$file" $maxsize -r $fps -vcodec png v2gif-tmp-%05d.png && \
$convert +dither -layers Optimize v2gif-tmp-*.png GIF:- | \ $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 cite about-plugin
about-plugin 'load jenv, if you are using it' about-plugin 'load jenv, if you are using it'
export JENV_ROOT="$HOME/.jenv" # Don't modify the environment if we can't find the tool:
pathmunge "$JENV_ROOT/bin" # - 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 cite about-plugin
about-plugin 'Node.js helper functions' about-plugin 'Node.js helper functions'
# Ensure local modules are preferred in PATH
pathmunge "./node_modules/.bin" "after" pathmunge "./node_modules/.bin" "after"
# Make sure the global npm prefix is on the path # Check that we have npm
[[ `which npm 2>/dev/null` ]] && pathmunge "$(npm config get prefix)/bin" "after" 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 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 { function pj {
about 'navigate quickly to your various project directories' about 'navigate quickly to your various project directories'

View File

@ -94,7 +94,6 @@ function _ensure_valid_sshagent_env() {
return return
fi fi
echo "There's a dead ssh-agent at the landing..."
ssh-agent > "${SSH_AGENT_ENV}" ssh-agent > "${SSH_AGENT_ENV}"
return 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 () { _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 [ "$SHORT_TERM_LINE" = true ] && [ ${#dir_name} -gt 8 ] && echo ${dir_name##*/} || echo $dir_name
} }

View File

@ -1,15 +1,26 @@
#!/bin/bash #!/bin/bash
BASH_IT_LOG_PREFIX="core: reloader: "
pushd "${BASH_IT}" >/dev/null || exit 1 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 if [ "$1" != "skip" ] && [ -d "./enabled" ]; then
_bash_it_config_type="" _bash_it_config_type=""
if [[ "${1}" =~ ^(alias|completion|plugin)$ ]]; then if [[ "${1}" =~ ^(alias|completion|plugin)$ ]]; then
_bash_it_config_type=$1 _bash_it_config_type=$1
_log_debug "Loading enabled $1 components..."
else
_log_debug "Loading all enabled components..."
fi fi
for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${_bash_it_config_type}.bash")); do for _bash_it_config_file in $(sort <(compgen -G "./enabled/*${_bash_it_config_type}.bash")); do
if [ -e "${_bash_it_config_file}" ]; then if [ -e "${_bash_it_config_file}" ]; then
_set-prefix-based-on-path "${_bash_it_config_file}"
_log_debug "Loading component..."
# shellcheck source=/dev/null # shellcheck source=/dev/null
source $_bash_it_config_file source $_bash_it_config_file
else else
@ -20,9 +31,11 @@ fi
if [ ! -z "${2}" ] && [[ "${2}" =~ ^(aliases|completion|plugins)$ ]] && [ -d "${2}/enabled" ]; then if [ ! -z "${2}" ] && [[ "${2}" =~ ^(aliases|completion|plugins)$ ]] && [ -d "${2}/enabled" ]; then
# TODO: We should warn users they're using legacy enabling _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 for _bash_it_config_file in $(sort <(compgen -G "./${2}/enabled/*.bash")); do
if [ -e "$_bash_it_config_file" ]; then if [ -e "$_bash_it_config_file" ]; then
_set-prefix-based-on-path "${_bash_it_config_file}"
_log_debug "Loading component..."
# shellcheck source=/dev/null # shellcheck source=/dev/null
source "$_bash_it_config_file" source "$_bash_it_config_file"
else 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`. # cloned bash-it with a remote other than origin such as `bash-it`.
# export BASH_IT_REMOTE='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. # Your place for hosting Git repos. I use this for private repos.
export GIT_HOSTING='git@git.domain.com' 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 # Set this to false to turn off version control status checking within the prompt for all themes
export SCM_CHECK=true 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. # Set Xterm/screen/Tmux title with only a short hostname.
# Uncomment this (or set SHORT_HOSTNAME to something else), # 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: 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 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 load ../../lib/composure
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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
# Copy the test fixture to the Bash-it folder # Copy the test fixture to the Bash-it folder
rsync -a "$BASH_IT/test/fixtures/bash_it/" "$BASH_IT/" if command -v rsync &> /dev/null
then
# Don't pollute the user's actual $HOME directory rsync -a "$BASH_IT/test/fixtures/bash_it/" "$BASH_IT/"
# Use a test home directory instead else
export BASH_IT_TEST_CURRENT_HOME="${HOME}" find "$BASH_IT/test/fixtures/bash_it" \
export BASH_IT_TEST_HOME="$(cd "${BASH_IT}/.." && pwd)/BASH_IT_TEST_HOME" -mindepth 1 -maxdepth 1 \
mkdir -p "${BASH_IT_TEST_HOME}" -exec cp -r {} "$BASH_IT/" \;
export HOME="${BASH_IT_TEST_HOME}" fi
}
function local_teardown {
export HOME="${BASH_IT_TEST_CURRENT_HOME}"
rm -rf "${BASH_IT_TEST_HOME}"
assert_equal "${BASH_IT_TEST_CURRENT_HOME}" "${HOME}"
} }
@test "bash-it: verify that the test fixture is available" { @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 load ../../completion/available/bash-it.completion
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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}"
} }
@test "completion bash-it: ensure that the _bash-it-comp function is available" { @test "completion bash-it: ensure that the _bash-it-comp function is available" {
@ -72,6 +43,11 @@ function __check_completion () {
echo "${COMPREPLY[@]}" 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" { @test "completion bash-it: help - show options" {
run __check_completion 'bash-it help ' run __check_completion 'bash-it help '
assert_line -n 0 "aliases completions migrate plugins update" assert_line -n 0 "aliases completions migrate plugins update"
@ -82,9 +58,14 @@ function __check_completion () {
assert_line -n 0 "vagrant vault vim" 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 ' 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" { @test "completion bash-it: search - show no options" {
@ -99,32 +80,32 @@ function __check_completion () {
@test "completion bash-it: show options" { @test "completion bash-it: show options" {
run __check_completion 'bash-it ' 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" { @test "completion bash-it: bash-ti - show options" {
run __check_completion 'bash-ti ' 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" { @test "completion bash-it: shit - show options" {
run __check_completion 'shit ' 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" { @test "completion bash-it: bashit - show options" {
run __check_completion 'bashit ' 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" { @test "completion bash-it: batshit - show options" {
run __check_completion 'batshit ' 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" { @test "completion bash-it: bash_it - show options" {
run __check_completion 'bash_it ' 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" { @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 esac
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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}"
} }
@test "install: verify that the install script exists" { @test "install: verify that the install script exists" {

View File

@ -14,31 +14,7 @@ case $OSTYPE in
esac esac
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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}"
} }
@test "uninstall: verify that the uninstall script exists" { @test "uninstall: verify that the uninstall script exists" {

View File

@ -2,6 +2,7 @@
load ../test_helper load ../test_helper
load ../../lib/composure load ../../lib/composure
load ../../lib/log
load ../../lib/utilities load ../../lib/utilities
load ../../lib/search load ../../lib/search
load ../../plugins/available/base.plugin load ../../plugins/available/base.plugin
@ -11,21 +12,7 @@ cite _about _param _example _group _author _version
load ../../lib/helpers load ../../lib/helpers
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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
} }
# TODO Create global __is_enabled function # TODO Create global __is_enabled function
@ -33,7 +20,7 @@ function local_setup {
# TODO Create global __get_enabled_name function # TODO Create global __get_enabled_name function
@test "helpers: _command_exists function exists" { @test "helpers: _command_exists function exists" {
type -a _command_exists &> /dev/null run type -a _command_exists &> /dev/null
assert_success assert_success
} }
@ -141,8 +128,8 @@ function local_setup {
@test "helpers: enable the brew completion" { @test "helpers: enable the brew completion" {
run _enable-completion "brew" run _enable-completion "brew"
assert_line -n 0 'brew enabled with priority 350.' assert_line -n 0 'brew enabled with priority 375.'
assert_link_exist "$BASH_IT/enabled/350---brew.completion.bash" assert_link_exist "$BASH_IT/enabled/375---brew.completion.bash"
} }
@test "helpers: enable the node plugin" { @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 ../test_helper
load ../../lib/composure load ../../lib/composure
load ../../lib/log
load ../../lib/helpers load ../../lib/helpers
load ../../lib/utilities load ../../lib/utilities
load ../../lib/search load ../../lib/search
cite _about _param _example _group _author _version
load ../../plugins/available/base.plugin load ../../plugins/available/base.plugin
load ../../aliases/available/git.aliases load ../../aliases/available/git.aliases
load ../../plugins/available/ruby.plugin load ../../plugins/available/ruby.plugin
@ -13,27 +17,10 @@ load ../../completion/available/bundler.completion
load ../../completion/available/gem.completion load ../../completion/available/gem.completion
load ../../completion/available/rake.completion load ../../completion/available/rake.completion
cite _about _param _example _group _author _version
load ../../lib/helpers load ../../lib/helpers
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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
export OLD_PATH="$PATH" export OLD_PATH="$PATH"
export PATH="/usr/bin:/bin:/usr/sbin" export PATH="/usr/bin:/bin:/usr/sbin"
@ -53,8 +40,13 @@ function local_teardown {
@test "search: git" { @test "search: git" {
run _bash-it-search 'git' --no-color run _bash-it-search 'git' --no-color
assert_line -n 0 ' aliases: git gitsvn ' assert_line -n 0 ' aliases: git gitsvn '
assert_line -n 1 ' plugins: autojump git git-subrepo jgitflow jump ' assert_line -n 1 -p ' plugins:'
assert_line -n 2 ' completions: git git_flow git_flow_avh ' 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" { @test "search: ruby gem bundle rake rails" {

View File

@ -9,22 +9,7 @@ load ../../lib/search
cite _about _param _example _group _author _version cite _about _param _example _group _author _version
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
lib_directory="$(cd "$(dirname "$0")" && pwd)"
# Use rsync to copy Bash-it to the temp folder
# rsync is faster than cp, since we can exclude the large ".git" folder
rsync -qavrKL -d --delete-excluded --exclude=.git $lib_directory/../../.. "$BASH_IT"
rm -rf "$BASH_IT"/enabled
rm -rf "$BASH_IT"/aliases/enabled
rm -rf "$BASH_IT"/completion/enabled
rm -rf "$BASH_IT"/plugins/enabled
rm -rf "$BASH_IT"/tmp/cache
mkdir -p "$BASH_IT"/enabled
mkdir -p "$BASH_IT"/aliases/enabled
mkdir -p "$BASH_IT"/completion/enabled
mkdir -p "$BASH_IT"/plugins/enabled
} }
function has_match() { 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()' { @test 'plugins base: myip()' {
if [[ ! $SLOW_TESTS ]]; then
skip 'myip is slow - run only with SLOW_TESTS=true'
fi
run myip run myip
assert_success assert_success
declare -r mask_ip=$(echo $output | tr -s '[0-9]' '?') declare -r mask_ip=$(echo $output | tr -s '[0-9]' '?')
@ -43,7 +39,7 @@ load ../../plugins/available/base.plugin
mkcd "${dir_name}" mkcd "${dir_name}"
assert_success 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}" assert_equal $(pwd) "${BASH_IT_ROOT}/${dir_name}"
} }

View File

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

View File

@ -6,21 +6,7 @@ load ../../lib/composure
load ../../plugins/available/ruby.plugin load ../../plugins/available/ruby.plugin
function local_setup { function local_setup {
mkdir -p "$BASH_IT" setup_test_fixture
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
export OLD_PATH="$PATH" export OLD_PATH="$PATH"
export PATH="/usr/bin:/bin:/usr/sbin" export PATH="/usr/bin:/bin:/usr/sbin"

View File

@ -16,4 +16,33 @@ else
test_dirs=( "$1" ) test_dirs=( "$1" )
fi 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 SCM_CHECK
unset BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE 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_MAIN_DIR="${BATS_TEST_DIRNAME}/.."
export TEST_DEPS_DIR="${TEST_DEPS_DIR-${TEST_MAIN_DIR}/../test_lib}" 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-support/load.bash"
load "${TEST_DEPS_DIR}/bats-assert/load.bash" load "${TEST_DEPS_DIR}/bats-assert/load.bash"
load "${TEST_DEPS_DIR}/bats-file/load.bash" load "${TEST_DEPS_DIR}/bats-file/load.bash"
@ -29,9 +24,70 @@ local_teardown() {
true 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() { 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}" 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 local_setup
} }
@ -39,49 +95,5 @@ teardown() {
local_teardown local_teardown
rm -rf "${BASH_IT_TEST_DIR}" rm -rf "${BASH_IT_TEST_DIR}"
} temp_del "${TEST_TEMP_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
} }

View File

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

View File

@ -2,6 +2,7 @@
load ../test_helper load ../test_helper
load ../../lib/composure load ../../lib/composure
load ../../lib/log
cite _about _param _example _group _author _version 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() { ____atomic_top_left_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) args=($1)
IFS="${ifs_old}" IFS="${ifs_old}"
if [ -n "${args[3]}" ]; then if [ -n "${args[3]}" ]; then
_TOP_LEFT+="${args[2]}${args[3]}" _TOP_LEFT+="${args[2]}${args[3]}"
@ -45,7 +45,7 @@ ____atomic_top_left_parse() {
____atomic_top_right_parse() { ____atomic_top_right_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) args=($1)
IFS="${ifs_old}" IFS="${ifs_old}"
_TOP_RIGHT+=" " _TOP_RIGHT+=" "
if [ -n "${args[3]}" ]; then if [ -n "${args[3]}" ]; then
@ -55,14 +55,14 @@ ____atomic_top_right_parse() {
if [ -n "${args[4]}" ]; then if [ -n "${args[4]}" ]; then
_TOP_RIGHT+="${args[2]}${args[4]}" _TOP_RIGHT+="${args[2]}${args[4]}"
fi fi
__TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1 )) __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN + ${#args[1]} + ${#args[3]} + ${#args[4]} + 1))
(( __SEG_AT_RIGHT += 1 )) ((__SEG_AT_RIGHT += 1))
} }
____atomic_bottom_parse() { ____atomic_bottom_parse() {
ifs_old="${IFS}" ifs_old="${IFS}"
IFS="|" IFS="|"
args=( $1 ) args=($1)
IFS="${ifs_old}" IFS="${ifs_old}"
_BOTTOM+="${args[0]}${args[1]}" _BOTTOM+="${args[0]}${args[1]}"
[ ${#args[1]} -gt 0 ] && _BOTTOM+=" " [ ${#args[1]} -gt 0 ] && _BOTTOM+=" "
@ -87,7 +87,7 @@ ____atomic_top() {
[ -n "${info}" ] && ____atomic_top_right_parse "${info}" [ -n "${info}" ] && ____atomic_top_right_parse "${info}"
done done
[ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$(( __TOP_RIGHT_LEN - 0 )) [ $__TOP_RIGHT_LEN -gt 0 ] && __TOP_RIGHT_LEN=$((__TOP_RIGHT_LEN - 0))
___cursor_adjust="\e[${__TOP_RIGHT_LEN}D" ___cursor_adjust="\e[${__TOP_RIGHT_LEN}D"
_TOP_LEFT+="${___cursor_adjust}" _TOP_LEFT+="${___cursor_adjust}"
@ -148,10 +148,10 @@ ___atomic_prompt_ruby() {
___atomic_prompt_todo() { ___atomic_prompt_todo() {
[ "${THEME_SHOW_TODO}" != "true" ] || [ "${THEME_SHOW_TODO}" != "true" ] ||
[ -z "$(which todo.sh)" ] && return [ -z "$(which todo.sh)" ] && return
color=$bold_white color=$bold_white
box="[|]" box="[|]"
info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }' )" info="t:$(todo.sh ls | egrep "TODO: [0-9]+ of ([0-9]+)" | awk '{ print $4 }')"
printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}" printf "%s|%s|%s|%s" "${color}" "${info}" "${bold_green}" "${box}"
} }
@ -165,15 +165,15 @@ ___atomic_prompt_clock() {
___atomic_prompt_battery() { ___atomic_prompt_battery() {
! _command_exists battery_percentage || ! _command_exists battery_percentage ||
[ "${THEME_SHOW_BATTERY}" != "true" ] || [ "${THEME_SHOW_BATTERY}" != "true" ] ||
[ "$(battery_percentage)" = "no" ] && return [ "$(battery_percentage)" = "no" ] && return
batp=$(battery_percentage) batp=$(battery_percentage)
if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then if [ "$batp" -eq 50 ] || [ "$batp" -gt 50 ]; then
color=$bold_green color=$bold_green
elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then elif [ "$batp" -lt 50 ] && [ "$batp" -gt 25 ]; then
color=$bold_yellow color=$bold_yellow
elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then elif [ "$batp" -eq 25 ] || [ "$batp" -lt 25 ]; then
color=$IRed color=$IRed
fi fi
box="[|]" box="[|]"
@ -194,7 +194,7 @@ ___atomic_prompt_char() {
color=$white color=$white
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}" prompt_char="${__ATOMIC_PROMPT_CHAR_PS1}"
if [ "${THEME_SHOW_SUDO}" == "true" ]; then if [ "${THEME_SHOW_SUDO}" == "true" ]; then
if [ $(sudo -n id -u 2>&1 | grep 0) ]; then if sudo -vn 1>/dev/null 2>&1; then
prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}" prompt_char="${__ATOMIC_PROMPT_CHAR_PS1_SUDO}"
fi fi
fi fi
@ -226,16 +226,16 @@ _atomic_completion() {
segments="battery clock exitcode python ruby scm sudo todo" segments="battery clock exitcode python ruby scm sudo todo"
case "${_action}" in case "${_action}" in
show) show)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) COMPREPLY=($(compgen -W "${segments}" -- "${cur}"))
return 0 return 0
;; ;;
hide) hide)
COMPREPLY=( $(compgen -W "${segments}" -- "${cur}") ) COMPREPLY=($(compgen -W "${segments}" -- "${cur}"))
return 0 return 0
;; ;;
esac esac
COMPREPLY=( $(compgen -W "${actions}" -- "${cur}") ) COMPREPLY=($(compgen -W "${actions}" -- "${cur}"))
return 0 return 0
} }
@ -246,9 +246,11 @@ atomic() {
typeset func typeset func
case $action in case $action in
show) show)
func=__atomic_show;; func=__atomic_show
;;
hide) hide)
func=__atomic_hide;; func=__atomic_hide
;;
esac esac
for seg in ${segs}; do for seg in ${segs}; do
seg=$(printf "%s" "${seg}" | tr '[:lower:]' '[:upper:]') 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 path (red when user is root)
* Current git info * Current git info
* Last command exit code (only shown when the exit code is greater than 0) * 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 ## Examples
@ -21,4 +90,10 @@ A minimal theme with a clean git prompt
```bash ```bash
 ~/.dotfiles on  master ⤏ origin ↑2 •7 ✗  ~/.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 #!/usr/bin/env bash
# shellcheck disable=2034,2154 # shellcheck disable=2034,2154
SCM_GIT_CHAR_GITLAB=' ' # Theme custom glyphs
SCM_GIT_CHAR_BITBUCKET=' ' SCM_GIT_CHAR_GITLAB=${BARBUK_GITLAB_CHAR:=' '}
SCM_GIT_CHAR_GITHUB=' ' SCM_GIT_CHAR_BITBUCKET=${BARBUK_BITBUCKET_CHAR:=' '}
SCM_GIT_CHAR_DEFAULT=' ' SCM_GIT_CHAR_GITHUB=${BARBUK_GITHUB_CHAR:=' '}
SCM_GIT_CHAR_ICON_BRANCH='' SCM_GIT_CHAR_DEFAULT=${BARBUK_GIT_DEFAULT_CHAR:=' '}
SCM_HG_CHAR='☿ ' SCM_GIT_CHAR_ICON_BRANCH=${BARBUK_GIT_BRANCH_ICON:=''}
SCM_SVN_CHAR='⑆ ' 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_NONE_CHAR=
SCM_THEME_PROMPT_DIRTY=" ${bold_red}" SCM_THEME_PROMPT_DIRTY=" ${bold_red}"
SCM_THEME_PROMPT_CLEAN=" ${bold_green}" SCM_THEME_PROMPT_CLEAN=" ${bold_green}"
@ -25,10 +33,9 @@ GIT_THEME_PROMPT_SUFFIX="${cyan}"
SCM_THEME_BRANCH_TRACK_PREFIX="${normal}${cyan}" SCM_THEME_BRANCH_TRACK_PREFIX="${normal}${cyan}"
SCM_THEME_CURRENT_USER_PREFFIX='  ' SCM_THEME_CURRENT_USER_PREFFIX='  '
SCM_GIT_SHOW_CURRENT_USER=false SCM_GIT_SHOW_CURRENT_USER=false
EXIT_CODE_ICON=' '
function _git-uptream-remote-logo { function _git-uptream-remote-logo {
[[ "$(_git-upstream)" == "" ]] && return [[ "$(_git-upstream)" == "" ]] && SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT"
local remote remote_domain local remote remote_domain
remote=$(_git-upstream-remote) remote=$(_git-upstream-remote)
@ -59,7 +66,7 @@ function _exit-code {
} }
function _prompt { 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 _exit-code exit_code
_git-uptream-remote-logo _git-uptream-remote-logo
@ -71,7 +78,24 @@ function _prompt {
dir_color=$red dir_color=$red
fi 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} -gt $((COLUMNS*3)) ]] && wrap_char="\\n"
PS1="${PS1}${wrap_char}${normal} " 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_MINIMAL_INFO=${SCM_GIT_SHOW_MINIMAL_INFO:=false}
SCM_GIT_SHOW_STASH_INFO=${SCM_GIT_SHOW_STASH_INFO:=true} SCM_GIT_SHOW_STASH_INFO=${SCM_GIT_SHOW_STASH_INFO:=true}
SCM_GIT_SHOW_COMMIT_COUNT=${SCM_GIT_SHOW_COMMIT_COUNT:=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='git'
SCM_GIT_CHAR='±' 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_PREFIX=''
USER_HOST_THEME_PROMPT_SUFFIX='' USER_HOST_THEME_PROMPT_SUFFIX=''
VIRTUAL_ENV=
VIRTUALENV_THEME_PROMPT_PREFIX=' |' VIRTUALENV_THEME_PROMPT_PREFIX=' |'
VIRTUALENV_THEME_PROMPT_SUFFIX='|' VIRTUALENV_THEME_PROMPT_SUFFIX='|'
@ -85,10 +85,19 @@ RBENV_THEME_PROMPT_SUFFIX='|'
RBFU_THEME_PROMPT_PREFIX=' |' RBFU_THEME_PROMPT_PREFIX=' |'
RBFU_THEME_PROMPT_SUFFIX='|' RBFU_THEME_PROMPT_SUFFIX='|'
GIT_EXE=`which git 2> /dev/null || true` GIT_EXE=$(which git 2> /dev/null || true)
P4_EXE=`which p4 2> /dev/null || true` P4_EXE=$(which p4 2> /dev/null || true)
HG_EXE=`which hg 2> /dev/null || true` HG_EXE=$(which hg 2> /dev/null || true)
SVN_EXE=`which svn 2> /dev/null || true` SVN_EXE=$(which svn 2> /dev/null || true)
# Check for broken SVN exe that is caused by some versions of Xcode.
# 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 { function scm {
if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE
@ -184,6 +193,12 @@ function git_prompt_minimal_info {
} }
function git_prompt_vars { function git_prompt_vars {
if ${SCM_GIT_USE_GITSTATUS} && _command_exists gitstatus_query && gitstatus_query && [[ "${VCS_STATUS_RESULT}" == "ok-sync" ]]; then # use faster gitstatus
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 if _git-branch &> /dev/null; then
SCM_GIT_DETACHED="false" SCM_GIT_DETACHED="false"
SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)" SCM_BRANCH="${SCM_THEME_BRANCH_PREFIX}\$(_git-friendly-ref)$(_git-remote-info)"
@ -199,7 +214,12 @@ function git_prompt_vars {
SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)" SCM_BRANCH="${detached_prefix}\$(_git-friendly-ref)"
fi fi
IFS=$'\t' read -r commits_behind commits_ahead <<< "$(_git-upstream-behind-ahead)" 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 if [[ "${commits_ahead}" -gt 0 ]]; then
SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}" SCM_BRANCH+="${SCM_GIT_AHEAD_BEHIND_PREFIX_CHAR}${SCM_GIT_AHEAD_CHAR}"
[[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}" [[ "${SCM_GIT_SHOW_COMMIT_COUNT}" = "true" ]] && SCM_BRANCH+="${commits_ahead}"
@ -211,13 +231,23 @@ function git_prompt_vars {
if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then if [[ "${SCM_GIT_SHOW_STASH_INFO}" = "true" ]]; then
local stash_count local stash_count
stash_count="$(git stash list 2> /dev/null | wc -l | tr -d ' ')" 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}" [[ "${stash_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_GIT_STASH_CHAR_PREFIX}${stash_count}${SCM_GIT_STASH_CHAR_SUFFIX}"
fi fi
SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN} SCM_STATE=${GIT_THEME_PROMPT_CLEAN:-$SCM_THEME_PROMPT_CLEAN}
if ! _git-hide-status; then if ! _git-hide-status; then
IFS=$'\t' read -r untracked_count unstaged_count staged_count <<< "$(_git-status-counts)" 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 if [[ "${untracked_count}" -gt 0 || "${unstaged_count}" -gt 0 || "${staged_count}" -gt 0 ]]; then
SCM_DIRTY=1 SCM_DIRTY=1
if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then if [[ "${SCM_GIT_SHOW_DETAILS}" = "true" ]]; then
@ -229,6 +259,7 @@ function git_prompt_vars {
fi fi
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_GIT_SHOW_CURRENT_USER}" == "true" ]] && SCM_BRANCH+="$(git_user_info)"
SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} SCM_PREFIX=${GIT_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX}
@ -313,7 +344,7 @@ function hg_prompt_vars {
if [ -f "$HG_ROOT/dirstate" ]; then if [ -f "$HG_ROOT/dirstate" ]; then
# Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState # Mercurial holds various information about the working directory in .hg/dirstate file. More on http://mercurial.selenic.com/wiki/DirState
SCM_CHANGE=$(hexdump -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 else
SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}') SCM_CHANGE=$(hg summary 2> /dev/null | grep parent: | awk '{print $2}')
fi fi

View File

@ -12,8 +12,13 @@ GIT_THEME_PROMPT_SUFFIX="${green}|"
CONDAENV_THEME_PROMPT_SUFFIX="|" CONDAENV_THEME_PROMPT_SUFFIX="|"
function prompt_command() { 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) " # Name of virtual env followed by python version
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+="${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 safe_append_prompt_command prompt_command

View File

@ -22,8 +22,13 @@ __bobby_clock() {
} }
function prompt_command() { 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)"
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+="${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"} THEME_SHOW_CLOCK_CHAR=${THEME_SHOW_CLOCK_CHAR:-"true"}

View File

@ -90,7 +90,7 @@ ____brainy_bottom() {
___brainy_prompt_user_info() { ___brainy_prompt_user_info() {
color=$bold_blue color=$bold_blue
if [ "${THEME_SHOW_SUDO}" == "true" ]; then 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 color=$bold_red
fi fi
fi fi

View File

@ -109,7 +109,7 @@ function __color_white {
function __color_rgb { function __color_rgb {
r=$1 && g=$2 && b=$3 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 ))" echo "8;5;$(( ($r * 36 + $b * 6 + $g) / 51 + 16 ))"
} }

View File

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

View File

@ -1,37 +1,35 @@
# git branch parser # git branch parser
function parse_git_branch() { 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() { 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() { function prompt() {
# If not running interactively, don't do anything # If not running interactively, don't do anything
[[ $- != *i* ]] && return [[ $- != *i* ]] && return
local force_color_prompt=yes local force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
local color_prompt=yes
else
local color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]$(parse_git_branch) $\[\e[0m\] "
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
local color_prompt=yes
else else
PS1='┌──[\u@\h]─[\w]\n└──╼ $(parse_git_branch_no_color) $ ' local color_prompt=
fi fi
fi
if [ "$color_prompt" = yes ]; then
PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]$(parse_git_branch) $\[\e[0m\] "
else
PS1='┌──[\u@\h]─[\w]\n└──╼ $(parse_git_branch_no_color) $ '
fi
} }
safe_append_prompt_command prompt safe_append_prompt_command 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_AFTER_LAST_SEGMENT | Removes the trailing space on the last segment
|POWERLINE_COMPACT_PROMPT | Removes the space after the prompt character |POWERLINE_COMPACT_PROMPT | Removes the space after the prompt character
|POWERLINE_COMPACT | Enable all Compact settings (you can still override individual settings) |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. 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="" LEFT_PROMPT=""
SEGMENTS_AT_LEFT=0 SEGMENTS_AT_LEFT=0
LAST_SEGMENT_COLOR="" LAST_SEGMENT_COLOR=""
PROMPT_AFTER="${POWERLINE_PROMPT_AFTER}"
_save-and-reload-history "${HISTORY_AUTOSAVE:-0}" _save-and-reload-history "${HISTORY_AUTOSAVE:-0}"
@ -51,7 +52,7 @@ function __powerline_prompt_command {
LEFT_PROMPT+=" " LEFT_PROMPT+=" "
fi fi
PS1="${LEFT_PROMPT}" PS1="${LEFT_PROMPT}${PROMPT_AFTER}"
## cleanup ## ## cleanup ##
unset LAST_SEGMENT_COLOR \ 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_BEFOR_FIRST_SEGMENT=${POWERLINE_COMPACT_BEFORE_FIRST_SEGMENT:=${POWERLINE_COMPACT}}
POWERLINE_COMPACT_AFTER_LAST_SEGMENT=${POWERLINE_COMPACT_AFTER_LAST_SEGMENT:=${POWERLINE_COMPACT}} POWERLINE_COMPACT_AFTER_LAST_SEGMENT=${POWERLINE_COMPACT_AFTER_LAST_SEGMENT:=${POWERLINE_COMPACT}}
POWERLINE_COMPACT_PROMPT=${POWERLINE_COMPACT_PROMPT:=${POWERLINE_COMPACT}} POWERLINE_COMPACT_PROMPT=${POWERLINE_COMPACT_PROMPT:=${POWERLINE_COMPACT}}
POWERLINE_PROMPT_AFTER=${POWERLINE_PROMPT_AFTER:-""}
PYTHON_VENV_CHAR=${POWERLINE_PYTHON_VENV_CHAR:="ⓔ "} PYTHON_VENV_CHAR=${POWERLINE_PYTHON_VENV_CHAR:="ⓔ "}
CONDA_PYTHON_VENV_CHAR=${POWERLINE_CONDA_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 # Define this here so it can be used by all of the Powerline themes
THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true} THEME_CHECK_SUDO=${THEME_CHECK_SUDO:=true}
function set_color { function set_color() {
set +u set +u
if [[ "${1}" != "-" ]]; then if [[ "${1}" != "-" ]]; then
fg="38;5;${1}" fg="38;5;${1}"
@ -13,14 +13,12 @@ function set_color {
echo -e "\[\033[${fg}${bg}m\]" echo -e "\[\033[${fg}${bg}m\]"
} }
function __powerline_user_info_prompt { function __powerline_user_info_prompt() {
local user_info="" local user_info=""
local color=${USER_INFO_THEME_PROMPT_COLOR} local color=${USER_INFO_THEME_PROMPT_COLOR}
if [[ "${THEME_CHECK_SUDO}" = true ]]; then if [[ "${THEME_CHECK_SUDO}" = true ]]; then
if sudo -n uptime 2>&1 | grep -q "load"; then sudo -vn 1>/dev/null 2>&1 && color=${USER_INFO_THEME_PROMPT_COLOR_SUDO}
color=${USER_INFO_THEME_PROMPT_COLOR_SUDO}
fi
fi fi
case "${POWERLINE_PROMPT_USER_INFO_MODE}" in case "${POWERLINE_PROMPT_USER_INFO_MODE}" in
@ -41,7 +39,7 @@ function __powerline_user_info_prompt {
[[ -n "${user_info}" ]] && echo "${user_info}|${color}" [[ -n "${user_info}" ]] && echo "${user_info}|${color}"
} }
function __powerline_terraform_prompt { function __powerline_terraform_prompt() {
local terraform_workspace="" local terraform_workspace=""
if [ -d .terraform ]; then if [ -d .terraform ]; then
@ -50,14 +48,14 @@ function __powerline_terraform_prompt {
fi fi
} }
function __powerline_node_prompt { function __powerline_node_prompt() {
local node_version="" local node_version=""
node_version="$(node_version_prompt)" node_version="$(node_version_prompt)"
[[ -n "${node_version}" ]] && echo "${NODE_CHAR}${node_version}|${NODE_THEME_PROMPT_COLOR}" [[ -n "${node_version}" ]] && echo "${NODE_CHAR}${node_version}|${NODE_THEME_PROMPT_COLOR}"
} }
function __powerline_ruby_prompt { function __powerline_ruby_prompt() {
local ruby_version="" local ruby_version=""
if _command_exists rvm; then 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}" [[ -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="" local kubernetes_context=""
if _command_exists kubectl; then 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}" [[ -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 set +u
local python_venv="" 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}" [[ -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 color=""
local scm_prompt="" local scm_prompt=""
@ -122,27 +120,27 @@ function __powerline_scm_prompt {
fi fi
} }
function __powerline_cwd_prompt { function __powerline_cwd_prompt() {
local cwd=$(pwd | sed "s|^${HOME}|~|") local cwd=$(pwd | sed "s|^${HOME}|~|")
echo "${cwd}|${CWD_THEME_PROMPT_COLOR}" echo "${cwd}|${CWD_THEME_PROMPT_COLOR}"
} }
function __powerline_hostname_prompt { function __powerline_hostname_prompt() {
echo "${SHORT_HOSTNAME:-$(hostname -s)}|${HOST_THEME_PROMPT_COLOR}" echo "${SHORT_HOSTNAME:-$(hostname -s)}|${HOST_THEME_PROMPT_COLOR}"
} }
function __powerline_wd_prompt { function __powerline_wd_prompt() {
echo "\W|${CWD_THEME_PROMPT_COLOR}" echo "\W|${CWD_THEME_PROMPT_COLOR}"
} }
function __powerline_clock_prompt { function __powerline_clock_prompt() {
echo "$(date +"${THEME_CLOCK_FORMAT}")|${CLOCK_THEME_PROMPT_COLOR}" echo "$(date +"${THEME_CLOCK_FORMAT}")|${CLOCK_THEME_PROMPT_COLOR}"
} }
function __powerline_battery_prompt { function __powerline_battery_prompt() {
local color="" 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 if [[ -z "${battery_status}" ]] || [[ "${battery_status}" = "-1" ]] || [[ "${battery_status}" = "no" ]]; then
true true
@ -159,29 +157,29 @@ function __powerline_battery_prompt {
fi fi
} }
function __powerline_in_vim_prompt { function __powerline_in_vim_prompt() {
if [ -n "$VIMRUNTIME" ]; then if [ -n "$VIMRUNTIME" ]; then
echo "${IN_VIM_THEME_PROMPT_TEXT}|${IN_VIM_THEME_PROMPT_COLOR}" echo "${IN_VIM_THEME_PROMPT_TEXT}|${IN_VIM_THEME_PROMPT_COLOR}"
fi fi
} }
function __powerline_aws_profile_prompt { function __powerline_aws_profile_prompt() {
if [[ -n "${AWS_PROFILE}" ]]; then if [[ -n "${AWS_PROFILE}" ]]; then
echo "${AWS_PROFILE_CHAR}${AWS_PROFILE}|${AWS_PROFILE_PROMPT_COLOR}" echo "${AWS_PROFILE_CHAR}${AWS_PROFILE}|${AWS_PROFILE_PROMPT_COLOR}"
fi fi
} }
function __powerline_shlvl_prompt { function __powerline_shlvl_prompt() {
if [[ "${SHLVL}" -gt 1 ]]; then if [[ "${SHLVL}" -gt 1 ]]; then
local prompt="${SHLVL_THEME_PROMPT_CHAR}" local prompt="${SHLVL_THEME_PROMPT_CHAR}"
local level=$(( ${SHLVL} - 1)) local level=$((${SHLVL} - 1))
echo "${prompt}${level}|${SHLVL_THEME_PROMPT_COLOR}" echo "${prompt}${level}|${SHLVL_THEME_PROMPT_COLOR}"
fi fi
} }
function __powerline_dirstack_prompt { function __powerline_dirstack_prompt() {
if [[ "${#DIRSTACK[@]}" -gt 1 ]]; then if [[ "${#DIRSTACK[@]}" -gt 1 ]]; then
local depth=$(( ${#DIRSTACK[@]} - 1 )) local depth=$((${#DIRSTACK[@]} - 1))
local prompt="${DIRSTACK_THEME_PROMPT_CHAR}" local prompt="${DIRSTACK_THEME_PROMPT_CHAR}"
if [[ "${depth}" -ge 2 ]]; then if [[ "${depth}" -ge 2 ]]; then
prompt+="${depth}" prompt+="${depth}"
@ -190,17 +188,18 @@ function __powerline_dirstack_prompt {
fi fi
} }
function __powerline_history_number_prompt { function __powerline_history_number_prompt() {
echo "${HISTORY_NUMBER_THEME_PROMPT_CHAR}\!|${HISTORY_NUMBER_THEME_PROMPT_COLOR}" 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}" echo "${COMMAND_NUMBER_THEME_PROMPT_CHAR}\#|${COMMAND_NUMBER_THEME_PROMPT_COLOR}"
} }
function __powerline_left_segment { function __powerline_left_segment() {
local OLD_IFS="${IFS}"; IFS="|" local OLD_IFS="${IFS}"
local params=( $1 ) IFS="|"
local params=($1)
IFS="${OLD_IFS}" IFS="${OLD_IFS}"
local pad_before_segment=" " local pad_before_segment=" "
@ -226,18 +225,18 @@ function __powerline_left_segment {
LEFT_PROMPT+="$(set_color - ${params[1]})${pad_before_segment}${params[0]}${normal}" LEFT_PROMPT+="$(set_color - ${params[1]})${pad_before_segment}${params[0]}${normal}"
LAST_SEGMENT_COLOR=${params[1]} 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}" 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}" [[ "$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 last_status="$?" ## always the first
local separator_char="${POWERLINE_PROMPT_CHAR}" local separator_char="${POWERLINE_PROMPT_CHAR}"
@ -245,9 +244,8 @@ function __powerline_prompt_command {
SEGMENTS_AT_LEFT=0 SEGMENTS_AT_LEFT=0
LAST_SEGMENT_COLOR="" LAST_SEGMENT_COLOR=""
if [[ -n "${POWERLINE_PROMPT_DISTRO_LOGO}" ]]; then if [[ -n "${POWERLINE_PROMPT_DISTRO_LOGO}" ]]; then
LEFT_PROMPT+="$(set_color ${PROMPT_DISTRO_LOGO_COLOR} ${PROMPT_DISTRO_LOGO_COLORBG})${PROMPT_DISTRO_LOGO}$(set_color - -)" LEFT_PROMPT+="$(set_color ${PROMPT_DISTRO_LOGO_COLOR} ${PROMPT_DISTRO_LOGO_COLORBG})${PROMPT_DISTRO_LOGO}$(set_color - -)"
fi fi
## left prompt ## ## left prompt ##
@ -279,6 +277,6 @@ function __powerline_prompt_command {
## cleanup ## ## cleanup ##
unset LAST_SEGMENT_COLOR \ unset LAST_SEGMENT_COLOR \
LEFT_PROMPT \ LEFT_PROMPT \
SEGMENTS_AT_LEFT SEGMENTS_AT_LEFT
} }

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