aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/terminal/shellintegrations/shellintegration.fish
blob: 4592c2f1f38d17f96b512ce96c369a540350cd01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# Copyright (c) Microsoft Corporation. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Visual Studio Code terminal integration for fish
#
# Manual installation:
#
#   (1) Add the following to the end of `$__fish_config_dir/config.fish`:
#
#         string match -q "$TERM_PROGRAM" "vscode"
#         and . (code --locate-shell-integration-path fish)
#
#   (2) Restart fish.

# Don't run in scripts, other terminals, or more than once per session.
status is-interactive
and string match --quiet "$TERM_PROGRAM" "vscode"
and ! set --query VSCODE_SHELL_INTEGRATION
or exit

set --global VSCODE_SHELL_INTEGRATION 1

# Apply any explicit path prefix (see #99878)
if status --is-login; and set -q VSCODE_PATH_PREFIX
	fish_add_path -p $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)
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_nonce

	# Creates a marker to indicate a command was run.
	set --global _vsc_has_cmd
end


# Escape a value for use in the 'P' ("Property") or 'E' ("Command Line") sequences.
# Backslashes are doubled and non-alphanumeric characters are hex encoded.
function __vsc_escape_value
	# Escape backslashes and semi-colons
	echo $argv \
	| string replace --all '\\' '\\\\' \
	| string replace --all ';' '\\x3b' \
	;
end

# Sent right after an interactive command has finished executing.
# Marks the end of command output.
function __vsc_cmd_finished --on-event fish_postexec
	__vsc_esc D $status
end

# Sent when a command line is cleared or reset, but no command was run.
# Marks the cleared line with neither success nor failure.
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
	__vsc_esc P Cwd=(__vsc_escape_value "$PWD")

	# If a command marker exists, remove it.
	# Otherwise, the commandline is empty and no command was run.
	if set --query _vsc_has_cmd
		set --erase _vsc_has_cmd
	else
		__vsc_cmd_clear
	end
end

# Sent at the start of the prompt.
# Marks the beginning of the prompt (and, implicitly, a new line).
function __vsc_fish_prompt_start
	__vsc_esc A
end

# Sent at the end of the prompt.
# Marks the beginning of the user's command input.
function __vsc_fish_cmd_start
	__vsc_esc B
end

function __vsc_fish_has_mode_prompt -d "Returns true if fish_mode_prompt is defined and not empty"
	functions fish_mode_prompt | string match -rvq '^ *(#|function |end$|$)'
end

# 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).
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

if test -n "$QT_CREATOR_EXECUTABLE_PATH" -a -n "$QT_CREATOR_PID"
	function qtc
		# If we lost either of these env vars, return an error
		if test -z "$QT_CREATOR_EXECUTABLE_PATH" -o -z "$QT_CREATOR_PID"
			echo "qtc: QT_CREATOR_EXECUTABLE_PATH or QT_CREATOR_PID not set" >&2
			return 1
		end
		$QT_CREATOR_EXECUTABLE_PATH -client -pid $QT_CREATOR_PID $argv
	end
end

__preserve_fish_prompt