add bash-it
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
: "${CLICOLOR:=$(tput colors)}"
|
||||
export CLICOLOR
|
||||
|
||||
: "${CUSTOM_THEME_DIR:="${BASH_IT_CUSTOM:=${BASH_IT}/custom}/themes"}"
|
||||
|
||||
# Load the theme
|
||||
# shellcheck disable=SC1090
|
||||
if [[ -n "${BASH_IT_THEME:-}" ]]; then
|
||||
if [[ -f "${BASH_IT_THEME}" ]]; then
|
||||
source "${BASH_IT_THEME}"
|
||||
elif [[ -f "$CUSTOM_THEME_DIR/$BASH_IT_THEME/$BASH_IT_THEME.theme.bash" ]]; then
|
||||
source "$CUSTOM_THEME_DIR/$BASH_IT_THEME/$BASH_IT_THEME.theme.bash"
|
||||
else
|
||||
source "$BASH_IT/themes/$BASH_IT_THEME/$BASH_IT_THEME.theme.bash"
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,91 @@
|
||||
# shellcheck shell=bash
|
||||
# shellcheck disable=SC2034
|
||||
#
|
||||
# A set of pre-defined color escape codes for use in prompts and with `echo`.
|
||||
|
||||
black="\[\e[0;30m\]"
|
||||
red="\[\e[0;31m\]"
|
||||
green="\[\e[0;32m\]"
|
||||
yellow="\[\e[0;33m\]"
|
||||
blue="\[\e[0;34m\]"
|
||||
purple="\[\e[0;35m\]"
|
||||
cyan="\[\e[0;36m\]"
|
||||
white="\[\e[0;37m\]"
|
||||
orange="\[\e[0;91m\]"
|
||||
|
||||
bold_black="\[\e[30;1m\]"
|
||||
bold_red="\[\e[31;1m\]"
|
||||
bold_green="\[\e[32;1m\]"
|
||||
bold_yellow="\[\e[33;1m\]"
|
||||
bold_blue="\[\e[34;1m\]"
|
||||
bold_purple="\[\e[35;1m\]"
|
||||
bold_cyan="\[\e[36;1m\]"
|
||||
bold_white="\[\e[37;1m\]"
|
||||
bold_orange="\[\e[91;1m\]"
|
||||
|
||||
underline_black="\[\e[30;4m\]"
|
||||
underline_red="\[\e[31;4m\]"
|
||||
underline_green="\[\e[32;4m\]"
|
||||
underline_yellow="\[\e[33;4m\]"
|
||||
underline_blue="\[\e[34;4m\]"
|
||||
underline_purple="\[\e[35;4m\]"
|
||||
underline_cyan="\[\e[36;4m\]"
|
||||
underline_white="\[\e[37;4m\]"
|
||||
underline_orange="\[\e[91;4m\]"
|
||||
|
||||
background_black="\[\e[40m\]"
|
||||
background_red="\[\e[41m\]"
|
||||
background_green="\[\e[42m\]"
|
||||
background_yellow="\[\e[43m\]"
|
||||
background_blue="\[\e[44m\]"
|
||||
background_purple="\[\e[45m\]"
|
||||
background_cyan="\[\e[46m\]"
|
||||
background_white="\[\e[47;1m\]"
|
||||
background_orange="\[\e[101m\]"
|
||||
|
||||
normal="\[\e[0m\]"
|
||||
reset_color="\[\e[39m\]"
|
||||
|
||||
# These colors are meant to be used with `echo -e`
|
||||
echo_black="\033[0;30m"
|
||||
echo_red="\033[0;31m"
|
||||
echo_green="\033[0;32m"
|
||||
echo_yellow="\033[0;33m"
|
||||
echo_blue="\033[0;34m"
|
||||
echo_purple="\033[0;35m"
|
||||
echo_cyan="\033[0;36m"
|
||||
echo_white="\033[0;37;1m"
|
||||
echo_orange="\033[0;91m"
|
||||
|
||||
echo_bold_black="\033[30;1m"
|
||||
echo_bold_red="\033[31;1m"
|
||||
echo_bold_green="\033[32;1m"
|
||||
echo_bold_yellow="\033[33;1m"
|
||||
echo_bold_blue="\033[34;1m"
|
||||
echo_bold_purple="\033[35;1m"
|
||||
echo_bold_cyan="\033[36;1m"
|
||||
echo_bold_white="\033[37;1m"
|
||||
echo_bold_orange="\033[91;1m"
|
||||
|
||||
echo_underline_black="\033[30;4m"
|
||||
echo_underline_red="\033[31;4m"
|
||||
echo_underline_green="\033[32;4m"
|
||||
echo_underline_yellow="\033[33;4m"
|
||||
echo_underline_blue="\033[34;4m"
|
||||
echo_underline_purple="\033[35;4m"
|
||||
echo_underline_cyan="\033[36;4m"
|
||||
echo_underline_white="\033[37;4m"
|
||||
echo_underline_orange="\033[91;4m"
|
||||
|
||||
echo_background_black="\033[40m"
|
||||
echo_background_red="\033[41m"
|
||||
echo_background_green="\033[42m"
|
||||
echo_background_yellow="\033[43m"
|
||||
echo_background_blue="\033[44m"
|
||||
echo_background_purple="\033[45m"
|
||||
echo_background_cyan="\033[46m"
|
||||
echo_background_white="\033[47;1m"
|
||||
echo_background_orange="\033[101m"
|
||||
|
||||
echo_normal="\033[0m"
|
||||
echo_reset_color="\033[39m"
|
||||
@@ -0,0 +1,61 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# Functions for measuring and reporting how long a command takes to run.
|
||||
|
||||
: "${COMMAND_DURATION_START_SECONDS:=${EPOCHREALTIME:-$SECONDS}}"
|
||||
: "${COMMAND_DURATION_ICON:=🕘}"
|
||||
: "${COMMAND_DURATION_MIN_SECONDS:=1}"
|
||||
|
||||
function _command_duration_pre_exec() {
|
||||
COMMAND_DURATION_START_SECONDS="${EPOCHREALTIME:-$SECONDS}"
|
||||
}
|
||||
|
||||
function _dynamic_clock_icon {
|
||||
local clock_hand
|
||||
# clock hand value is between 90 and 9b in hexadecimal.
|
||||
# so between 144 and 155 in base 10.
|
||||
printf -v clock_hand '%x' $(((${1:-${SECONDS}} % 12) + 144))
|
||||
printf -v 'COMMAND_DURATION_ICON' '%b' "\xf0\x9f\x95\x$clock_hand"
|
||||
}
|
||||
|
||||
function _command_duration() {
|
||||
[[ -n "${BASH_IT_COMMAND_DURATION:-}" ]] || return
|
||||
|
||||
local command_duration=0 command_start="${COMMAND_DURATION_START_SECONDS:-0}"
|
||||
local -i minutes=0 seconds=0 deciseconds=0
|
||||
local -i command_start_seconds="${command_start%.*}"
|
||||
local -i command_start_deciseconds=$((10#${command_start##*.}))
|
||||
command_start_deciseconds="${command_start_deciseconds:0:1}"
|
||||
local current_time="${EPOCHREALTIME:-$SECONDS}"
|
||||
local -i current_time_seconds="${current_time%.*}"
|
||||
local -i current_time_deciseconds="$((10#${current_time##*.}))"
|
||||
current_time_deciseconds="${current_time_deciseconds:0:1}"
|
||||
|
||||
if [[ "${command_start_seconds:-0}" -gt 0 ]]; then
|
||||
# seconds
|
||||
command_duration="$((current_time_seconds - command_start_seconds))"
|
||||
|
||||
if ((current_time_deciseconds >= command_start_deciseconds)); then
|
||||
deciseconds="$((current_time_deciseconds - command_start_deciseconds))"
|
||||
else
|
||||
((command_duration -= 1))
|
||||
deciseconds="$((10 - (command_start_deciseconds - current_time_deciseconds)))"
|
||||
fi
|
||||
else
|
||||
command_duration=0
|
||||
fi
|
||||
|
||||
if ((command_duration > 0)); then
|
||||
minutes=$((command_duration / 60))
|
||||
seconds=$((command_duration % 60))
|
||||
fi
|
||||
|
||||
_dynamic_clock_icon "${command_duration}"
|
||||
if ((minutes > 0)); then
|
||||
printf "%s %s%dm %ds" "${COMMAND_DURATION_ICON:-}" "${COMMAND_DURATION_COLOR:-}" "$minutes" "$seconds"
|
||||
elif ((seconds >= COMMAND_DURATION_MIN_SECONDS)); then
|
||||
printf "%s %s%d.%01ds" "${COMMAND_DURATION_ICON:-}" "${COMMAND_DURATION_COLOR:-}" "$seconds" "$deciseconds"
|
||||
fi
|
||||
}
|
||||
|
||||
_bash_it_library_finalize_hook+=("safe_append_preexec '_command_duration_pre_exec'")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# Functions for working with Bash's command history.
|
||||
|
||||
function _bash-it-history-init() {
|
||||
safe_append_preexec '_bash-it-history-auto-save'
|
||||
safe_append_prompt_command '_bash-it-history-auto-load'
|
||||
}
|
||||
|
||||
function _bash-it-history-auto-save() {
|
||||
case $HISTCONTROL in
|
||||
*'noauto'* | *'autoload'*)
|
||||
: # Do nothing, as configured.
|
||||
;;
|
||||
*'auto'*)
|
||||
# Append new history from this session to the $HISTFILE
|
||||
history -a
|
||||
;;
|
||||
*)
|
||||
# Append *only* if shell option `histappend` has been enabled.
|
||||
shopt -q histappend && history -a && return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function _bash-it-history-auto-load() {
|
||||
case $HISTCONTROL in
|
||||
*'noauto'*)
|
||||
: # Do nothing, as configured.
|
||||
;;
|
||||
*'autosave'*)
|
||||
# Append new history from this session to the $HISTFILE
|
||||
history -a
|
||||
;;
|
||||
*'autoloadnew'*)
|
||||
# Read new entries from $HISTFILE
|
||||
history -n
|
||||
;;
|
||||
*'auto'*)
|
||||
# Blank in-memory history, then read entire $HISTFILE fresh from disk.
|
||||
history -a && history -c && history -r
|
||||
;;
|
||||
*)
|
||||
: # Do nothing, default.
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_bash_it_library_finalize_hook+=('_bash-it-history-init')
|
||||
@@ -0,0 +1,100 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# A collection of logging functions.
|
||||
|
||||
# Declare log severity levels, matching syslog numbering
|
||||
: "${BASH_IT_LOG_LEVEL_FATAL:=1}"
|
||||
: "${BASH_IT_LOG_LEVEL_ERROR:=3}"
|
||||
: "${BASH_IT_LOG_LEVEL_WARNING:=4}"
|
||||
: "${BASH_IT_LOG_LEVEL_ALL:=6}"
|
||||
: "${BASH_IT_LOG_LEVEL_INFO:=6}"
|
||||
: "${BASH_IT_LOG_LEVEL_TRACE:=7}"
|
||||
readonly "${!BASH_IT_LOG_LEVEL_@}"
|
||||
|
||||
function _bash-it-log-prefix-by-path() {
|
||||
local component_path="${1?${FUNCNAME[0]}: path specification required}"
|
||||
local without_extension component_directory
|
||||
local component_filename component_type component_name
|
||||
|
||||
# get the directory, if any
|
||||
component_directory="${component_path%/*}"
|
||||
# drop the directory, if any
|
||||
component_filename="${component_path##*/}"
|
||||
# strip the file extension
|
||||
without_extension="${component_filename%.bash}"
|
||||
# strip before the last dot
|
||||
component_type="${without_extension##*.}"
|
||||
# strip component type, but try not to strip other words
|
||||
# - aliases, completions, plugins, themes
|
||||
component_name="${without_extension%.[acpt][hlo][eimu]*[ens]}"
|
||||
# Finally, strip load priority prefix
|
||||
component_name="${component_name##[[:digit:]][[:digit:]][[:digit:]]"${BASH_IT_LOAD_PRIORITY_SEPARATOR:----}"}"
|
||||
|
||||
# best-guess for files without a type
|
||||
if [[ "${component_type:-${component_name}}" == "${component_name}" ]]; then
|
||||
if [[ "${component_directory}" == *'vendor'* ]]; then
|
||||
component_type='vendor'
|
||||
else
|
||||
component_type="${component_directory##*/}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
BASH_IT_LOG_PREFIX="${component_type:-lib}: $component_name"
|
||||
}
|
||||
|
||||
function _has_colors() {
|
||||
# Check that stdout is a terminal, and that it has at least 8 colors.
|
||||
[[ -t 1 && "${CLICOLOR:=$(tput colors 2> /dev/null)}" -ge 8 ]]
|
||||
}
|
||||
|
||||
function _bash-it-log-message() {
|
||||
: _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'
|
||||
|
||||
local prefix="${BASH_IT_LOG_PREFIX:-default}"
|
||||
local color="${1-${echo_cyan:-}}"
|
||||
local level="${2:-TRACE}"
|
||||
local message="${level%: }: ${prefix%: }: ${3?}"
|
||||
if _has_colors; then
|
||||
printf '%b%s%b\n' "${color}" "${message}" "${echo_normal:-}"
|
||||
else
|
||||
printf '%s\n' "${message}"
|
||||
fi
|
||||
}
|
||||
|
||||
function _log_debug() {
|
||||
: _about 'log a debug message by echoing to the screen. needs BASH_IT_LOG_LEVEL >= BASH_IT_LOG_LEVEL_INFO'
|
||||
: _param '1: message to log'
|
||||
: _example '$ _log_debug "Loading plugin git..."'
|
||||
: _group 'log'
|
||||
|
||||
if [[ "${BASH_IT_LOG_LEVEL:-0}" -ge "${BASH_IT_LOG_LEVEL_INFO?}" ]]; then
|
||||
_bash-it-log-message "${echo_green:-}" "DEBUG: " "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
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'
|
||||
|
||||
if [[ "${BASH_IT_LOG_LEVEL:-0}" -ge "${BASH_IT_LOG_LEVEL_WARNING?}" ]]; then
|
||||
_bash-it-log-message "${echo_yellow:-}" " WARN: " "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
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'
|
||||
|
||||
if [[ "${BASH_IT_LOG_LEVEL:-0}" -ge "${BASH_IT_LOG_LEVEL_ERROR?}" ]]; then
|
||||
_bash-it-log-message "${echo_red:-}" "ERROR: " "$1"
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# shellcheck shell=bash
|
||||
# shellcheck disable=SC2034
|
||||
#
|
||||
# Load the `bash-preexec.sh` library, and define helper functions
|
||||
|
||||
## Prepare, load, fix, and install `bash-preexec.sh`
|
||||
|
||||
# Disable `$PROMPT_COMMAND` modification for now.
|
||||
__bp_delay_install="delayed"
|
||||
|
||||
# shellcheck source-path=SCRIPTDIR/../vendor/github.com/rcaloras/bash-preexec
|
||||
source "${BASH_IT?}/vendor/github.com/rcaloras/bash-preexec/bash-preexec.sh"
|
||||
|
||||
# Block damanaging user's `$HISTCONTROL`
|
||||
function __bp_adjust_histcontrol() { :; }
|
||||
|
||||
# Don't fail on readonly variables
|
||||
function __bp_require_not_readonly() { :; }
|
||||
|
||||
# For performance, testing, and to avoid unexpected behavior: disable DEBUG traps in subshells.
|
||||
# See bash-it/bash-it#1040 and rcaloras/bash-preexec#26
|
||||
: "${__bp_enable_subshells:=}" # blank
|
||||
|
||||
# Modify `$PROMPT_COMMAND` in finalize hook
|
||||
_bash_it_library_finalize_hook+=('__bp_install_after_session_init')
|
||||
|
||||
## Helper functions
|
||||
function __check_precmd_conflict() {
|
||||
local f
|
||||
__bp_trim_whitespace f "${1?}"
|
||||
_bash-it-array-contains-element "${f}" "${precmd_functions[@]}"
|
||||
}
|
||||
|
||||
function __check_preexec_conflict() {
|
||||
local f
|
||||
__bp_trim_whitespace f "${1?}"
|
||||
_bash-it-array-contains-element "${f}" "${preexec_functions[@]}"
|
||||
}
|
||||
|
||||
function safe_append_prompt_command() {
|
||||
local prompt_re prompt_er f
|
||||
|
||||
if [[ "${bash_preexec_imported:-${__bp_imported:-missing}}" == "defined" ]]; then
|
||||
# We are using bash-preexec
|
||||
__bp_trim_whitespace f "${1?}"
|
||||
if ! __check_precmd_conflict "${f}"; then
|
||||
precmd_functions+=("${f}")
|
||||
fi
|
||||
else
|
||||
# Match on word-boundaries
|
||||
prompt_re='(^|[^[:alnum:]_])'
|
||||
prompt_er='([^[:alnum:]_]|$)'
|
||||
if [[ ${PROMPT_COMMAND} =~ ${prompt_re}"${1}"${prompt_er} ]]; then
|
||||
return
|
||||
elif [[ -z ${PROMPT_COMMAND} ]]; then
|
||||
PROMPT_COMMAND="${1}"
|
||||
else
|
||||
PROMPT_COMMAND="${1};${PROMPT_COMMAND}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function safe_append_preexec() {
|
||||
local prompt_re f
|
||||
|
||||
if [[ "${bash_preexec_imported:-${__bp_imported:-missing}}" == "defined" ]]; then
|
||||
# We are using bash-preexec
|
||||
__bp_trim_whitespace f "${1?}"
|
||||
if ! __check_preexec_conflict "${f}"; then
|
||||
preexec_functions+=("${f}")
|
||||
fi
|
||||
else
|
||||
_log_error "${FUNCNAME[0]}: can't append to preexec hook because _bash-preexec.sh_ hasn't been loaded"
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# Displays the prompt from each _Bash It_ theme.
|
||||
|
||||
function _bash-it-preview() {
|
||||
local BASH_IT_THEME BASH_IT_LOG_LEVEL
|
||||
local themes IFS=$'\n' cur
|
||||
|
||||
if [[ $# -gt '0' ]]; then
|
||||
themes=("$@")
|
||||
else
|
||||
themes=("${BASH_IT?}/themes"/*/*.theme.bash)
|
||||
themes=("${themes[@]##*/}")
|
||||
themes=("${themes[@]%.theme.bash}")
|
||||
fi
|
||||
|
||||
if [[ ${COMP_CWORD:-} -gt '0' ]]; then
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
read -d '' -ra COMPREPLY < <(compgen -W "all${IFS}${themes[*]}" -- "${cur}")
|
||||
return
|
||||
fi
|
||||
printf '\n\n\t%s\n\n' "Previewing Bash-it Themes"
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
for BASH_IT_THEME in "${themes[@]}"; do
|
||||
BASH_IT_LOG_LEVEL=0
|
||||
bash --init-file "${BASH_IT?}/bash_it.sh" -i <<< '_bash-it-flash-term "${#BASH_IT_THEME}" "${BASH_IT_THEME}"'
|
||||
done
|
||||
}
|
||||
|
||||
if [[ -n "${BASH_PREVIEW:-}" ]]; then
|
||||
_bash-it-preview "${BASH_PREVIEW}" "$@"
|
||||
unset BASH_PREVIEW #Prevent infinite looping
|
||||
fi
|
||||
@@ -0,0 +1,373 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# Search by Konstantin Gredeskoul «github.com/kigster»
|
||||
#———————————————————————————————————————————————————————————————————————————————
|
||||
# This function returns list of aliases, plugins and completions in bash-it,
|
||||
# whose name or description matches one of the search terms provided as arguments.
|
||||
#
|
||||
# Usage:
|
||||
# ❯ bash-it search [-|@]term1 [-|@]term2 ... \
|
||||
# [ --enable | -e ] \
|
||||
# [ --disable | -d ] \
|
||||
# [ --no-color | -c ] \
|
||||
# [ --refresh | -r ] \
|
||||
# [ --help | -h ]
|
||||
#
|
||||
# Single dash, as in "-chruby", indicates a negative search term.
|
||||
# Double dash indicates a command that is to be applied to the search result.
|
||||
# At the moment only --help, --enable and --disable are supported.
|
||||
# An '@' sign indicates an exact (not partial) match.
|
||||
#
|
||||
# Examples:
|
||||
# ❯ bash-it search ruby rbenv rvm gem rake
|
||||
# aliases: bundler
|
||||
# plugins: chruby chruby-auto ruby rbenv rvm ruby
|
||||
# completions: rvm gem rake
|
||||
#
|
||||
# ❯ bash-it search ruby rbenv rvm gem rake -chruby
|
||||
# aliases: bundler
|
||||
# plugins: ruby rbenv rvm ruby
|
||||
# completions: rvm gem rake
|
||||
#
|
||||
# Examples of enabling or disabling results of the search:
|
||||
#
|
||||
# ❯ bash-it search ruby
|
||||
# aliases: bundler
|
||||
# plugins: chruby chruby-auto ruby
|
||||
#
|
||||
# ❯ bash-it search ruby -chruby --enable
|
||||
# aliases: bundler
|
||||
# plugins: ruby
|
||||
#
|
||||
# Examples of using exact match:
|
||||
|
||||
# ❯ bash-it search @git @ruby
|
||||
# aliases: git
|
||||
# plugins: git ruby
|
||||
# completions: git
|
||||
#
|
||||
|
||||
function _bash-it-search() {
|
||||
_about 'searches for given terms amongst bash-it plugins, aliases and completions'
|
||||
_param '1: term1'
|
||||
_param '2: [ term2 ]...'
|
||||
_example '$ _bash-it-search @git ruby -rvm rake bundler'
|
||||
|
||||
local component
|
||||
local BASH_IT_SEARCH_USE_COLOR="${BASH_IT_SEARCH_USE_COLOR:=true}"
|
||||
local -a BASH_IT_COMPONENTS=('aliases' 'plugins' 'completions')
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
_bash-it-search-help
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -a args=()
|
||||
for word in "$@"; do
|
||||
case "${word}" in
|
||||
'-h' | '--help')
|
||||
_bash-it-search-help
|
||||
return 0
|
||||
;;
|
||||
'-r' | '--refresh')
|
||||
_bash-it-component-cache-clean
|
||||
;;
|
||||
'-c' | '--no-color')
|
||||
BASH_IT_SEARCH_USE_COLOR=false
|
||||
;;
|
||||
*)
|
||||
args+=("${word}")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ${#args} -gt 0 ]]; then
|
||||
for component in "${BASH_IT_COMPONENTS[@]}"; do
|
||||
_bash-it-search-component "${component}" "${args[@]}"
|
||||
done
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function _bash-it-search-help() {
|
||||
printf '%b' "${echo_normal-}
|
||||
${echo_underline_yellow-}USAGE${echo_normal-}
|
||||
|
||||
bash-it search [-|@]term1 [-|@]term2 ... \\
|
||||
[ --enable | -e ] \\
|
||||
[ --disable | -d ] \\
|
||||
[ --no-color | -c ] \\
|
||||
[ --refresh | -r ] \\
|
||||
[ --help | -h ]
|
||||
|
||||
${echo_underline_yellow-}DESCRIPTION${echo_normal-}
|
||||
|
||||
Use ${echo_bold_green-}search${echo_normal-} bash-it command to search for a list of terms or term negations
|
||||
across all components: aliases, completions and plugins. Components that are
|
||||
enabled are shown in green (or with a check box if --no-color option is used).
|
||||
|
||||
In addition to simply finding the right component, you can use the results
|
||||
of the search to enable or disable all components that the search returns.
|
||||
|
||||
When search is used to enable/disable components it becomes clear that
|
||||
you must be able to perform not just a partial match, but an exact match,
|
||||
as well as be able to exclude some components.
|
||||
|
||||
* To exclude a component (or all components matching a substring) use
|
||||
a search term with minus as a prefix, eg '-flow'
|
||||
|
||||
* To perform an exact match, use character '@' in front of the term,
|
||||
eg. '@git' would only match aliases, plugins and completions named 'git'.
|
||||
|
||||
${echo_underline_yellow-}FLAGS${echo_normal-}
|
||||
--enable | -e ${echo_purple-}Enable all matching componenents.${echo_normal-}
|
||||
--disable | -d ${echo_purple-}Disable all matching componenents.${echo_normal-}
|
||||
--help | -h ${echo_purple-}Print this help.${echo_normal-}
|
||||
--refresh | -r ${echo_purple-}Force a refresh of the search cache.${echo_normal-}
|
||||
--no-color | -c ${echo_purple-}Disable color output and use monochrome text.${echo_normal-}
|
||||
|
||||
${echo_underline_yellow-}EXAMPLES${echo_normal-}
|
||||
|
||||
For example, ${echo_bold_green-}bash-it search git${echo_normal-} would match any alias, completion
|
||||
or plugin that has the word 'git' in either the module name or
|
||||
it's description. You should see something like this when you run this
|
||||
command:
|
||||
|
||||
${echo_bold_green-}❯ bash-it search git${echo_bold_blue-}
|
||||
${echo_bold_yellow-}aliases: ${echo_bold_green-}git ${echo_normal-}gitsvn
|
||||
${echo_bold_yellow-}plugins: ${echo_normal-}autojump ${echo_bold_green-}git ${echo_normal-}git-subrepo jgitflow jump
|
||||
${echo_bold_yellow-}completions: ${echo_bold_green-}git ${echo_normal-}git_flow git_flow_avh${echo_normal-}
|
||||
|
||||
You can exclude some terms by prefixing a term with a minus, eg:
|
||||
|
||||
${echo_bold_green-}❯ bash-it search git -flow -svn${echo_bold_blue-}
|
||||
${echo_bold_yellow-}aliases: ${echo_normal-}git
|
||||
${echo_bold_yellow-}plugins: ${echo_normal-}autojump git git-subrepo jump
|
||||
${echo_bold_yellow-}completions: ${echo_normal-}git${echo_normal-}
|
||||
|
||||
Finally, if you prefix a term with '@' symbol, that indicates an exact
|
||||
match. Note, that we also pass the '--enable' flag, which would ensure
|
||||
that all matches are automatically enabled. The example is below:
|
||||
|
||||
${echo_bold_green-}❯ bash-it search @git --enable${echo_bold_blue-}
|
||||
${echo_bold_yellow-}aliases: ${echo_normal-}git
|
||||
${echo_bold_yellow-}plugins: ${echo_normal-}git
|
||||
${echo_bold_yellow-}completions: ${echo_normal-}git${echo_normal-}
|
||||
|
||||
${echo_underline_yellow-}SUMMARY${echo_normal-}
|
||||
|
||||
Take advantage of the search functionality to discover what Bash-It can do
|
||||
for you. Try searching for partial term matches, mix and match with the
|
||||
negative terms, or specify an exact matches of any number of terms. Once
|
||||
you created the search command that returns ONLY the modules you need,
|
||||
simply append '--enable' or '--disable' at the end to activate/deactivate
|
||||
each module.
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
function _bash-it-is-partial-match() {
|
||||
local component="${1?${FUNCNAME[0]}: component type must be specified}"
|
||||
local term="${2:-}"
|
||||
_bash-it-component-help "${component}" | _bash-it-egrep -i -q -- "${term}"
|
||||
}
|
||||
|
||||
function _bash-it-component-term-matches-negation() {
|
||||
local match="$1"
|
||||
shift
|
||||
local negative
|
||||
for negative in "$@"; do
|
||||
[[ "${match}" =~ ${negative} ]] && return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function _bash-it-search-component() {
|
||||
_about 'searches for given terms amongst a given component'
|
||||
_param '1: component type, one of: [ aliases | plugins | completions ]'
|
||||
_param '2: term1 term2 @term3'
|
||||
_param '3: [-]term4 [-]term5 ...'
|
||||
_example '$ _bash-it-search-component aliases @git rake bundler -chruby'
|
||||
|
||||
local component="${1?${FUNCNAME[0]}: component type must be specified}"
|
||||
shift
|
||||
|
||||
# if one of the search terms is --enable or --disable, we will apply
|
||||
# this action to the matches further ` down.
|
||||
local component_singular action action_func
|
||||
local -a search_commands=('enable' 'disable')
|
||||
for search_command in "${search_commands[@]}"; do
|
||||
if _bash-it-array-contains-element "--${search_command}" "$@"; then
|
||||
component_singular="${component/es/}" # aliases -> alias
|
||||
component_singular="${component_singular/ns/n}" # plugins -> plugin
|
||||
|
||||
action="${search_command}"
|
||||
action_func="_${action}-${component_singular}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
local -a terms=("$@") # passed on the command line
|
||||
|
||||
local -a exact_terms=() # terms that should be included only if they match exactly
|
||||
local -a partial_terms=() # terms that should be included if they match partially
|
||||
local -a negative_terms=() # negated partial terms that should be excluded
|
||||
|
||||
local term line
|
||||
|
||||
local -a component_list=()
|
||||
while IFS='' read -r line; do
|
||||
component_list+=("$line")
|
||||
done < <(_bash-it-component-list "${component}")
|
||||
|
||||
for term in "${terms[@]}"; do
|
||||
local search_term="${term:1}"
|
||||
if [[ "${term:0:2}" == "--" ]]; then
|
||||
continue
|
||||
elif [[ "${term:0:1}" == "-" ]]; then
|
||||
negative_terms+=("${search_term}")
|
||||
elif [[ "${term:0:1}" == "@" ]]; then
|
||||
if _bash-it-array-contains-element "${search_term}" "${component_list[@]:-}"; then
|
||||
exact_terms+=("${search_term}")
|
||||
fi
|
||||
else
|
||||
while IFS='' read -r line; do
|
||||
partial_terms+=("$line")
|
||||
done < <(_bash-it-component-list-matching "${component}" "${term}")
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
local -a total_matches=()
|
||||
while IFS='' read -r line; do
|
||||
total_matches+=("$line")
|
||||
done < <(_bash-it-array-dedup "${exact_terms[@]:-}" "${partial_terms[@]:-}")
|
||||
|
||||
local -a matches=()
|
||||
for match in "${total_matches[@]}"; do
|
||||
local -i include_match=1
|
||||
if [[ ${#negative_terms[@]} -gt 0 ]]; then
|
||||
_bash-it-component-term-matches-negation "${match}" "${negative_terms[@]:-}" && include_match=0
|
||||
fi
|
||||
((include_match)) && matches+=("${match}")
|
||||
done
|
||||
|
||||
_bash-it-search-result "${component}" "${action:-}" "${action_func:-}" "${matches[@]:-}"
|
||||
}
|
||||
|
||||
function _bash-it-search-result() {
|
||||
local component="${1?${FUNCNAME[0]}: component type must be specified}"
|
||||
shift
|
||||
local action="${1:-}"
|
||||
shift
|
||||
local action_func="${1:-}"
|
||||
shift
|
||||
|
||||
local color_component color_enable color_disable color_off
|
||||
local match_color compatible_action suffix opposite_suffix
|
||||
local color_sep=':' line match matched temp
|
||||
local -i modified=0 enabled=0 len
|
||||
local -a matches=()
|
||||
|
||||
# Discard any empty arguments
|
||||
while IFS='' read -r line; do
|
||||
[[ -n "${line}" ]] && matches+=("$line")
|
||||
done < <(_bash-it-array-dedup "${@}")
|
||||
|
||||
if [[ "${BASH_IT_SEARCH_USE_COLOR}" == "true" ]]; then
|
||||
color_component='\e[1;34m'
|
||||
color_enable='\e[1;32m'
|
||||
suffix_enable=''
|
||||
suffix_disable=''
|
||||
color_disable='\e[0;0m'
|
||||
color_off='\e[0;0m'
|
||||
else
|
||||
color_component=''
|
||||
suffix_enable=' ✓ ︎'
|
||||
suffix_disable=' '
|
||||
color_enable=''
|
||||
color_disable=''
|
||||
color_off=''
|
||||
fi
|
||||
|
||||
if [[ "${#matches[@]}" -gt 0 ]]; then
|
||||
printf "${color_component}%13s${color_sep}${color_off} " "${component}"
|
||||
|
||||
for match in "${matches[@]}"; do
|
||||
enabled=0
|
||||
_bash-it-component-item-is-enabled "${component}" "${match}" && enabled=1
|
||||
|
||||
if ((enabled)); then
|
||||
match_color="${color_enable}"
|
||||
suffix="${suffix_enable}"
|
||||
opposite_suffix="${suffix_disable}"
|
||||
compatible_action="disable"
|
||||
else
|
||||
match_color="${color_disable}"
|
||||
suffix="${suffix_disable}"
|
||||
opposite_suffix="${suffix_enable}"
|
||||
compatible_action="enable"
|
||||
fi
|
||||
|
||||
matched="${match}${suffix}"
|
||||
len="${#matched}"
|
||||
|
||||
printf '%b' "${match_color}${matched}" # print current state
|
||||
if [[ "${action}" == "${compatible_action}" ]]; then
|
||||
if [[ "${action}" == "enable" && "${BASH_IT_SEARCH_USE_COLOR}" == "true" ]]; then
|
||||
_bash-it-flash-term "${len}" "${matched}"
|
||||
else
|
||||
_bash-it-erase-term "${len}" "${matched}"
|
||||
fi
|
||||
modified=1
|
||||
# shellcheck disable=SC2034 # no idea if `$result` is ever used
|
||||
result=$("${action_func}" "${match}")
|
||||
temp="color_${compatible_action}"
|
||||
match_color="${!temp}"
|
||||
_bash-it-rewind "${len}"
|
||||
printf '%b' "${match_color}${match}${opposite_suffix}"
|
||||
fi
|
||||
|
||||
printf '%b' "${color_off} "
|
||||
done
|
||||
|
||||
((modified)) && _bash-it-component-cache-clean "${component}"
|
||||
printf "\n"
|
||||
fi
|
||||
}
|
||||
|
||||
function _bash-it-rewind() {
|
||||
local -i len="${1:-0}"
|
||||
printf '%b' "\033[${len}D"
|
||||
}
|
||||
|
||||
function _bash-it-flash-term() {
|
||||
local -i len="${1:-0}" # redundant
|
||||
local term="${2:-}"
|
||||
# as currently implemented, `$match` has already been printed to screen the first time
|
||||
local delay=0.2
|
||||
local color
|
||||
[[ "${#term}" -gt 0 ]] && len="${#term}"
|
||||
|
||||
for color in "${echo_black-}" "${echo_bold_blue-}" "${echo_bold_yellow-}" "${echo_bold_red-}" "${echo_bold_green-}" "${echo_normal-}"; do
|
||||
sleep "${delay}"
|
||||
_bash-it-rewind "${len}"
|
||||
printf '%b' "${color}${term}"
|
||||
done
|
||||
}
|
||||
|
||||
function _bash-it-erase-term() {
|
||||
local -i len="${1:-0}" i
|
||||
local delay=0.05
|
||||
local term="${2:-}" # calculate length ourselves
|
||||
[[ "${#term}" -gt 0 ]] && len="${#term}"
|
||||
|
||||
_bash-it-rewind "${len}"
|
||||
# white-out the already-printed term by printing blanks
|
||||
for ((i = 0; i <= len; i++)); do
|
||||
printf "%.*s" "$i" " "
|
||||
sleep "${delay}"
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# A collection of reusable functions.
|
||||
|
||||
###########################################################################
|
||||
# Generic utilies
|
||||
###########################################################################
|
||||
|
||||
function _bash-it-get-component-name-from-path() {
|
||||
local filename
|
||||
# filename without path
|
||||
filename="${1##*/}"
|
||||
# filename without path or priority
|
||||
filename="${filename##*"${BASH_IT_LOAD_PRIORITY_SEPARATOR?}"}"
|
||||
# filename without path, priority or extension
|
||||
echo "${filename%.*.bash}"
|
||||
}
|
||||
|
||||
function _bash-it-get-component-type-from-path() {
|
||||
local filename
|
||||
# filename without path
|
||||
filename="${1##*/}"
|
||||
# filename without extension
|
||||
filename="${filename%.bash}"
|
||||
# extension without priority or name
|
||||
filename="${filename##*.}"
|
||||
echo "${filename}"
|
||||
}
|
||||
|
||||
# This function searches an array for an exact match against the term passed
|
||||
# as the first argument to the function. This function exits as soon as
|
||||
# a match is found.
|
||||
#
|
||||
# Returns:
|
||||
# 0 when a match is found, otherwise 1.
|
||||
#
|
||||
# Examples:
|
||||
# $ declare -a fruits=(apple orange pear mandarin)
|
||||
#
|
||||
# $ _bash-it-array-contains-element apple "@{fruits[@]}" && echo 'contains apple'
|
||||
# contains apple
|
||||
#
|
||||
# $ if _bash-it-array-contains-element pear "${fruits[@]}"; then
|
||||
# echo "contains pear!"
|
||||
# fi
|
||||
# contains pear!
|
||||
#
|
||||
#
|
||||
function _bash-it-array-contains-element() {
|
||||
local e element="${1?}"
|
||||
shift
|
||||
for e in "$@"; do
|
||||
[[ "$e" == "${element}" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Dedupe an array (without embedded newlines).
|
||||
function _bash-it-array-dedup() {
|
||||
printf '%s\n' "$@" | sort -u
|
||||
}
|
||||
|
||||
# Outputs a full path of the grep found on the filesystem
|
||||
function _bash-it-grep() {
|
||||
: "${BASH_IT_GREP:=$(type -P egrep || type -P grep)}"
|
||||
printf "%s" "${BASH_IT_GREP:-/usr/bin/grep}"
|
||||
}
|
||||
|
||||
# Runs `grep` with extended regular expressions
|
||||
function _bash-it-egrep() {
|
||||
: "${BASH_IT_GREP:=$(type -P egrep || type -P grep)}"
|
||||
"${BASH_IT_GREP:-/usr/bin/grep}" -E "$@"
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Component-specific functions (component is either an alias, a plugin, or a
|
||||
# completion).
|
||||
###########################################################################
|
||||
|
||||
function _bash-it-component-help() {
|
||||
local component file func
|
||||
_bash-it-component-pluralize "${1}" component
|
||||
_bash-it-component-cache-file "${component}" file
|
||||
if [[ ! -s "${file?}" || -z "$(find "${file}" -mmin -300)" ]]; then
|
||||
func="_bash-it-${component?}"
|
||||
"${func}" | _bash-it-egrep '\[[x ]\]' >| "${file}"
|
||||
fi
|
||||
cat "${file}"
|
||||
}
|
||||
|
||||
function _bash-it-component-cache-file() {
|
||||
local _component_to_cache _file_path _result="${2:-${FUNCNAME[0]//-/_}}"
|
||||
_bash-it-component-pluralize "${1?${FUNCNAME[0]}: component name required}" _component_to_cache
|
||||
_file_path="${XDG_CACHE_HOME:-${HOME?}/.cache}/bash/${_component_to_cache?}"
|
||||
[[ -f "${_file_path}" ]] || mkdir -p "${_file_path%/*}"
|
||||
printf -v "${_result?}" '%s' "${_file_path}"
|
||||
}
|
||||
|
||||
function _bash-it-component-singularize() {
|
||||
local _result="${2:-${FUNCNAME[0]//-/_}}"
|
||||
local _component_to_single="${1?${FUNCNAME[0]}: component name required}"
|
||||
local -i len="$((${#_component_to_single} - 2))"
|
||||
if [[ "${_component_to_single:${len}:2}" == 'ns' ]]; then
|
||||
_component_to_single="${_component_to_single%s}"
|
||||
elif [[ "${_component_to_single}" == "aliases" ]]; then
|
||||
_component_to_single="${_component_to_single%es}"
|
||||
fi
|
||||
printf -v "${_result?}" '%s' "${_component_to_single}"
|
||||
}
|
||||
|
||||
function _bash-it-component-pluralize() {
|
||||
local _result="${2:-${FUNCNAME[0]//-/_}}"
|
||||
local _component_to_plural="${1?${FUNCNAME[0]}: component name required}"
|
||||
local -i len="$((${#_component_to_plural} - 1))"
|
||||
# pluralize component name for consistency
|
||||
if [[ "${_component_to_plural:${len}:1}" != 's' ]]; then
|
||||
_component_to_plural="${_component_to_plural}s"
|
||||
elif [[ "${_component_to_plural}" == "alias" ]]; then
|
||||
_component_to_plural="${_component_to_plural}es"
|
||||
fi
|
||||
printf -v "${_result?}" '%s' "${_component_to_plural}"
|
||||
}
|
||||
|
||||
function _bash-it-component-cache-clean() {
|
||||
local component="${1:-}"
|
||||
local cache
|
||||
local -a components=('aliases' 'plugins' 'completions')
|
||||
if [[ -z "${component}" ]]; then
|
||||
for component in "${components[@]}"; do
|
||||
_bash-it-component-cache-clean "${component}"
|
||||
done
|
||||
else
|
||||
_bash-it-component-cache-file "${component}" cache
|
||||
: >| "${cache:?}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Returns an array of items within each compoenent.
|
||||
function _bash-it-component-list() {
|
||||
local IFS=$'\n' component="$1"
|
||||
_bash-it-component-help "${component}" | awk '{print $1}' | sort -u
|
||||
}
|
||||
|
||||
function _bash-it-component-list-matching() {
|
||||
local component="$1"
|
||||
shift
|
||||
local term="$1"
|
||||
_bash-it-component-help "${component}" | _bash-it-egrep -- "${term}" | awk '{print $1}' | sort -u
|
||||
}
|
||||
|
||||
function _bash-it-component-list-enabled() {
|
||||
local IFS=$'\n' component="$1"
|
||||
_bash-it-component-help "${component}" | _bash-it-egrep '\[x\]' | awk '{print $1}' | sort -u
|
||||
}
|
||||
|
||||
function _bash-it-component-list-disabled() {
|
||||
local IFS=$'\n' component="$1"
|
||||
_bash-it-component-help "${component}" | _bash-it-egrep -v '\[x\]' | awk '{print $1}' | sort -u
|
||||
}
|
||||
|
||||
# Checks if a given item is enabled for a particular component/file-type.
|
||||
#
|
||||
# Returns:
|
||||
# 0 if an item of the component is enabled, 1 otherwise.
|
||||
#
|
||||
# Examples:
|
||||
# _bash-it-component-item-is-enabled alias git && echo "git alias is enabled"
|
||||
function _bash-it-component-item-is-enabled() {
|
||||
local component_type item_name each_file
|
||||
|
||||
if [[ -f "${1?}" ]]; then
|
||||
item_name="$(_bash-it-get-component-name-from-path "${1}")"
|
||||
component_type="$(_bash-it-get-component-type-from-path "${1}")"
|
||||
else
|
||||
component_type="${1}" item_name="${2?}"
|
||||
fi
|
||||
|
||||
for each_file in "${BASH_IT}/enabled"/*"${BASH_IT_LOAD_PRIORITY_SEPARATOR?}${item_name}.${component_type}"*."bash" \
|
||||
"${BASH_IT}/${component_type}"*/"enabled/${item_name}.${component_type}"*."bash" \
|
||||
"${BASH_IT}/${component_type}"*/"enabled"/*"${BASH_IT_LOAD_PRIORITY_SEPARATOR?}${item_name}.${component_type}"*."bash"; do
|
||||
if [[ -f "${each_file}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Checks if a given item is disabled for a particular component/file-type.
|
||||
#
|
||||
# Returns:
|
||||
# 0 if an item of the component is enabled, 1 otherwise.
|
||||
#
|
||||
# Examples:
|
||||
# _bash-it-component-item-is-disabled alias git && echo "git aliases are disabled"
|
||||
function _bash-it-component-item-is-disabled() {
|
||||
! _bash-it-component-item-is-enabled "$@"
|
||||
}
|
||||
Reference in New Issue
Block a user