Skip to content

Instantly share code, notes, and snippets.

@gagata
Created February 23, 2022 21:51
Show Gist options
  • Save gagata/d9b48d8c3037e8a57abbd87f3b534155 to your computer and use it in GitHub Desktop.
Save gagata/d9b48d8c3037e8a57abbd87f3b534155 to your computer and use it in GitHub Desktop.
warp_escape_ps1 () {
tr '\n\n' ' ' <<< "$*" | xxd -p | tr -d '\n'
}
# Format a string value according to JSON syntax - Adapted from https://github.com/lework/script.
warp_escape_json () {
# Explanation of the sed replacements (each command is separated by a `;`):
# s/(["\\])/\\\1/g - Replace all double-quote (") and backslash (\) characters with the escaped versions (\" and \\)
# s/\b/\\b/g - Replace all backspace characters with \b
# s/\t/\\t/g - Replace all tab characters with \t
# s/\f/\\f/g - Replace all form feed characters with \f
# s/\r/\\r/g - Replace all carriage return characters with \r
# $!s/$/\\n/ - On every line except the last, insert the \n escape at the end of the line
# Note: sed acts line-by-line, so it doesn't see the literal newline characters to replace
#
# tr -d '\n' - Remove the literal newlines from the final output
#
# Additional note: In a shell script between single quotes ('), no escape sequences are interpreted.
# To work around that and insert the literal values into the regular expressions, we stop the single-quote,
# then add the literal using ANSI-C syntax ($'\t'), then start a new single-quote. That is the meaning
# behind the various `'$'\b''` blocks in the command. All of these separate strings are then concatenated
# together to form the full argument to send to sed.
sed -E 's/(["\\])/\\\1/g; s/'$'\b''/\\b/g; s/'$'\t''/\\t/g; s/'$'\f''/\\f/g; s/'$'\r''/\\r/g; $!s/$/\\n/' <<<"$*" | tr -d '\n'
}
warp_precmd () {
# $? is relative to the process so we MUST check this first
# or else the exit code will correspond to the commands
# executed within this block instead of the actual last
# command that was run.
local exit_code=$?
# Clear the prompt again before the command is rendered as it could
# have been reset by the user's bashrc or by setting the variable
# on the command line.
if [[ -n $PS1 ]]; then
WARP_PS1="$PS1"
fi
unset PS1
unset PROMPT
# Escaped PS1 variable
local escaped_ps1
if [[ $WARP_FEATURE_FLAG_HONOR_PS1 == "1" ]]; then
# Tricking the shell into rendering the prompt
# Note that in more modern versions of bash we could use ${PS1@P} to achieve the same,
# but macOs comes by default with a much older version of bash, and we want to be compatible.
deref_ps1=$(echo -e "\n" | PS1="$WARP_PS1" bash --norc -i 2>&1 | head -2 | tail -1)
escaped_ps1=$(warp_escape_ps1 "$(echo "$deref_ps1")")
fi
# Flush history
history -a
# Reset the custom kill-whole-line binding as the user's bashrc (which is sourced after bashrc_warp)
# could have added another bind. This won't have any user-impact because these shortcuts are only run
# in the context of the bash editor, which isn't displayed in Warp.
bind -r '"\C-p"'
bind "\C-p":kill-whole-line
local escaped_pwd
escaped_pwd=$(warp_escape_json "$PWD")
local escaped_virtual_env=""
if [ ! -z "$VIRTUAL_ENV" ]; then
escaped_virtual_env=$(warp_escape_json "$VIRTUAL_ENV")
fi
local escaped_conda_env=""
if [ ! -z "$CONDA_DEFAULT_ENV" ]; then
escaped_conda_env=$(warp_escape_json "$CONDA_DEFAULT_ENV")
fi
local git_branch
git_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
local escaped_git_branch
escaped_git_branch=$(warp_escape_json "$git_branch")
# At this point, escaped prompt looks something like
# \\u{001B}\\u{005B}\\u{0030}\\u{0031}\\u{003B} ...
# We need to maintain the double quoting of \\u in the message that
# is sent otherwise the receiving side will interpret the value
# as JS string literals of the form \uHEX, and will include
# ctrl characters (like ESC) in the json, which will cause a JSON
# parse error.
# Note WARP_SESSION_ID doesn't need to be escaped since it's a number
local escaped_json="{\"hook\": \"Precmd\", \"value\": {\"pwd\": \"$escaped_pwd\", \"ps1\": \"$escaped_ps1\", \"git_branch\": \"$escaped_git_branch\", \"virtual_env\": \"$escaped_virtual_env\", \"conda_env\": \"$escaped_conda_env\", \"exit_code\": $exit_code, \"session_id\": $WARP_SESSION_ID}}"
warp_send_message "$escaped_json"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment