Skip to content

Commit 4ab88b8

Browse files
authored
Merge pull request microsoft#165631 from rwe/serialize-message-fish
shellIntegration.fish: escape values in "E" (executed command) and "P" (property KV) codes
2 parents f6f1d64 + 409c566 commit 4ab88b8

File tree

1 file changed

+23
-11
lines changed

1 file changed

+23
-11
lines changed

src/vs/workbench/contrib/terminal/browser/media/shellIntegration.fish

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,40 @@ set --global VSCODE_SHELL_INTEGRATION 1
2424

2525
# Helper function
2626
function __vsc_esc -d "Emit escape sequences for VS Code shell integration"
27-
builtin printf "\e]633;%s\007" (string join ";" $argv)
27+
builtin printf "\e]633;%s\a" (string join ";" $argv)
2828
end
2929

3030
# Sent right before executing an interactive command.
3131
# Marks the beginning of command output.
3232
function __vsc_cmd_executed --on-event fish_preexec
3333
__vsc_esc C
34-
__vsc_esc E (__vsc_escape_cmd "$argv")
34+
__vsc_esc E (__vsc_escape_value "$argv")
3535

3636
# Creates a marker to indicate a command was run.
3737
set --global _vsc_has_cmd
3838
end
3939

4040

41-
# Escapes backslashes, newlines, and semicolons to serialize the command line.
42-
function __vsc_escape_cmd
43-
set -l commandline "$argv"
44-
# `string replace` automatically breaks its input apart on any newlines.
45-
# Then `string join` at the end will bring it all back together.
46-
string replace --all '\\' '\\\\' $commandline \
47-
| string replace --all ';' '\x3b' \
48-
| string join '\x0a'
41+
# Escape a value for use in the 'P' ("Property") or 'E' ("Command Line") sequences.
42+
# Backslashes are doubled and non-alphanumeric characters are hex encoded.
43+
function __vsc_escape_value
44+
# Replace all non-alnum characters with %XX hex form.
45+
string escape --style=url "$argv" \
46+
# The characters [-./_~] are not encoded in the builtin url escaping, despite not being alphanumeric.
47+
# See: https://github.com/fish-shell/fish-shell/blob/f82537bcdcb32f85a530395f00e7be1aa9afc592/src/common.cpp#L738
48+
# For consistency, also encode those characters.
49+
| string replace --all '-' '%2D' \
50+
| string replace --all '.' '%2E' \
51+
| string replace --all '/' '%2F' \
52+
| string replace --all '_' '%5F' \
53+
| string replace --all '~' '%7E' \
54+
# Now everything is either alphanumeric [0-9A-Za-z] or %XX escapes.
55+
# Change the hex escape representation from '%' to '\x'. (e.g. ' ' → '%20' → '\x20').
56+
# Note that all '%' characters are escapes: literal '%' will already have been encoded.
57+
| string replace --all '%' '\\x' \
58+
# For readability, prefer to represent literal backslashes with doubling. ('\' → '%5C' → '\x5C' → '\\').
59+
| string replace --all --ignore-case '%5C' '\\\\' \
60+
;
4961
end
5062
5163
# Sent right after an interactive command has finished executing.
@@ -63,7 +75,7 @@ end
6375
# Sent whenever a new fish prompt is about to be displayed.
6476
# Updates the current working directory.
6577
function __vsc_update_cwd --on-event fish_prompt
66-
__vsc_esc P "Cwd=$PWD"
78+
__vsc_esc P "Cwd=$(__vsc_escape_value "$PWD")"
6779
6880
# If a command marker exists, remove it.
6981
# Otherwise, the commandline is empty and no command was run.

0 commit comments

Comments
 (0)