@@ -37,9 +37,47 @@ if [ -z "$VSCODE_SHELL_INTEGRATION" ]; then
37
37
builtin return
38
38
fi
39
39
40
+ # The property (P) and command (E) codes embed values which require escaping.
41
+ # Backslashes are doubled. Non-alphanumeric characters are converted to escaped hex.
42
+ __vsc_escape_value () {
43
+ # Process text byte by byte, not by codepoint.
44
+ builtin local LC_ALL=C str=" ${1} " i byte token out=' '
45
+
46
+ for (( i= 0 ; i < "${# str} "; ++ i )) ; do
47
+ byte=" ${str: $i : 1} "
48
+
49
+ # Backslashes must be doubled.
50
+ if [ " $byte " = " \\ " ]; then
51
+ token=" \\\\ "
52
+ # Conservatively pass alphanumerics through.
53
+ elif [[ " $byte " == [0-9A-Za-z] ]]; then
54
+ token=" $byte "
55
+ # Hex-encode anything else.
56
+ # (Importantly including: semicolon, newline, and control chars).
57
+ else
58
+ # The printf '0x%02X' "'$byte'" converts the character to a hex integer.
59
+ # See printf's specification:
60
+ # > If the leading character is a single-quote or double-quote, the value shall be the numeric value in the
61
+ # > underlying codeset of the character following the single-quote or double-quote.
62
+ # However, the result is a sign-extended int, so a high bit like 0xD7 becomes 0xFFF…FD7
63
+ # We mask that word with 0xFF to get lowest 8 bits, and then encode that byte as "\xD7" per our escaping scheme.
64
+ builtin printf -v token ' \\x%02X' " $(( $(builtin printf '0 x% X' "'$byte '") & 0xFF )) "
65
+ # |________| ^^^ ^^^ ^^^^^^ ^^^^^^^ |______|
66
+ # | | | | | |
67
+ # store in `token` -+ | | the hex value -----------+ | |
68
+ # the '\x…'-prefixed -----+ | of the byte as an integer --------+ |
69
+ # 0-padded, two hex digits --+ masked to one byte (due to sign extension) -+
70
+ fi
71
+
72
+ out+=" $token "
73
+ done
74
+
75
+ builtin printf ' %s\n' " ${out} "
76
+ }
77
+
40
78
# Send the IsWindows property if the environment looks like Windows
41
79
if [[ " $( uname -s) " =~ ^CYGWIN* | MINGW* | MSYS* ]]; then
42
- builtin printf " \x1b ]633;P;IsWindows=True\x07 "
80
+ builtin printf ' \e ]633;P;IsWindows=True\a '
43
81
fi
44
82
45
83
# Allow verifying $BASH_COMMAND doesn't have aliases resolved via history when the right HISTCONTROL
@@ -59,35 +97,35 @@ __vsc_in_command_execution="1"
59
97
__vsc_current_command=" "
60
98
61
99
__vsc_prompt_start () {
62
- builtin printf " \033 ]633;A\007 "
100
+ builtin printf ' \e ]633;A\a '
63
101
}
64
102
65
103
__vsc_prompt_end () {
66
- builtin printf " \033 ]633;B\007 "
104
+ builtin printf ' \e ]633;B\a '
67
105
}
68
106
69
107
__vsc_update_cwd () {
70
- builtin printf " \033 ]633;P;Cwd=%s\007 " " $PWD "
108
+ builtin printf ' \e ]633;P;Cwd=%s\a ' " $( __vsc_escape_value " $PWD " ) "
71
109
}
72
110
73
111
__vsc_command_output_start () {
74
- builtin printf " \033 ]633;C\007 "
75
- builtin printf " \033 ]633;E;%s\007 " " $__vsc_current_command "
112
+ builtin printf ' \e ]633;C\a '
113
+ builtin printf ' \e ]633;E;%s\a ' " $( __vsc_escape_value " ${ __vsc_current_command} " ) "
76
114
}
77
115
78
116
__vsc_continuation_start () {
79
- builtin printf " \033 ]633;F\007 "
117
+ builtin printf ' \e ]633;F\a '
80
118
}
81
119
82
120
__vsc_continuation_end () {
83
- builtin printf " \033 ]633;G\007 "
121
+ builtin printf ' \e ]633;G\a '
84
122
}
85
123
86
124
__vsc_command_complete () {
87
125
if [ " $__vsc_current_command " = " " ]; then
88
- builtin printf " \033 ]633;D\007 "
126
+ builtin printf ' \e ]633;D\a '
89
127
else
90
- builtin printf " \033 ]633;D;%s\007 " " $__vsc_status "
128
+ builtin printf ' \e ]633;D;%s\a ' " $__vsc_status "
91
129
fi
92
130
__vsc_update_cwd
93
131
}
0 commit comments