Update the iTerm2 Bash integration script
This commit is contained in:
parent
9f5e2575ae
commit
bfa4edc910
224
.iterm2/shell_integration.bash
Executable file → Normal file
224
.iterm2/shell_integration.bash
Executable file → Normal file
|
@ -1,15 +1,39 @@
|
|||
#!/bin/bash
|
||||
# The iTerm2 customizations fall under the following license:
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
# -- BEGIN ITERM2 CUSTOMIZATIONS --
|
||||
if [[ "$TERM" != screen && "$ITERM_SHELL_INTEGRATION_INSTALLED" = "" && "$-" == *i* ]]; then
|
||||
if [[ "$ITERM_ENABLE_SHELL_INTEGRATION_WITH_TMUX""$TERM" != screen && "$ITERM_SHELL_INTEGRATION_INSTALLED" = "" && "$-" == *i* ]]; then
|
||||
|
||||
if shopt extdebug | grep on > /dev/null; then
|
||||
echo "iTerm2 Shell Integration not installed."
|
||||
echo ""
|
||||
echo "Your shell has 'extdebug' turned on."
|
||||
echo "This is incompatible with shell integration."
|
||||
echo "Find 'shopt -s extdebug' in bash's rc scripts and remove it."
|
||||
return 0
|
||||
fi
|
||||
|
||||
ITERM_SHELL_INTEGRATION_INSTALLED=Yes
|
||||
# Saved copy of your PS1. This is used to detect if the user changes PS1
|
||||
# directly. ITERM_PREV_PS1 will hold the last value that this script set PS1 to
|
||||
# (including various custom escape sequences).
|
||||
ITERM_PREV_PS1="$PS1"
|
||||
|
||||
# -- END ITERM2 CUSTOMIZATIONS --
|
||||
|
||||
# The following chunk of code, bash-preexec.sh, is licensed like this:
|
||||
# The MIT License
|
||||
#
|
||||
|
@ -33,6 +57,9 @@ ITERM_PREV_PS1="$PS1"
|
|||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
# Wrap bash-preexec.sh in a function so that, if it exits early due to having
|
||||
# been sourced elsewhere, it doesn't exit our entire script.
|
||||
_install_bash_preexec () {
|
||||
# -- BEGIN BASH-PREEXEC.SH --
|
||||
#!/bin/bash
|
||||
#
|
||||
|
@ -47,7 +74,22 @@ ITERM_PREV_PS1="$PS1"
|
|||
# Author: Ryan Caloras (ryan@bashhub.com)
|
||||
# Forked from Original Author: Glyph Lefkowitz
|
||||
#
|
||||
# V0.3.3
|
||||
# V0.3.7
|
||||
#
|
||||
# -- END ITERM2 CUSTOMIZATIONS --
|
||||
|
||||
# bash-preexec.sh -- Bash support for ZSH-like 'preexec' and 'precmd' functions.
|
||||
# https://github.com/rcaloras/bash-preexec
|
||||
#
|
||||
#
|
||||
# 'preexec' functions are executed before each interactive command is
|
||||
# executed, with the interactive command as its argument. The 'precmd'
|
||||
# function is executed before each prompt is displayed.
|
||||
#
|
||||
# Author: Ryan Caloras (ryan@bashhub.com)
|
||||
# Forked from Original Author: Glyph Lefkowitz
|
||||
#
|
||||
# V0.3.7
|
||||
#
|
||||
|
||||
# General Usage:
|
||||
|
@ -62,13 +104,13 @@ ITERM_PREV_PS1="$PS1"
|
|||
#
|
||||
# preexec_functions+=(my_preexec_function)
|
||||
#
|
||||
# 3. If you have anything that's using the Debug Trap, change it to use
|
||||
# preexec. (Optional) change anything using PROMPT_COMMAND to now use
|
||||
# precmd instead.
|
||||
# 3. Consider changing anything using the DEBUG trap or PROMPT_COMMAND
|
||||
# to use preexec and precmd instead. Preexisting usages will be
|
||||
# preserved, but doing so manually may be less surprising.
|
||||
#
|
||||
# Note: This module requires two bash features which you must not otherwise be
|
||||
# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. prexec_and_precmd_install
|
||||
# will override these and if you override one or the other this will most likely break.
|
||||
# Note: This module requires two Bash features which you must not otherwise be
|
||||
# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. If you override
|
||||
# either of these after bash-preexec has been installed it will most likely break.
|
||||
|
||||
# Avoid duplicate inclusion
|
||||
if [[ "$__bp_imported" == "defined" ]]; then
|
||||
|
@ -81,9 +123,19 @@ __bp_imported="defined"
|
|||
__bp_last_ret_value="$?"
|
||||
__bp_last_argument_prev_command="$_"
|
||||
|
||||
# Command to set our preexec trap. It's invoked once via
|
||||
# PROMPT_COMMAND and then removed.
|
||||
__bp_trap_install_string="trap '__bp_preexec_invoke_exec \"\$_\"' DEBUG;"
|
||||
__bp_inside_precmd=0
|
||||
__bp_inside_preexec=0
|
||||
|
||||
# Fails if any of the given variables are readonly
|
||||
# Reference https://stackoverflow.com/a/4441178
|
||||
__bp_require_not_readonly() {
|
||||
for var; do
|
||||
if ! ( unset "$var" 2> /dev/null ); then
|
||||
echo "iTerm2 Shell Integration: bash-preexec requires write access to ${var}" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Remove ignorespace and or replace ignoreboth from HISTCONTROL
|
||||
# so we can accurately invoke preexec with a command from our
|
||||
|
@ -123,11 +175,19 @@ __bp_interactive_mode() {
|
|||
# This function is installed as part of the PROMPT_COMMAND.
|
||||
# It will invoke any functions defined in the precmd_functions array.
|
||||
__bp_precmd_invoke_cmd() {
|
||||
|
||||
# Save the returned value from our last command
|
||||
# Save the returned value from our last command. Note: this MUST be the
|
||||
# first thing done in this function.
|
||||
__bp_last_ret_value="$?"
|
||||
|
||||
# For every function defined in our function array. Invoke it.
|
||||
# Don't invoke precmds if we are inside an execution of an "original
|
||||
# prompt command" by another precmd execution loop. This avoids infinite
|
||||
# recursion.
|
||||
if (( __bp_inside_precmd > 0 )); then
|
||||
return
|
||||
fi
|
||||
local __bp_inside_precmd=1
|
||||
|
||||
# Invoke every function defined in our function array.
|
||||
local precmd_function
|
||||
for precmd_function in "${precmd_functions[@]}"; do
|
||||
|
||||
|
@ -135,7 +195,8 @@ __bp_precmd_invoke_cmd() {
|
|||
# Test existence of functions with: declare -[Ff]
|
||||
if type -t "$precmd_function" 1>/dev/null; then
|
||||
__bp_set_ret_value "$__bp_last_ret_value" "$__bp_last_argument_prev_command"
|
||||
$precmd_function
|
||||
# Quote our function invocation to prevent issues with IFS
|
||||
"$precmd_function"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
@ -173,12 +234,16 @@ __bp_in_prompt_command() {
|
|||
# environment to attempt to detect if the current command is being invoked
|
||||
# interactively, and invoke 'preexec' if so.
|
||||
__bp_preexec_invoke_exec() {
|
||||
|
||||
|
||||
# Save the contents of $_ so that it can be restored later on.
|
||||
# https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702
|
||||
__bp_last_argument_prev_command="$1"
|
||||
|
||||
# Don't invoke preexecs if we are inside of another preexec.
|
||||
if (( __bp_inside_preexec > 0 )); then
|
||||
return
|
||||
fi
|
||||
local __bp_inside_preexec=1
|
||||
|
||||
# Checks if the file descriptor is not standard out (i.e. '1')
|
||||
# __bp_delay_install checks if we're in test. Needed for bats to run.
|
||||
# Prevents preexec from being invoked for functions in PS1
|
||||
|
@ -214,7 +279,7 @@ __bp_preexec_invoke_exec() {
|
|||
fi
|
||||
|
||||
local this_command
|
||||
this_command=$(HISTTIMEFORMAT= history 1 | { read -r _ this_command; echo "$this_command"; })
|
||||
this_command=$(HISTTIMEFORMAT= builtin history 1 | { IFS=" " read -r _ this_command; echo "$this_command"; })
|
||||
|
||||
# Sanity check to make sure we have something to invoke our function with.
|
||||
if [[ -z "$this_command" ]]; then
|
||||
|
@ -225,8 +290,9 @@ __bp_preexec_invoke_exec() {
|
|||
# the command is in fact interactive and we should invoke the user's
|
||||
# preexec functions.
|
||||
|
||||
# For every function defined in our function array. Invoke it.
|
||||
# Invoke every function defined in our function array.
|
||||
local preexec_function
|
||||
local preexec_function_ret_value
|
||||
local preexec_ret_value=0
|
||||
for preexec_function in "${preexec_functions[@]}"; do
|
||||
|
||||
|
@ -234,54 +300,42 @@ __bp_preexec_invoke_exec() {
|
|||
# Test existence of function with: declare -[fF]
|
||||
if type -t "$preexec_function" 1>/dev/null; then
|
||||
__bp_set_ret_value $__bp_last_ret_value
|
||||
$preexec_function "$this_command"
|
||||
preexec_ret_value="$?"
|
||||
# Quote our function invocation to prevent issues with IFS
|
||||
"$preexec_function" "$this_command"
|
||||
preexec_function_ret_value="$?"
|
||||
if [[ "$preexec_function_ret_value" != 0 ]]; then
|
||||
preexec_ret_value="$preexec_function_ret_value"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Restore the last argument of the last executed command
|
||||
# Also preserves the return value of the last function executed in preexec
|
||||
# If `extdebug` is enabled a non-zero return value from the last function
|
||||
# in prexec causes the command not to execute
|
||||
# Restore the last argument of the last executed command, and set the return
|
||||
# value of the DEBUG trap to be the return code of the last preexec function
|
||||
# to return an error.
|
||||
# If `extdebug` is enabled a non-zero return value from any preexec function
|
||||
# will cause the user's command not to execute.
|
||||
# Run `shopt -s extdebug` to enable
|
||||
__bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command"
|
||||
}
|
||||
|
||||
# Returns PROMPT_COMMAND with a semicolon appended
|
||||
# if it doesn't already have one.
|
||||
__bp_prompt_command_with_semi_colon() {
|
||||
|
||||
# Trim our existing PROMPT_COMMAND
|
||||
local trimmed
|
||||
trimmed=$(__bp_trim_whitespace "$PROMPT_COMMAND")
|
||||
|
||||
# Take our existing prompt command and append a semicolon to it
|
||||
# if it doesn't already have one.
|
||||
local existing_prompt_command
|
||||
if [[ -n "$trimmed" ]]; then
|
||||
existing_prompt_command=${trimmed%${trimmed##*[![:space:]]}}
|
||||
existing_prompt_command=${existing_prompt_command%;}
|
||||
existing_prompt_command=${existing_prompt_command/%/;}
|
||||
else
|
||||
existing_prompt_command=""
|
||||
fi
|
||||
|
||||
echo -n "$existing_prompt_command"
|
||||
}
|
||||
|
||||
__bp_install() {
|
||||
|
||||
# Remove setting our trap from PROMPT_COMMAND
|
||||
PROMPT_COMMAND="${PROMPT_COMMAND//$__bp_trap_install_string}"
|
||||
|
||||
# Remove this function from our PROMPT_COMMAND
|
||||
PROMPT_COMMAND="${PROMPT_COMMAND//__bp_install;}"
|
||||
|
||||
# Exit if we already have this installed.
|
||||
if [[ "$PROMPT_COMMAND" == *"__bp_precmd_invoke_cmd"* ]]; then
|
||||
return 1;
|
||||
fi
|
||||
|
||||
trap '__bp_preexec_invoke_exec "$_"' DEBUG
|
||||
|
||||
# Preserve any prior DEBUG trap as a preexec function
|
||||
local prior_trap=$(sed "s/[^']*'\(.*\)'[^']*/\1/" <<<"$__bp_trap_string")
|
||||
unset __bp_trap_string
|
||||
if [[ -n "$prior_trap" ]]; then
|
||||
eval '__bp_original_debug_trap() {
|
||||
'"$prior_trap"'
|
||||
}'
|
||||
preexec_functions+=(__bp_original_debug_trap)
|
||||
fi
|
||||
|
||||
# Adjust our HISTCONTROL Variable if needed.
|
||||
__bp_adjust_histcontrol
|
||||
|
||||
|
@ -297,28 +351,21 @@ __bp_install() {
|
|||
shopt -s extdebug > /dev/null 2>&1
|
||||
fi;
|
||||
|
||||
|
||||
local existing_prompt_command
|
||||
existing_prompt_command=$(__bp_prompt_command_with_semi_colon)
|
||||
|
||||
# Install our hooks in PROMPT_COMMAND to allow our trap to know when we've
|
||||
# actually entered something.
|
||||
PROMPT_COMMAND="__bp_precmd_invoke_cmd; ${existing_prompt_command} __bp_interactive_mode"
|
||||
eval "$__bp_trap_install_string"
|
||||
PROMPT_COMMAND="__bp_precmd_invoke_cmd; __bp_interactive_mode"
|
||||
|
||||
# Add two functions to our arrays for convenience
|
||||
# of definition.
|
||||
precmd_functions+=(precmd)
|
||||
preexec_functions+=(preexec)
|
||||
|
||||
# Since this is in PROMPT_COMMAND, invoke any precmd functions we have defined.
|
||||
__bp_precmd_invoke_cmd
|
||||
# Put us in interactive mode for our first command.
|
||||
__bp_interactive_mode
|
||||
# Since this function is invoked via PROMPT_COMMAND, re-execute PC now that it's properly set
|
||||
eval "$PROMPT_COMMAND"
|
||||
}
|
||||
|
||||
# Sets our trap and __bp_install as part of our PROMPT_COMMAND to install
|
||||
# after our session has started. This allows bash-preexec to be inlucded
|
||||
# after our session has started. This allows bash-preexec to be included
|
||||
# at any point in our bash profile. Ideally we could set our trap inside
|
||||
# __bp_install, but if a trap already exists it'll only set locally to
|
||||
# the function.
|
||||
|
@ -329,20 +376,35 @@ __bp_install_after_session_init() {
|
|||
return 1;
|
||||
fi
|
||||
|
||||
local existing_prompt_command
|
||||
existing_prompt_command=$(__bp_prompt_command_with_semi_colon)
|
||||
# bash-preexec needs to modify these variables in order to work correctly
|
||||
# if it can't, just stop the installation
|
||||
__bp_require_not_readonly PROMPT_COMMAND HISTCONTROL HISTTIMEFORMAT || return
|
||||
|
||||
# Add our installation to be done last via our PROMPT_COMMAND. These are
|
||||
# removed by __bp_install when it's invoked so it only runs once.
|
||||
PROMPT_COMMAND="${existing_prompt_command} $__bp_trap_install_string __bp_install;"
|
||||
# If there's an existing PROMPT_COMMAND capture it and convert it into a function
|
||||
# So it is preserved and invoked during precmd.
|
||||
if [[ -n "$PROMPT_COMMAND" ]]; then
|
||||
eval '__bp_original_prompt_command() {
|
||||
'"$PROMPT_COMMAND"'
|
||||
}'
|
||||
precmd_functions+=(__bp_original_prompt_command)
|
||||
fi
|
||||
|
||||
# Installation is finalized in PROMPT_COMMAND, which allows us to override the DEBUG
|
||||
# trap. __bp_install sets PROMPT_COMMAND to its final value, so these are only
|
||||
# invoked once.
|
||||
# It's necessary to clear any existing DEBUG trap in order to set it from the install function.
|
||||
# Using \n as it's the most universal delimiter of bash commands
|
||||
PROMPT_COMMAND=$'\n__bp_trap_string="$(trap -p DEBUG)"\ntrap DEBUG\n__bp_install\n'
|
||||
}
|
||||
|
||||
# Run our install so long as we're not delaying it.
|
||||
if [[ -z "$__bp_delay_install" ]]; then
|
||||
__bp_install_after_session_init
|
||||
fi;
|
||||
|
||||
# -- BEGIN BASH-PREEXEC.SH --
|
||||
# -- END BASH-PREEXEC.SH --
|
||||
}
|
||||
_install_bash_preexec
|
||||
unset -f _install_bash_preexec
|
||||
|
||||
# -- BEGIN ITERM2 CUSTOMIZATIONS --
|
||||
|
||||
|
@ -410,7 +472,7 @@ function iterm2_prompt_suffix() {
|
|||
|
||||
function iterm2_print_version_number() {
|
||||
iterm2_begin_osc
|
||||
printf "1337;ShellIntegrationVersion=8;shell=bash"
|
||||
printf "1337;ShellIntegrationVersion=12;shell=bash"
|
||||
iterm2_end_osc
|
||||
}
|
||||
|
||||
|
@ -490,6 +552,15 @@ function __iterm2_precmd () {
|
|||
export ITERM_ORIG_PS1="$PS1"
|
||||
fi
|
||||
|
||||
# If you want to generate PS1 dynamically from PROMPT_COMMAND, the best way
|
||||
# to do it is to define a function named iterm2_generate_ps1 that sets PS1.
|
||||
# Issue 5964. Other shells don't have this issue because they don't need
|
||||
# such extremes to get precmd and preexec.
|
||||
if [ -n "$(type -t iterm2_generate_ps1)" ] && [ "$(type -t iterm2_generate_ps1)" = function ]; then
|
||||
iterm2_generate_ps1
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$PS1" != "$ITERM_PREV_PS1" ]]
|
||||
then
|
||||
export ITERM_ORIG_PS1="$PS1"
|
||||
|
@ -522,8 +593,9 @@ function __iterm2_precmd () {
|
|||
preexec_functions+=(__iterm2_preexec)
|
||||
precmd_functions+=(__iterm2_precmd)
|
||||
|
||||
iterm2_print_state_data
|
||||
iterm2_print_version_number
|
||||
fi
|
||||
|
||||
# -- END ITERM2 CUSTOMIZATIONS --
|
||||
|
||||
alias imgcat=~/.iterm2/imgcat;alias imgls=~/.iterm2/imgls;alias it2attention=~/.iterm2/it2attention;alias it2check=~/.iterm2/it2check;alias it2copy=~/.iterm2/it2copy;alias it2dl=~/.iterm2/it2dl;alias it2getvar=~/.iterm2/it2getvar;alias it2setcolor=~/.iterm2/it2setcolor;alias it2setkeylabel=~/.iterm2/it2setkeylabel;alias it2ul=~/.iterm2/it2ul;alias it2universion=~/.iterm2/it2universion
|
||||
|
|
Loading…
Reference in a new issue