diff options
author | Marcus Tillmanns <[email protected]> | 2023-09-28 16:07:17 +0200 |
---|---|---|
committer | Marcus Tillmanns <[email protected]> | 2023-10-04 11:13:46 +0000 |
commit | 43f770b08778739f45fb2e25aec564acd3114669 (patch) | |
tree | 1134587c9d79d099c969b58ff5a434a28c569f7d /src/plugins/terminal/shellintegrations | |
parent | fc93f7d1b71c93b573660c7b59cb5b748ec4fc51 (diff) |
Terminal: Pull upstream shellintegration scripts
Change-Id: Ic0fed1a56ec635351716dca1e410050990d2dd98
Reviewed-by: <[email protected]>
Reviewed-by: Alessandro Portale <[email protected]>
Diffstat (limited to 'src/plugins/terminal/shellintegrations')
4 files changed, 187 insertions, 31 deletions
diff --git a/src/plugins/terminal/shellintegrations/shellintegration-bash.sh b/src/plugins/terminal/shellintegrations/shellintegration-bash.sh index 7db188be08e..d9792f34baa 100755 --- a/src/plugins/terminal/shellintegrations/shellintegration-bash.sh +++ b/src/plugins/terminal/shellintegrations/shellintegration-bash.sh @@ -3,7 +3,7 @@ # Prevent the script recursing when setting up -if [[ -n "$VSCODE_SHELL_INTEGRATION" ]]; then +if [[ -n "${VSCODE_SHELL_INTEGRATION:-}" ]]; then builtin return fi @@ -32,7 +32,7 @@ if [ "$VSCODE_INJECTION" == "1" ]; then builtin unset VSCODE_SHELL_LOGIN # Apply any explicit path prefix (see #99878) - if [ -n "$VSCODE_PATH_PREFIX" ]; then + if [ -n "${VSCODE_PATH_PREFIX:-}" ]; then export PATH=$VSCODE_PATH_PREFIX$PATH builtin unset VSCODE_PATH_PREFIX fi @@ -44,6 +44,35 @@ 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. @@ -110,6 +139,10 @@ __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 + __vsc_prompt_start() { builtin printf '\e]633;A\a' } @@ -124,7 +157,7 @@ __vsc_update_cwd() { __vsc_command_output_start() { builtin printf '\e]633;C\a' - builtin printf '\e]633;E;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" + builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce } __vsc_continuation_start() { @@ -241,10 +274,10 @@ __vsc_prompt_cmd() { # 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 +__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 + 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 diff --git a/src/plugins/terminal/shellintegrations/shellintegration-rc.zsh b/src/plugins/terminal/shellintegrations/shellintegration-rc.zsh index df4109131a9..119c85be9e0 100644 --- a/src/plugins/terminal/shellintegrations/shellintegration-rc.zsh +++ b/src/plugins/terminal/shellintegrations/shellintegration-rc.zsh @@ -37,6 +37,32 @@ 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%%=*})" + export $VARNAME="$(echo -e ${ITEM#*=})" + done + 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%%=*})" + export $VARNAME="$(echo -e ${ITEM#*=})${(P)VARNAME}" + done + 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%%=*})" + export $VARNAME="${(P)VARNAME}$(echo -e ${ITEM#*=})" + done + unset VSCODE_ENV_APPEND +fi + # 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() { @@ -66,6 +92,10 @@ __vsc_escape_value() { __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 + __vsc_prompt_start() { builtin printf '\e]633;A\a' } @@ -80,7 +110,7 @@ __vsc_update_cwd() { __vsc_command_output_start() { builtin printf '\e]633;C\a' - builtin printf '\e]633;E;%s\a' "${__vsc_current_command}" + builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce } __vsc_continuation_start() { @@ -149,6 +179,7 @@ __vsc_preexec() { RPROMPT="$__vsc_prior_rprompt" fi __vsc_in_command_execution="1" + # For some reason Qt Creator needs this to be $2 instead of $1 __vsc_current_command=$2 __vsc_command_output_start } diff --git a/src/plugins/terminal/shellintegrations/shellintegration.fish b/src/plugins/terminal/shellintegrations/shellintegration.fish index 7495bab3f40..21cc823c480 100644 --- a/src/plugins/terminal/shellintegrations/shellintegration.fish +++ b/src/plugins/terminal/shellintegrations/shellintegration.fish @@ -26,16 +26,48 @@ if status --is-login; and set -q VSCODE_PATH_PREFIX end set -e VSCODE_PATH_PREFIX +# Apply EnvironmentVariableCollections if needed +if test -n "$VSCODE_ENV_REPLACE" + set ITEMS (string split : $VSCODE_ENV_REPLACE) + for B in $ITEMS + set split (string split = $B) + set -gx "$split[1]" (echo -e "$split[2]") + end + set -e VSCODE_ENV_REPLACE +end +if test -n "$VSCODE_ENV_PREPEND" + set ITEMS (string split : $VSCODE_ENV_PREPEND) + for B in $ITEMS + set split (string split = $B) + set -gx "$split[1]" (echo -e "$split[2]")"$$split[1]" # avoid -p as it adds a space + end + set -e VSCODE_ENV_PREPEND +end +if test -n "$VSCODE_ENV_APPEND" + set ITEMS (string split : $VSCODE_ENV_APPEND) + for B in $ITEMS + set split (string split = $B) + set -gx "$split[1]" "$$split[1]"(echo -e "$split[2]") # avoid -a as it adds a space + end + set -e VSCODE_ENV_APPEND +end + +# Handle the shell integration nonce +if set -q VSCODE_NONCE + set -l __vsc_nonce $VSCODE_NONCE + set -e VSCODE_NONCE +end + # Helper function function __vsc_esc -d "Emit escape sequences for VS Code shell integration" - builtin printf "\e]633;%s\a" (string join ";" $argv) + builtin printf "\e]633;%s\a" (string join ";" -- $argv) end # Sent right before executing an interactive command. # Marks the beginning of command output. function __vsc_cmd_executed --on-event fish_preexec __vsc_esc C - __vsc_esc E (__vsc_escape_value "$argv") + __vsc_esc E (__vsc_escape_value "$argv") $__vsc_nonce # Creates a marker to indicate a command was run. set --global _vsc_has_cmd @@ -64,6 +96,31 @@ function __vsc_cmd_clear --on-event fish_cancel __vsc_esc D end +# Preserve the user's existing prompt, to wrap in our escape sequences. +function __preserve_fish_prompt --on-event fish_prompt + if functions --query fish_prompt + if functions --query __vsc_fish_prompt + # Erase the fallback so it can be set to the user's prompt + functions --erase __vsc_fish_prompt + end + functions --copy fish_prompt __vsc_fish_prompt + functions --erase __preserve_fish_prompt + # Now __vsc_fish_prompt is guaranteed to be defined + __init_vscode_shell_integration + else + if functions --query __vsc_fish_prompt + functions --erase __preserve_fish_prompt + __init_vscode_shell_integration + else + # There is no fish_prompt set, so stick with the default + # Now __vsc_fish_prompt is guaranteed to be defined + function __vsc_fish_prompt + echo -n (whoami)@(prompt_hostname) (prompt_pwd) '~> ' + end + end + end +end + # Sent whenever a new fish prompt is about to be displayed. # Updates the current working directory. function __vsc_update_cwd --on-event fish_prompt @@ -94,29 +151,29 @@ function __vsc_fish_has_mode_prompt -d "Returns true if fish_mode_prompt is defi functions fish_mode_prompt | string match -rvq '^ *(#|function |end$|$)' end -# Preserve the user's existing prompt, to wrap in our escape sequences. -functions --copy fish_prompt __vsc_fish_prompt - # Preserve and wrap fish_mode_prompt (which appears to the left of the regular # prompt), but only if it's not defined as an empty function (which is the # officially documented way to disable that feature). -if __vsc_fish_has_mode_prompt - functions --copy fish_mode_prompt __vsc_fish_mode_prompt - - function fish_mode_prompt - __vsc_fish_prompt_start - __vsc_fish_mode_prompt - end - - function fish_prompt - __vsc_fish_prompt - __vsc_fish_cmd_start - end -else - # No fish_mode_prompt, so put everything in fish_prompt. - function fish_prompt - __vsc_fish_prompt_start - __vsc_fish_prompt - __vsc_fish_cmd_start +function __init_vscode_shell_integration + if __vsc_fish_has_mode_prompt + functions --copy fish_mode_prompt __vsc_fish_mode_prompt + + function fish_mode_prompt + __vsc_fish_prompt_start + __vsc_fish_mode_prompt + __vsc_fish_cmd_start + end + + function fish_prompt + __vsc_fish_prompt + end + else + # No fish_mode_prompt, so put everything in fish_prompt. + function fish_prompt + __vsc_fish_prompt_start + __vsc_fish_prompt + __vsc_fish_cmd_start + end end end +__preserve_fish_prompt diff --git a/src/plugins/terminal/shellintegrations/shellintegration.ps1 b/src/plugins/terminal/shellintegrations/shellintegration.ps1 index 4fd978a8844..e277724b0a2 100644 --- a/src/plugins/terminal/shellintegrations/shellintegration.ps1 +++ b/src/plugins/terminal/shellintegrations/shellintegration.ps1 @@ -15,6 +15,35 @@ $Global:__VSCodeOriginalPrompt = $function:Prompt $Global:__LastHistoryId = -1 +# Store the nonce in script scope and unset the global +$Nonce = $env:VSCODE_NONCE +$env:VSCODE_NONCE = $null + +if ($env:VSCODE_ENV_REPLACE) { + $Split = $env:VSCODE_ENV_REPLACE.Split(":") + foreach ($Item in $Split) { + $Inner = $Item.Split('=') + [Environment]::SetEnvironmentVariable($Inner[0], $Inner[1].Replace('\x3a', ':')) + } + $env:VSCODE_ENV_REPLACE = $null +} +if ($env:VSCODE_ENV_PREPEND) { + $Split = $env:VSCODE_ENV_PREPEND.Split(":") + foreach ($Item in $Split) { + $Inner = $Item.Split('=') + [Environment]::SetEnvironmentVariable($Inner[0], $Inner[1].Replace('\x3a', ':') + [Environment]::GetEnvironmentVariable($Inner[0])) + } + $env:VSCODE_ENV_PREPEND = $null +} +if ($env:VSCODE_ENV_APPEND) { + $Split = $env:VSCODE_ENV_APPEND.Split(":") + foreach ($Item in $Split) { + $Inner = $Item.Split('=') + [Environment]::SetEnvironmentVariable($Inner[0], [Environment]::GetEnvironmentVariable($Inner[0]) + $Inner[1].Replace('\x3a', ':')) + } + $env:VSCODE_ENV_APPEND = $null +} + function Global:__VSCode-Escape-Value([string]$value) { # NOTE: In PowerShell v6.1+, this can be written `$value -replace '…', { … }` instead of `[regex]::Replace`. # Replace any non-alphanumeric characters. @@ -40,7 +69,7 @@ function Global:Prompt() { $Result += "$([char]0x1b)]633;D`a" } else { # Command finished command line - # OSC 633 ; A ; <CommandLine?> ST + # OSC 633 ; E ; <CommandLine?> ; <Nonce?> ST $Result = "$([char]0x1b)]633;E;" # Sanitize the command line to ensure it can get transferred to the terminal and can be parsed # correctly. This isn't entirely safe but good for most cases, it's important for the Pt parameter @@ -51,6 +80,7 @@ function Global:Prompt() { $CommandLine = "" } $Result += $(__VSCode-Escape-Value $CommandLine) + $Result += ";$Nonce" $Result += "`a" # Command finished exit code # OSC 633 ; D [; <ExitCode>] ST @@ -88,7 +118,12 @@ if (Get-Module -Name PSReadLine) { } # Set IsWindows property -[Console]::Write("$([char]0x1b)]633;P;IsWindows=$($IsWindows)`a") +if ($PSVersionTable.PSVersion -lt "6.0") { + # Windows PowerShell is only available on Windows + [Console]::Write("$([char]0x1b)]633;P;IsWindows=$true`a") +} else { + [Console]::Write("$([char]0x1b)]633;P;IsWindows=$IsWindows`a") +} # Set always on key handlers which map to default VS Code keybindings function Set-MappedKeyHandler { |