#!/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 ` 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-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} } # Wrapper for resh-cli for calling resh directly resh() { 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 "$@" return $? fi local buffer local git_remote; git_remote="$(git remote get-url origin 2>/dev/null)" buffer=$(resh-cli -requireVersion "$__RESH_VERSION" \ --git-origin-remote "$git_remote" \ --pwd "$PWD" \ --session-id "$__RESH_SESSION_ID" \ "$@" ) status_code=$? if [ $status_code = 111 ]; then # execute echo "$buffer" eval "$buffer" elif [ $status_code = 0 ]; then # paste echo "$buffer" elif [ $status_code = 130 ]; then true else printf "%s" "$buffer" >&2 fi } __resh_widget_control_R_compat() { __bindfunc_compat_wrapper __resh_widget_control_R } __resh_nop() { # does nothing true } # shellcheck source=../submodules/bash-zsh-compat-widgets/bindfunc.sh . ~/.resh/bindfunc.sh __resh_bind_control_R() { bindfunc '\C-r' __resh_widget_control_R_compat if [ -n "${BASH_VERSION-}" ]; then # fuck bash bind '"\C-r": "\u[31~\u[32~"' bind -x '"\u[31~": __resh_widget_control_R_compat' # execute # bind '"\u[32~": accept-line' # just paste # bind -x '"\u[32~": __resh_nop' true fi return 0 }