diff --git a/clean_files.txt b/clean_files.txt index 8f9c173a29..70b1175cb1 100644 --- a/clean_files.txt +++ b/clean_files.txt @@ -83,6 +83,7 @@ completion/available/wpscan.completion.bash # libraries lib/colors.bash lib/helpers.bash +lib/history.bash lib/log.bash lib/preexec.bash lib/search.bash diff --git a/lib/history.bash b/lib/history.bash new file mode 100644 index 0000000000..7bdbbd5ef0 --- /dev/null +++ b/lib/history.bash @@ -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') diff --git a/plugins/available/history-eternal.plugin.bash b/plugins/available/history-eternal.plugin.bash index a18283d31f..829868df4a 100644 --- a/plugins/available/history-eternal.plugin.bash +++ b/plugins/available/history-eternal.plugin.bash @@ -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 diff --git a/plugins/available/history-search.plugin.bash b/plugins/available/history-search.plugin.bash index 341ce2af27..969419934c 100644 --- a/plugins/available/history-search.plugin.bash +++ b/plugins/available/history-search.plugin.bash @@ -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 diff --git a/plugins/available/history-substring-search.plugin.bash b/plugins/available/history-substring-search.plugin.bash index 586ceb50b0..dde3272083 100644 --- a/plugins/available/history-substring-search.plugin.bash +++ b/plugins/available/history-substring-search.plugin.bash @@ -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 diff --git a/plugins/available/history.plugin.bash b/plugins/available/history.plugin.bash index be253e4a53..d9e930c389 100644 --- a/plugins/available/history.plugin.bash +++ b/plugins/available/history.plugin.bash @@ -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' diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index b614d148c1..71712de9b8 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -41,6 +41,16 @@ SCM_THEME_BRANCH_TRACK_PREFIX="${normal} ⤏ ${cyan}" SCM_THEME_CURRENT_USER_PREFFIX='  ' SCM_GIT_SHOW_CURRENT_USER=false +case $HISTCONTROL in + *'auto'*) + : # Do nothing, already configured. + ;; + *) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac + function _git-uptream-remote-logo { [[ "$(_git-upstream)" == "" ]] && SCM_GIT_CHAR="$SCM_GIT_CHAR_DEFAULT" @@ -80,8 +90,6 @@ function _prompt { _exit-code exit_code _git-uptream-remote-logo - history -a - # Detect root shell if [ "$(whoami)" = root ]; then dir_color=$red @@ -109,4 +117,5 @@ function _prompt { PS1="${PS1}${wrap_char}❯${normal} " } +safe_append_preexec _bash-it-history-auto-save safe_append_prompt_command _prompt diff --git a/themes/base.theme.bash b/themes/base.theme.bash index a7e999617b..d7479b3fc0 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -584,6 +584,7 @@ function aws_profile { } function _save-and-reload-history() { - local autosave=${1:-0} - [[ $autosave -eq 1 ]] && history -a && history -c && history -r + local autosave="${1:-${HISTORY_AUTOSAVE:-0}}" + [[ ${autosave} -eq 1 ]] && local HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autoshare" + _bash-it-history-auto-save && _bash-it-history-auto-load } diff --git a/themes/codeword/codeword.theme.bash b/themes/codeword/codeword.theme.bash index d52403c12e..16f1098735 100644 --- a/themes/codeword/codeword.theme.bash +++ b/themes/codeword/codeword.theme.bash @@ -1,5 +1,17 @@ # shellcheck shell=bash +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + SCM_THEME_PROMPT_PREFIX="${SCM_THEME_PROMPT_SUFFIX:-}" SCM_THEME_PROMPT_DIRTY="${bold_red?} ✗${normal?}" SCM_THEME_PROMPT_CLEAN="${bold_green?} ✓${normal?}" @@ -21,5 +33,4 @@ function prompt() { PS1="$(user_host_path_prompt)$(virtualenv_prompt)$(scm_prompt) $(mark_prompt) " } -safe_append_prompt_command '_save-and-reload-history 1' safe_append_prompt_command prompt diff --git a/themes/doubletime/doubletime.theme.bash b/themes/doubletime/doubletime.theme.bash index 8186db736b..536573e446 100644 --- a/themes/doubletime/doubletime.theme.bash +++ b/themes/doubletime/doubletime.theme.bash @@ -1,5 +1,17 @@ # shellcheck shell=bash +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + SCM_THEME_PROMPT_DIRTY='' SCM_THEME_PROMPT_CLEAN='' SCM_GIT_CHAR="${bold_cyan}±${normal}" @@ -29,8 +41,6 @@ else fi function prompt_setter() { - # Save history - _save-and-reload-history 1 PS1=" $(clock_prompt) $(scm_char) [${THEME_PROMPT_HOST_COLOR}\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt)$(ruby_version_prompt)\w $(scm_prompt)$reset_color $ " diff --git a/themes/doubletime_multiline/doubletime_multiline.theme.bash b/themes/doubletime_multiline/doubletime_multiline.theme.bash index f2dfe43a7b..8b2bab04b7 100644 --- a/themes/doubletime_multiline/doubletime_multiline.theme.bash +++ b/themes/doubletime_multiline/doubletime_multiline.theme.bash @@ -2,9 +2,19 @@ source "$BASH_IT/themes/doubletime/doubletime.theme.bash" +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + function prompt_setter() { - # Save history - _save-and-reload-history 1 PS1=" $(clock_prompt) $(scm_char) [$THEME_PROMPT_HOST_COLOR\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt)$(ruby_version_prompt) \w diff --git a/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.bash b/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.bash index 0fe0eff486..a2a5884c8f 100644 --- a/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.bash +++ b/themes/doubletime_multiline_pyonly/doubletime_multiline_pyonly.theme.bash @@ -2,9 +2,19 @@ source "$BASH_IT/themes/doubletime/doubletime.theme.bash" +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + function prompt_setter() { - # Save history - _save-and-reload-history 1 PS1=" $(clock_prompt) $(scm_char) [$THEME_PROMPT_HOST_COLOR\u@${THEME_PROMPT_HOST}$reset_color] $(virtualenv_prompt) \w diff --git a/themes/font/font.theme.bash b/themes/font/font.theme.bash index 2dbccceadd..d611745bce 100644 --- a/themes/font/font.theme.bash +++ b/themes/font/font.theme.bash @@ -41,6 +41,16 @@ USER_HOST_THEME_PROMPT_SUFFIX=" " VIRTUALENV_THEME_PROMPT_PREFIX='(' VIRTUALENV_THEME_PROMPT_SUFFIX=') ' +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac + function prompt_command() { # This needs to be first to save last command return code local RC="$?" @@ -55,10 +65,8 @@ function prompt_command() { ret_status="${bold_red}" fi - # Append new history lines to history file - history -a - PS1="$(clock_prompt)${virtualenv}$(user_host_prompt)${bold_cyan}\W $(scm_prompt_char_info)${ret_status}→ ${normal}" } +save_append_preexec _bash-it-history-auto-save safe_append_prompt_command prompt_command diff --git a/themes/nwinkler/nwinkler.theme.bash b/themes/nwinkler/nwinkler.theme.bash index 983c8d0020..2f424f6ce2 100644 --- a/themes/nwinkler/nwinkler.theme.bash +++ b/themes/nwinkler/nwinkler.theme.bash @@ -16,6 +16,18 @@ # since 'fasd' is messing with the $PROMPT_COMMAND +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + PROMPT_END_CLEAN="${green}→${reset_color}" PROMPT_END_DIRTY="${red}→${reset_color}" @@ -28,8 +40,6 @@ prompt_setter() { if [[ $exit_status -eq 0 ]]; then PROMPT_END=$PROMPT_END_CLEAN else PROMPT_END=$PROMPT_END_DIRTY fi - # Save history - _save-and-reload-history 1 PS1="($(clock_prompt)) $(scm_char) [${blue}\u${reset_color}@${green}\H${reset_color}] ${yellow}\w${reset_color}$(scm_prompt_info) ${reset_color}\n$(prompt_end) " PS2='> ' PS4='+ ' diff --git a/themes/nwinkler_random_colors/nwinkler_random_colors.theme.bash b/themes/nwinkler_random_colors/nwinkler_random_colors.theme.bash index 05391b0b7b..16c79448c8 100644 --- a/themes/nwinkler_random_colors/nwinkler_random_colors.theme.bash +++ b/themes/nwinkler_random_colors/nwinkler_random_colors.theme.bash @@ -95,13 +95,23 @@ prompt_setter() { if [[ $exit_status -eq 0 ]]; then PROMPT_END=$PROMPT_END_CLEAN else PROMPT_END=$PROMPT_END_DIRTY fi - # Save history - _save-and-reload-history 1 PS1="($(clock_prompt)${reset_color}) $(scm_char) [${USERNAME_COLOR}\u${reset_color}@${HOSTNAME_COLOR}\H${reset_color}] ${PATH_COLOR}\w${reset_color}$(scm_prompt_info) ${reset_color}\n$(prompt_end) " PS2='> ' PS4='+ ' } +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + safe_append_prompt_command prompt_setter SCM_THEME_PROMPT_DIRTY=" ${bold_red}✗${normal}" diff --git a/themes/pete/pete.theme.bash b/themes/pete/pete.theme.bash index e55ad6ebc1..85947d564b 100644 --- a/themes/pete/pete.theme.bash +++ b/themes/pete/pete.theme.bash @@ -7,12 +7,20 @@ function prompt_setter() { scm_char="$(scm_char)" scm_prompt_info="$(scm_prompt_info)" ruby_version_prompt="$(ruby_version_prompt)" - _save-and-reload-history 1 # Save history PS1="(${clock_prompt}) ${scm_char} [${blue?}\u${reset_color?}@${green?}\H${reset_color?}] ${yellow?}\w${reset_color?}${scm_prompt_info}${ruby_version_prompt} ${reset_color?} " PS2='> ' PS4='+ ' } +case $HISTCONTROL in + *'auto'*) + : # Do nothing, already configured. + ;; + *) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac safe_append_prompt_command prompt_setter SCM_THEME_PROMPT_DIRTY=" ✗" diff --git a/themes/powerline-plain/powerline-plain.base.bash b/themes/powerline-plain/powerline-plain.base.bash index ce91ef899c..60aa27ae71 100644 --- a/themes/powerline-plain/powerline-plain.base.bash +++ b/themes/powerline-plain/powerline-plain.base.bash @@ -1,5 +1,18 @@ +# shellcheck shell=bash . "$BASH_IT/themes/powerline/powerline.base.bash" +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + function __powerline_left_segment { local OLD_IFS="${IFS}"; IFS="|" local params=( $1 ) @@ -34,8 +47,6 @@ function __powerline_prompt_command { LAST_SEGMENT_COLOR="" PROMPT_AFTER="${POWERLINE_PROMPT_AFTER}" - _save-and-reload-history "${HISTORY_AUTOSAVE:-0}" - ## left prompt ## for segment in $POWERLINE_PROMPT; do local info="$(__powerline_${segment}_prompt)" diff --git a/themes/rainbowbrite/rainbowbrite.theme.bash b/themes/rainbowbrite/rainbowbrite.theme.bash index 07e5843fcf..826baf002e 100644 --- a/themes/rainbowbrite/rainbowbrite.theme.bash +++ b/themes/rainbowbrite/rainbowbrite.theme.bash @@ -5,9 +5,19 @@ # ± ~/path/to (branch ✓) $ # in glorious red / blue / yellow color scheme +case $HISTCONTROL in +*'auto'*) + : # Do nothing, already configured. + ;; +*) + # Append new history lines to history file + HISTCONTROL="${HISTCONTROL:-}${HISTCONTROL:+:}autosave" + ;; +esac +safe_append_preexec '_bash-it-history-auto-load' +safe_append_prompt_command '_bash-it-history-auto-save' + prompt_setter() { - # Save history - _save-and-reload-history 1 # displays user@server in purple # PS1="$red$(scm_char) $purple\u@\h$reset_color:$blue\w$yellow$(scm_prompt_info)$(ruby_version_prompt) $black\$$reset_color " # no user@server