Merge branch 'master' of https://github.com/Bash-it/bash-it into ira/fix-dirs
* 'master' of https://github.com/Bash-it/bash-it: (22 commits) main: variable name cleanup lib/history: new functions `_bash-it-history-auto-*()` plugin/history*search: no need to load after `plugin/history` plugin/history-eternal: Use `readonly` instead of `export` plugin/history: don't use `export` lib/preview: add full completion lib/helpers: add `preview` to `bash-it` spaghetti lib/preview: refactor into a function completion/system: correctly load version when not linked main: adopt `_bash-it-log-prefix-by-path()` main: Glob for *.bash properly when path contains spaces completion/aliases: rename init function test/battery: require matching battery identifier test/battery: add multiple-battery edge case plugin/battery: split `upower` to two variables completion/alias: add stub file completion/alias: fix tests completion/alias: rename completion/alias: `shfmt` && `shellcheck` completion/alias: eliminate use of `eval` ...
This commit is contained in:
@@ -1,105 +1,5 @@
|
||||
# shellcheck shell=bash
|
||||
# Load after the other completions to understand what needs to be completed
|
||||
# BASH_IT_LOAD_PRIORITY: 365
|
||||
# stub for renamed file
|
||||
|
||||
cite about-plugin
|
||||
about-plugin 'Automatic completion of aliases'
|
||||
|
||||
# References:
|
||||
# http://superuser.com/a/437508/119764
|
||||
# http://stackoverflow.com/a/1793178/1228454
|
||||
|
||||
# This needs to be a plugin so it gets executed after the completions and the aliases have been defined.
|
||||
# Bash-it loads its components in the order
|
||||
# 1) Aliases
|
||||
# 2) Completions
|
||||
# 3) Plugins
|
||||
# 4) Custom scripts
|
||||
|
||||
# Automatically add completion for all aliases to commands having completion functions
|
||||
function alias_completion {
|
||||
local namespace="alias_completion"
|
||||
local tmp_file completion_loader alias_name alias_tokens line completions
|
||||
local alias_arg_words new_completion compl_func compl_wrapper
|
||||
|
||||
# parse function based completion definitions, where capture group 2 => function and 3 => trigger
|
||||
local compl_regex='complete( +[^ ]+)* -F ([^ ]+) ("[^"]+"|[^ ]+)'
|
||||
# parse alias definitions, where capture group 1 => trigger, 2 => command, 3 => command arguments
|
||||
local alias_regex="alias( -- | )([^=]+)='(\"[^\"]+\"|[^ ]+)(( +[^ ]+)*)'"
|
||||
|
||||
# create array of function completion triggers, keeping multi-word triggers together
|
||||
eval "completions=($(complete -p | sed -Ene "/$compl_regex/s//'\3'/p"))"
|
||||
((${#completions[@]} == 0)) && return 0
|
||||
|
||||
# create temporary file for wrapper functions and completions
|
||||
tmp_file="$(mktemp -t "${namespace}-${RANDOM}XXXXXX")" || return 1
|
||||
|
||||
completion_loader="$(complete -p -D 2> /dev/null | sed -Ene 's/.* -F ([^ ]*).*/\1/p')"
|
||||
|
||||
# read in "<alias> '<aliased command>' '<command args>'" lines from defined aliases
|
||||
# some aliases do have backslashes that needs to be interpreted
|
||||
# shellcheck disable=SC2162
|
||||
while read line; do
|
||||
eval "alias_tokens=($line)" 2> /dev/null || continue # some alias arg patterns cause an eval parse error
|
||||
# shellcheck disable=SC2154 # see `eval` above
|
||||
alias_name="${alias_tokens[0]}" alias_cmd="${alias_tokens[1]}" alias_args="${alias_tokens[2]# }"
|
||||
|
||||
# skip aliases to pipes, boolean control structures and other command lists
|
||||
# (leveraging that eval errs out if $alias_args contains unquoted shell metacharacters)
|
||||
eval "alias_arg_words=($alias_args)" 2> /dev/null || continue
|
||||
# avoid expanding wildcards
|
||||
read -a alias_arg_words <<< "$alias_args"
|
||||
|
||||
# skip alias if there is no completion function triggered by the aliased command
|
||||
if ! _bash-it-array-contains-element "$alias_cmd" "${completions[@]}"; then
|
||||
if [[ -n "$completion_loader" ]]; then
|
||||
# force loading of completions for the aliased command
|
||||
eval "$completion_loader $alias_cmd"
|
||||
# 124 means completion loader was successful
|
||||
[[ $? -eq 124 ]] || continue
|
||||
completions+=("$alias_cmd")
|
||||
else
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
new_completion="$(complete -p "$alias_cmd" 2> /dev/null)"
|
||||
|
||||
# create a wrapper inserting the alias arguments if any
|
||||
if [[ -n $alias_args ]]; then
|
||||
compl_func="${new_completion/#* -F /}"
|
||||
compl_func="${compl_func%% *}"
|
||||
# avoid recursive call loops by ignoring our own functions
|
||||
if [[ "${compl_func#_"$namespace"::}" == "$compl_func" ]]; then
|
||||
compl_wrapper="_${namespace}::${alias_name}"
|
||||
echo "function $compl_wrapper {
|
||||
local compl_word=\$2
|
||||
local prec_word=\$3
|
||||
# check if prec_word is the alias itself. if so, replace it
|
||||
# with the last word in the unaliased form, i.e.,
|
||||
# alias_cmd + ' ' + alias_args.
|
||||
if [[ \$COMP_LINE == \"\$prec_word \$compl_word\" ]]; then
|
||||
prec_word='$alias_cmd $alias_args'
|
||||
prec_word=\${prec_word#* }
|
||||
fi
|
||||
(( COMP_CWORD += ${#alias_arg_words[@]} ))
|
||||
COMP_WORDS=($alias_cmd $alias_args \${COMP_WORDS[@]:1})
|
||||
(( COMP_POINT -= \${#COMP_LINE} ))
|
||||
COMP_LINE=\${COMP_LINE/$alias_name/$alias_cmd $alias_args}
|
||||
(( COMP_POINT += \${#COMP_LINE} ))
|
||||
$compl_func \"$alias_cmd\" \"\$compl_word\" \"\$prec_word\"
|
||||
}" >> "$tmp_file"
|
||||
new_completion="${new_completion/ -F $compl_func / -F $compl_wrapper }"
|
||||
fi
|
||||
fi
|
||||
|
||||
# replace completion trigger by alias
|
||||
if [[ -n $new_completion ]]; then
|
||||
new_completion="${new_completion% *} $alias_name"
|
||||
echo "$new_completion" >> "$tmp_file"
|
||||
fi
|
||||
done < <(alias -p | sed -Ene "s/$alias_regex/\2 '\3' '\4'/p")
|
||||
# shellcheck source=/dev/null
|
||||
source "$tmp_file" && command rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
alias_completion
|
||||
_enable-completion aliases && _disable-plugin alias-completion
|
||||
source "${BASH_IT?}/completion/aliases.completion.bash"
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
about-plugin 'display info about your battery charge level'
|
||||
|
||||
function ac_adapter_connected() {
|
||||
local batteries
|
||||
if _command_exists upower; then
|
||||
upower -i "$(upower -e | grep -i BAT)" | grep 'state' | grep -q 'charging\|fully-charged'
|
||||
batteries="$(upower -e | grep --max-count=1 -i BAT)"
|
||||
upower -i "${batteries}" | grep 'state' | grep -q 'charging\|fully-charged'
|
||||
elif _command_exists acpi; then
|
||||
acpi -a | grep -q "on-line"
|
||||
elif _command_exists pmset; then
|
||||
@@ -16,8 +18,10 @@ function ac_adapter_connected() {
|
||||
}
|
||||
|
||||
function ac_adapter_disconnected() {
|
||||
local batteries
|
||||
if _command_exists upower; then
|
||||
upower -i "$(upower -e | grep -i BAT)" | grep 'state' | grep -q 'discharging'
|
||||
batteries="$(upower -e | grep --max-count=1 -i BAT)"
|
||||
upower -i "${batteries}" | grep 'state' | grep -q 'discharging'
|
||||
elif _command_exists acpi; then
|
||||
acpi -a | grep -q "off-line"
|
||||
elif _command_exists pmset; then
|
||||
@@ -33,16 +37,17 @@ function battery_percentage() {
|
||||
about 'displays battery charge as a percentage of full (100%)'
|
||||
group 'battery'
|
||||
|
||||
local command_output="no"
|
||||
local command_output batteries
|
||||
|
||||
if _command_exists upower; then
|
||||
command_output=$(upower --show-info "$(upower --enumerate | grep -i BAT)" | grep percentage | grep -o "[0-9]\+" | head -1)
|
||||
batteries="$(upower --enumerate | grep --max-count=1 -i BAT)"
|
||||
command_output="$(upower --show-info "${batteries:-}" | grep percentage | grep -o '[0-9]\+' | head -1)"
|
||||
elif _command_exists acpi; then
|
||||
command_output=$(acpi -b | awk -F, '/,/{gsub(/ /, "", $0); gsub(/%/,"", $0); print $2}')
|
||||
elif _command_exists pmset; then
|
||||
command_output=$(pmset -g ps | sed -n 's/.*[[:blank:]]+*\(.*%\).*/\1/p' | grep -o "[0-9]\+" | head -1)
|
||||
command_output=$(pmset -g ps | sed -n 's/.*[[:blank:]]+*\(.*%\).*/\1/p' | grep -o '[0-9]\+' | head -1)
|
||||
elif _command_exists ioreg; then
|
||||
command_output=$(ioreg -n AppleSmartBattery -r | awk '$1~/Capacity/{c[$1]=$3} END{OFMT="%05.2f"; max=c["\"MaxCapacity\""]; print (max>0? 100*c["\"CurrentCapacity\""]/max: "?")}' | grep -o "[0-9]\+" | head -1)
|
||||
command_output=$(ioreg -n AppleSmartBattery -r | awk '$1~/Capacity/{c[$1]=$3} END{OFMT="%05.2f"; max=c["\"MaxCapacity\""]; print (max>0? 100*c["\"CurrentCapacity\""]/max: "?")}' | grep -o '[0-9]\+' | head -1)
|
||||
elif _command_exists WMIC; then
|
||||
command_output=$(WMIC PATH Win32_Battery Get EstimatedChargeRemaining /Format:List | grep -o '[0-9]\+' | head -1)
|
||||
else
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
# shellcheck shell=bash
|
||||
about-plugin 'eternal bash history'
|
||||
|
||||
# Load after the history plugin
|
||||
# BASH_IT_LOAD_PRIORITY: 375
|
||||
if [[ ${BASH_VERSINFO[0]} -lt 4 ]] || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then
|
||||
_log_warning "Bash version 4.3 introduced the 'unlimited' history size capability."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Modify history sizes before changing location to avoid unintentionally
|
||||
# truncating the history file early.
|
||||
|
||||
# "Numeric values less than zero result in every command being saved on the history list (there is no limit)"
|
||||
export HISTSIZE=-1
|
||||
readonly HISTSIZE=-1 2> /dev/null || true
|
||||
|
||||
# "Non-numeric values and numeric values less than zero inhibit truncation"
|
||||
export HISTFILESIZE='unlimited'
|
||||
readonly HISTFILESIZE='unlimited' 2> /dev/null || true
|
||||
|
||||
# Use a custom history file location so history is not truncated
|
||||
# if the environment ever loses this "eternal" configuration.
|
||||
HISTDIR="${XDG_STATE_HOME:-${HOME?}/.local/state}/bash"
|
||||
[[ -d ${HISTDIR?} ]] || mkdir -p "${HISTDIR?}"
|
||||
export HISTFILE="${HISTDIR?}/history"
|
||||
readonly HISTFILE="${HISTDIR?}/history" 2> /dev/null || true
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# shellcheck shell=bash
|
||||
about-plugin 'search history using the prefix already entered'
|
||||
|
||||
# Load after the history plugin
|
||||
# BASH_IT_LOAD_PRIORITY: 375
|
||||
|
||||
# enter a few characters and press UpArrow/DownArrow
|
||||
# to search backwards/forwards through the history
|
||||
if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# shellcheck shell=bash
|
||||
about-plugin 'search history using the substring already entered'
|
||||
|
||||
# Load after the history plugin
|
||||
# BASH_IT_LOAD_PRIORITY: 375
|
||||
|
||||
# enter a few characters and press UpArrow/DownArrow
|
||||
# to search backwards/forwards through the history
|
||||
if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then
|
||||
|
||||
@@ -5,14 +5,13 @@ about-plugin 'improve history handling with sane defaults'
|
||||
# variable when the shell exits, rather than overwriting the file.
|
||||
shopt -s histappend
|
||||
|
||||
# erase duplicates; alternative option: export HISTCONTROL=ignoredups
|
||||
export HISTCONTROL=${HISTCONTROL:-ignorespace:erasedups}
|
||||
# 'ignorespace': don't save command lines which begin with a space to history
|
||||
# 'erasedups' (alternative 'ignoredups'): don't save duplicates to history
|
||||
# 'autoshare': automatically share history between multiple running shells
|
||||
: "${HISTCONTROL:=ignorespace:erasedups:autoshare}"
|
||||
|
||||
# resize history to 100x the default (500)
|
||||
export HISTSIZE=${HISTSIZE:-50000}
|
||||
|
||||
# Flush history to disk after each command.
|
||||
export PROMPT_COMMAND="history -a;${PROMPT_COMMAND}"
|
||||
: "${HISTSIZE:=50000}"
|
||||
|
||||
function top-history() {
|
||||
about 'print the name and count of the most commonly run tools'
|
||||
|
||||
Reference in New Issue
Block a user