Rich Enhanced Shell History - Contextual shell history for zsh and bash
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
resh/scripts/hooks.sh

160 lines
6.6 KiB

#!/hint/sh
# BACKWARDS COMPATIBILITY NOTES:
#
# Stable names and options:
# * `resh-collect -version` / `resh-postcollect -version` is used to detect version mismatch.
# => The go-like/short `-version` option needs to exist for new resh-(post)collect commands in all future version.
# => Prefer using go-like/short `-version` option so that we don't have more options to support indefinitely.
# * `__resh_preexec <CMDLINE>` with `__RESH_NO_RELOAD=1` is called on version mismatch.
# => The `__resh_preexec` function needs to exist in all future versions.
# => Make sure that `__RESH_NO_RELOAD` behavior is not broken in any future version.
# => Prefer only testing `__RESH_NO_RELOAD` for emptyness instead of specific value
# * `__resh_reload_msg` is called *after* shell files reload
# => The function shows a message from the already updated shell files
# => We can drop this function at any time - the old version will be used
# Backwards compatibilty: Please see notes above before making any changes here.
__resh_reload_msg() {
printf '\n'
printf '+--------------------------------------------------------------+\n'
printf '| New version of RESH shell files was loaded in this terminal. |\n'
printf '| This is an informative message - no action is necessary. |\n'
printf '| Please restart this terminal if you encounter any issues. |\n'
printf '+--------------------------------------------------------------+\n'
printf '\n'
}
# (pre)collect
# Backwards compatibilty: Please see notes above before making any changes here.
__resh_preexec() {
if [ "$(resh-collect -version)" != "$__RESH_VERSION" ] && [ -z "${__RESH_NO_RELOAD-}" ]; then
# Reload shell files and restart __resh_preexec - i.e. the full command will be recorded only with a slight delay.
# This should happens in every already open terminal after resh update.
# __RESH_NO_RELOAD prevents recursive reloads
# We never repeatadly reload the shell files to prevent potentially infinite recursion.
# If the version is still wrong then error will be raised by `resh-collect -requiredVersion`.
source ~/.resh/shellrc
# Show reload message from the updated shell files
__resh_reload_msg
# Rerun self but prevent another reload. Extra protection against infinite recursion.
__RESH_NO_RELOAD=1 __resh_preexec "$@"
return $?
fi
__RESH_COLLECT=1
__RESH_RECORD_ID=$(resh-generate-uuid)
# TODO: do this in resh-collect
# shellcheck disable=2155
local git_remote="$(git remote get-url origin 2>/dev/null)"
# TODO: do this in resh-collect
__RESH_RT_BEFORE=$(resh-get-epochtime)
resh-collect -requireVersion "$__RESH_VERSION" \
--git-remote "$git_remote" \
--home "$HOME" \
--pwd "$PWD" \
--record-id "$__RESH_RECORD_ID" \
--session-id "$__RESH_SESSION_ID" \
--session-pid "$$" \
--shell "$__RESH_SHELL" \
--shlvl "$SHLVL" \
--time "$__RESH_RT_BEFORE" \
--cmd-line "$1"
return $?
}
# postcollect
# Backwards compatibilty: Please see notes above before making any changes here.
__resh_precmd() {
# Get status first before it gets overriden by another command.
local exit_code=$?
# Don't do anything if __resh_preexec was not called.
# There are situations (in bash) where no command was submitted but __resh_precmd gets called anyway.
[ -n "${__RESH_COLLECT-}" ] || return
if [ "$(resh-postcollect -version)" != "$__RESH_VERSION" ]; then
# Reload shell files and return - i.e. skip recording part2 for this command.
# We don't call __resh_precmd because the new __resh_preexec might not be backwards compatible with variables set by old __resh_preexec.
# This should happen only in the one terminal where resh update was executed.
# And the resh-daemon was likely restarted so we likely don't even have the matching part1 of the comand in the resh-daemon memory.
source ~/.resh/shellrc
# Show reload message from the updated shell files
__resh_reload_msg
return
fi
unset __RESH_COLLECT
# do this in resh-postcollect
# shellcheck disable=2155
local rt_after=$(resh-get-epochtime)
resh-postcollect -requireVersion "$__RESH_VERSION" \
--exit-code "$exit_code" \
--record-id "$__RESH_RECORD_ID" \
--session-id "$__RESH_SESSION_ID" \
--shlvl "$SHLVL" \
--time-after "$rt_after" \
--time-before "$__RESH_RT_BEFORE"
return $?
}
# Backwards compatibilty: No restrictions. This is only used at the start of the session.
__resh_session_init() {
resh-session-init -requireVersion "$__RESH_VERSION" \
--session-id "$__RESH_SESSION_ID" \
--session-pid "$$"
return $?
}
# Backwards compatibilty: Please see notes above before making any changes here.
__resh_widget_control_R() {
# This is a very bad workaround.
# Force bash-preexec to run repeatedly because otherwise premature run of bash-preexec overshadows the next proper run.
# I honestly think that it's impossible to make widgets work in bash without hacks like this.
# shellcheck disable=2034
__bp_preexec_interactive_mode="on"
local PREVBUFFER=$BUFFER
local status_code
local git_remote; git_remote="$(git remote get-url origin 2>/dev/null)"
if [ "$(resh-cli -version)" != "$__RESH_VERSION" ] && [ -z "${__RESH_NO_RELOAD-}" ]; then
source ~/.resh/shellrc
# Show reload message from the updated shell files
__resh_reload_msg
# Rerun self but prevent another reload. Extra protection against infinite recursion.
__RESH_NO_RELOAD=1 __resh_widget_control_R "$@"
return $?
fi
BUFFER=$(resh-cli -requireVersion "$__RESH_VERSION" \
--git-origin-remote "$git_remote" \
--pwd "$PWD" \
--query "$BUFFER" \
--session-id "$__RESH_SESSION_ID" \
)
status_code=$?
if [ $status_code = 111 ]; then
# execute
if [ -n "${ZSH_VERSION-}" ]; then
# zsh
zle accept-line
elif [ -n "${BASH_VERSION-}" ]; then
# bash
# set chained keyseq to accept-line
bind '"\u[32~": accept-line'
fi
elif [ $status_code = 0 ]; then
if [ -n "${BASH_VERSION-}" ]; then
# bash
# set chained keyseq to nothing
bind -x '"\u[32~": __resh_nop'
fi
else
echo "RESH SEARCH APP failed"
printf "%s" "$buffer" >&2
BUFFER="$PREVBUFFER"
fi
CURSOR=${#BUFFER}
}
__resh_widget_control_R_compat() {
__bindfunc_compat_wrapper __resh_widget_control_R
}