Jafner.net/dotfiles/vscode/shellinit.sh
Joey Hafner 27cf692572
Clean up dotfiles
- Move shell profiles to shell folder
- Add `ffconvert` and `zipline` functions
- Delete configuration files for tools I don't use
2024-09-04 13:06:03 -07:00

335 lines
9.5 KiB
Bash

# ---------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# ---------------------------------------------------------------------------------------------
# Prevent the script recursing when setting up
if [[ -n "${VSCODE_SHELL_INTEGRATION:-}" ]]; then
builtin return
fi
VSCODE_SHELL_INTEGRATION=1
# Run relevant rc/profile only if shell integration has been injected, not when run manually
if [ "$VSCODE_INJECTION" == "1" ]; then
if [ -z "$VSCODE_SHELL_LOGIN" ]; then
if [ -r ~/.bashrc ]; then
. ~/.bashrc
fi
else
# Imitate -l because --init-file doesn't support it:
# run the first of these files that exists
if [ -r /etc/profile ]; then
. /etc/profile
fi
# execute the first that exists
if [ -r ~/.bash_profile ]; then
. ~/.bash_profile
elif [ -r ~/.bash_login ]; then
. ~/.bash_login
elif [ -r ~/.profile ]; then
. ~/.profile
fi
builtin unset VSCODE_SHELL_LOGIN
# Apply any explicit path prefix (see #99878)
if [ -n "${VSCODE_PATH_PREFIX:-}" ]; then
export PATH=$VSCODE_PATH_PREFIX$PATH
builtin unset VSCODE_PATH_PREFIX
fi
fi
builtin unset VSCODE_INJECTION
fi
if [ -z "$VSCODE_SHELL_INTEGRATION" ]; then
builtin return
fi
# Apply EnvironmentVariableCollections if needed
if [ -n "${VSCODE_ENV_REPLACE:-}" ]; then
IFS=':' read -ra ADDR <<< "$VSCODE_ENV_REPLACE"
for ITEM in "${ADDR[@]}"; do
VARNAME="$(echo $ITEM | cut -d "=" -f 1)"
VALUE="$(echo -e "$ITEM" | cut -d "=" -f 2-)"
export $VARNAME="$VALUE"
done
builtin unset VSCODE_ENV_REPLACE
fi
if [ -n "${VSCODE_ENV_PREPEND:-}" ]; then
IFS=':' read -ra ADDR <<< "$VSCODE_ENV_PREPEND"
for ITEM in "${ADDR[@]}"; do
VARNAME="$(echo $ITEM | cut -d "=" -f 1)"
VALUE="$(echo -e "$ITEM" | cut -d "=" -f 2-)"
export $VARNAME="$VALUE${!VARNAME}"
done
builtin unset VSCODE_ENV_PREPEND
fi
if [ -n "${VSCODE_ENV_APPEND:-}" ]; then
IFS=':' read -ra ADDR <<< "$VSCODE_ENV_APPEND"
for ITEM in "${ADDR[@]}"; do
VARNAME="$(echo $ITEM | cut -d "=" -f 1)"
VALUE="$(echo -e "$ITEM" | cut -d "=" -f 2-)"
export $VARNAME="${!VARNAME}$VALUE"
done
builtin unset VSCODE_ENV_APPEND
fi
__vsc_get_trap() {
# 'trap -p DEBUG' outputs a shell command like `trap -- '…shellcode…' DEBUG`.
# The terms are quoted literals, but are not guaranteed to be on a single line.
# (Consider a trap like $'echo foo\necho \'bar\'').
# To parse, we splice those terms into an expression capturing them into an array.
# This preserves the quoting of those terms: when we `eval` that expression, they are preserved exactly.
# This is different than simply exploding the string, which would split everything on IFS, oblivious to quoting.
builtin local -a terms
builtin eval "terms=( $(trap -p "${1:-DEBUG}") )"
# |________________________|
# |
# \-------------------*--------------------/
# terms=( trap -- '…arbitrary shellcode…' DEBUG )
# |____||__| |_____________________| |_____|
# | | | |
# 0 1 2 3
# |
# \--------*----/
builtin printf '%s' "${terms[2]:-}"
}
__vsc_escape_value_fast() {
builtin local LC_ALL=C out
out=${1//\\/\\\\}
out=${out//;/\\x3b}
builtin printf '%s\n' "${out}"
}
# The property (P) and command (E) codes embed values which require escaping.
# Backslashes are doubled. Non-alphanumeric characters are converted to escaped hex.
__vsc_escape_value() {
# If the input being too large, switch to the faster function
if [ "${#1}" -ge 2000 ]; then
__vsc_escape_value_fast "$1"
builtin return
fi
# Process text byte by byte, not by codepoint.
builtin local LC_ALL=C str="${1}" i byte token out=''
for (( i=0; i < "${#str}"; ++i )); do
byte="${str:$i:1}"
# Escape backslashes, semi-colons specially, then special ASCII chars below space (0x20)
if [ "$byte" = "\\" ]; then
token="\\\\"
elif [ "$byte" = ";" ]; then
token="\\x3b"
elif (( $(builtin printf '%d' "'$byte") < 31 )); then
token=$(builtin printf '\\x%02x' "'$byte")
else
token="$byte"
fi
out+="$token"
done
builtin printf '%s\n' "${out}"
}
# Send the IsWindows property if the environment looks like Windows
if [[ "$(uname -s)" =~ ^CYGWIN*|MINGW*|MSYS* ]]; then
builtin printf '\e]633;P;IsWindows=True\a'
__vsc_is_windows=1
else
__vsc_is_windows=0
fi
# Allow verifying $BASH_COMMAND doesn't have aliases resolved via history when the right HISTCONTROL
# configuration is used
if [[ "$HISTCONTROL" =~ .*(erasedups|ignoreboth|ignoredups).* ]]; then
__vsc_history_verify=0
else
__vsc_history_verify=1
fi
__vsc_initialized=0
__vsc_original_PS1="$PS1"
__vsc_original_PS2="$PS2"
__vsc_custom_PS1=""
__vsc_custom_PS2=""
__vsc_in_command_execution="1"
__vsc_current_command=""
# It's fine this is in the global scope as it getting at it requires access to the shell environment
__vsc_nonce="$VSCODE_NONCE"
unset VSCODE_NONCE
# Report continuation prompt
builtin printf "\e]633;P;ContinuationPrompt=$(echo "$PS2" | sed 's/\x1b/\\\\x1b/g')\a"
__vsc_report_prompt() {
# Expand the original PS1 similarly to how bash would normally
# See https://stackoverflow.com/a/37137981 for technique
if ((BASH_VERSINFO[0] >= 5 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4))); then
__vsc_prompt=${__vsc_original_PS1@P}
else
__vsc_prompt=${__vsc_original_PS1}
fi
__vsc_prompt="$(builtin printf "%s" "${__vsc_prompt//[$'\001'$'\002']}")"
builtin printf "\e]633;P;Prompt=%s\a" "$(__vsc_escape_value "${__vsc_prompt}")"
}
__vsc_prompt_start() {
builtin printf '\e]633;A\a'
}
__vsc_prompt_end() {
builtin printf '\e]633;B\a'
}
__vsc_update_cwd() {
if [ "$__vsc_is_windows" = "1" ]; then
__vsc_cwd="$(cygpath -m "$PWD")"
else
__vsc_cwd="$PWD"
fi
builtin printf '\e]633;P;Cwd=%s\a' "$(__vsc_escape_value "$__vsc_cwd")"
}
__vsc_command_output_start() {
if [[ -z "$__vsc_first_prompt" ]]; then
builtin return
fi
builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce
builtin printf '\e]633;C\a'
}
__vsc_continuation_start() {
builtin printf '\e]633;F\a'
}
__vsc_continuation_end() {
builtin printf '\e]633;G\a'
}
__vsc_command_complete() {
if [[ -z "$__vsc_first_prompt" ]]; then
builtin return
fi
if [ "$__vsc_current_command" = "" ]; then
builtin printf '\e]633;D\a'
else
builtin printf '\e]633;D;%s\a' "$__vsc_status"
fi
__vsc_update_cwd
}
__vsc_update_prompt() {
# in command execution
if [ "$__vsc_in_command_execution" = "1" ]; then
# Wrap the prompt if it is not yet wrapped, if the PS1 changed this this was last set it
# means the user re-exported the PS1 so we should re-wrap it
if [[ "$__vsc_custom_PS1" == "" || "$__vsc_custom_PS1" != "$PS1" ]]; then
__vsc_original_PS1=$PS1
__vsc_custom_PS1="\[$(__vsc_prompt_start)\]$__vsc_original_PS1\[$(__vsc_prompt_end)\]"
PS1="$__vsc_custom_PS1"
fi
if [[ "$__vsc_custom_PS2" == "" || "$__vsc_custom_PS2" != "$PS2" ]]; then
__vsc_original_PS2=$PS2
__vsc_custom_PS2="\[$(__vsc_continuation_start)\]$__vsc_original_PS2\[$(__vsc_continuation_end)\]"
PS2="$__vsc_custom_PS2"
fi
__vsc_in_command_execution="0"
fi
}
__vsc_precmd() {
__vsc_command_complete "$__vsc_status"
__vsc_current_command=""
__vsc_report_prompt
__vsc_first_prompt=1
__vsc_update_prompt
}
__vsc_preexec() {
__vsc_initialized=1
if [[ ! $BASH_COMMAND == __vsc_prompt* ]]; then
# Use history if it's available to verify the command as BASH_COMMAND comes in with aliases
# resolved
if [ "$__vsc_history_verify" = "1" ]; then
__vsc_current_command="$(builtin history 1 | sed 's/ *[0-9]* *//')"
else
__vsc_current_command=$BASH_COMMAND
fi
else
__vsc_current_command=""
fi
__vsc_command_output_start
}
# Debug trapping/preexec inspired by starship (ISC)
if [[ -n "${bash_preexec_imported:-}" ]]; then
__vsc_preexec_only() {
if [ "$__vsc_in_command_execution" = "0" ]; then
__vsc_in_command_execution="1"
__vsc_preexec
fi
}
precmd_functions+=(__vsc_prompt_cmd)
preexec_functions+=(__vsc_preexec_only)
else
__vsc_dbg_trap="$(__vsc_get_trap DEBUG)"
if [[ -z "$__vsc_dbg_trap" ]]; then
__vsc_preexec_only() {
if [ "$__vsc_in_command_execution" = "0" ]; then
__vsc_in_command_execution="1"
__vsc_preexec
fi
}
trap '__vsc_preexec_only "$_"' DEBUG
elif [[ "$__vsc_dbg_trap" != '__vsc_preexec "$_"' && "$__vsc_dbg_trap" != '__vsc_preexec_all "$_"' ]]; then
__vsc_preexec_all() {
if [ "$__vsc_in_command_execution" = "0" ]; then
__vsc_in_command_execution="1"
__vsc_preexec
builtin eval "${__vsc_dbg_trap}"
fi
}
trap '__vsc_preexec_all "$_"' DEBUG
fi
fi
__vsc_update_prompt
__vsc_restore_exit_code() {
return "$1"
}
__vsc_prompt_cmd_original() {
__vsc_status="$?"
__vsc_restore_exit_code "${__vsc_status}"
# Evaluate the original PROMPT_COMMAND similarly to how bash would normally
# See https://unix.stackexchange.com/a/672843 for technique
local cmd
for cmd in "${__vsc_original_prompt_command[@]}"; do
eval "${cmd:-}"
done
__vsc_precmd
}
__vsc_prompt_cmd() {
__vsc_status="$?"
__vsc_precmd
}
# PROMPT_COMMAND arrays and strings seem to be handled the same (handling only the first entry of
# the array?)
__vsc_original_prompt_command=${PROMPT_COMMAND:-}
if [[ -z "${bash_preexec_imported:-}" ]]; then
if [[ -n "${__vsc_original_prompt_command:-}" && "${__vsc_original_prompt_command:-}" != "__vsc_prompt_cmd" ]]; then
PROMPT_COMMAND=__vsc_prompt_cmd_original
else
PROMPT_COMMAND=__vsc_prompt_cmd
fi
fi