Skip to content

Commit c2c61be

Browse files
committed
Extract command line from buffer, send E before C
1 parent eff40ad commit c2c61be

File tree

10 files changed

+88
-23
lines changed

10 files changed

+88
-23
lines changed

src/vs/platform/terminal/common/capabilities/capabilities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ export interface ITerminalCommand extends IBaseTerminalCommand {
263263
readonly aliases?: string[][];
264264
readonly wasReplayed?: boolean;
265265

266+
extractCommandLine(): string;
266267
getOutput(): string | undefined;
267268
getOutputMatch(outputMatcher: ITerminalOutputMatcher): ITerminalOutputMatch | undefined;
268269
hasOutput(): boolean;

src/vs/platform/terminal/common/capabilities/commandDetection/terminalCommand.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ export class TerminalCommand implements ITerminalCommand {
113113
};
114114
}
115115

116+
extractCommandLine(): string {
117+
return extractCommandLine(this._xterm.buffer.active, this._xterm.cols, this.marker, this.startX, this.executedMarker, this.executedX);
118+
}
119+
116120
getOutput(): string | undefined {
117121
if (!this.executedMarker || !this.endMarker) {
118122
return undefined;
@@ -344,6 +348,10 @@ export class PartialTerminalCommand implements ICurrentPartialCommand {
344348
}
345349
}
346350

351+
extractCommandLine(): string {
352+
return extractCommandLine(this._xterm.buffer.active, this._xterm.cols, this.commandStartMarker, this.commandStartX, this.commandExecutedMarker, this.commandExecutedX);
353+
}
354+
347355
getPromptRowCount(): number {
348356
return getPromptRowCount(this, this._xterm.buffer.active);
349357
}
@@ -353,6 +361,27 @@ export class PartialTerminalCommand implements ICurrentPartialCommand {
353361
}
354362
}
355363

364+
function extractCommandLine(
365+
buffer: IBuffer,
366+
cols: number,
367+
commandStartMarker: IXtermMarker | undefined,
368+
commandStartX: number | undefined,
369+
commandExecutedMarker: IXtermMarker | undefined,
370+
commandExecutedX: number | undefined
371+
): string {
372+
if (!commandStartMarker || !commandExecutedMarker || commandStartX === undefined || commandExecutedX === undefined) {
373+
return '';
374+
}
375+
let content = '';
376+
for (let i = commandStartMarker.line; i <= commandExecutedMarker.line; i++) {
377+
const line = buffer.getLine(i);
378+
if (line) {
379+
content += line.translateToString(true, i === commandStartMarker.line ? commandStartX : 0, i === commandExecutedMarker.line ? commandExecutedX : cols);
380+
}
381+
}
382+
return content;
383+
}
384+
356385
function getXtermLineContent(buffer: IBuffer, lineStart: number, lineEnd: number, cols: number): string {
357386
// Cap the maximum number of lines generated to prevent potential performance problems. This is
358387
// more of a sanity check as the wrapped line should already be trimmed down at this point.

src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,42 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
8787
) {
8888
super();
8989

90-
this.onCommandExecuted(command => {
91-
// Pull command line from the buffer if it was not set explicitly
90+
// Pull command line from the buffer if it was not set explicitly
91+
this._register(this.onCommandExecuted(command => {
9292
if (command.commandLineConfidence !== 'high') {
93-
94-
console.log('commandLineConfidence !== high', command.command);
93+
// HACK: onCommandExecuted actually fired with PartialTerminalCommand
94+
const typedCommand = (command as ITerminalCommand | PartialTerminalCommand);
95+
command.command = typedCommand.extractCommandLine();
96+
command.commandLineConfidence = 'low';
97+
98+
// ITerminalCommand
99+
if ('getOutput' in typedCommand) {
100+
if (
101+
// Markers exist
102+
typedCommand.promptStartMarker && typedCommand.marker && typedCommand.executedMarker &&
103+
// Single line command
104+
command.command.indexOf('\n') === -1 &&
105+
// Start marker is not on the left-most column
106+
typedCommand.startX !== undefined && typedCommand.startX > 0
107+
) {
108+
command.commandLineConfidence = 'medium';
109+
}
110+
}
111+
// PartialTerminalCommand
112+
else {
113+
if (
114+
// Markers exist
115+
typedCommand.promptStartMarker && typedCommand.commandStartMarker && typedCommand.commandExecutedMarker &&
116+
// Single line command
117+
command.command.indexOf('\n') === -1 &&
118+
// Start marker is not on the left-most column
119+
typedCommand.commandStartX !== undefined && typedCommand.commandStartX > 0
120+
) {
121+
command.commandLineConfidence = 'medium';
122+
}
123+
}
95124
}
96-
});
125+
}));
97126

98127
// Set up platform-specific behaviors
99128
const that = this;

src/vs/workbench/api/browser/mainThreadTerminalShellIntegration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ export class MainThreadTerminalShellIntegration extends Disposable implements Ma
4747
}
4848
// String paths are not exposed in the extension API
4949
currentCommand = e.data;
50-
this._proxy.$shellExecutionStart(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), this._convertCwdToUri(e.data.cwd));
50+
this._proxy.$shellExecutionStart(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, this._convertCwdToUri(e.data.cwd));
5151
}));
5252

5353
// onDidEndTerminalShellExecution
5454
const commandDetectionEndEvent = this._store.add(this._terminalService.createOnInstanceCapabilityEvent(TerminalCapability.CommandDetection, e => e.onCommandFinished));
5555
this._store.add(commandDetectionEndEvent.event(e => {
5656
currentCommand = undefined;
57-
this._proxy.$shellExecutionEnd(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.exitCode);
57+
this._proxy.$shellExecutionEnd(e.instance.instanceId, e.data.command, convertToExtHostCommandLineConfidence(e.data), e.data.isTrusted, e.data.exitCode);
5858
}));
5959

6060
// onDidChangeTerminalShellIntegration via cwd

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,8 +2259,8 @@ export interface ExtHostTerminalServiceShape {
22592259

22602260
export interface ExtHostTerminalShellIntegrationShape {
22612261
$shellIntegrationChange(instanceId: number): void;
2262-
$shellExecutionStart(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, cwd: UriComponents | undefined): void;
2263-
$shellExecutionEnd(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, exitCode: number | undefined): void;
2262+
$shellExecutionStart(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, isTrusted: boolean, cwd: UriComponents | undefined): void;
2263+
$shellExecutionEnd(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, isTrusted: boolean, exitCode: number | undefined): void;
22642264
$shellExecutionData(instanceId: number, data: string): void;
22652265
$cwdChange(instanceId: number, cwd: UriComponents | undefined): void;
22662266
$closeTerminal(instanceId: number): void;

src/vs/workbench/api/common/extHostTerminalShellIntegration.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,23 +104,25 @@ export class ExtHostTerminalShellIntegration extends Disposable implements IExtH
104104
});
105105
}
106106

107-
public $shellExecutionStart(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, cwd: URI | undefined): void {
107+
public $shellExecutionStart(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, isTrusted: boolean, cwd: URI | undefined): void {
108108
// Force shellIntegration creation if it hasn't been created yet, this could when events
109109
// don't come through on startup
110110
if (!this._activeShellIntegrations.has(instanceId)) {
111111
this.$shellIntegrationChange(instanceId);
112112
}
113113
const commandLine: vscode.TerminalShellExecutionCommandLine = {
114114
value: commandLineValue,
115-
confidence: commandLineConfidence
115+
confidence: commandLineConfidence,
116+
isTrusted
116117
};
117118
this._activeShellIntegrations.get(instanceId)?.startShellExecution(commandLine, cwd);
118119
}
119120

120-
public $shellExecutionEnd(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, exitCode: number | undefined): void {
121+
public $shellExecutionEnd(instanceId: number, commandLineValue: string, commandLineConfidence: TerminalShellExecutionCommandLineConfidence, isTrusted: boolean, exitCode: number | undefined): void {
121122
const commandLine: vscode.TerminalShellExecutionCommandLine = {
122123
value: commandLineValue,
123-
confidence: commandLineConfidence
124+
confidence: commandLineConfidence,
125+
isTrusted
124126
};
125127
this._activeShellIntegrations.get(instanceId)?.endShellExecution(commandLine, exitCode);
126128
}
@@ -182,7 +184,8 @@ class InternalTerminalShellIntegration extends Disposable {
182184
// the start event fires
183185
const commandLine: vscode.TerminalShellExecutionCommandLine = {
184186
value: commandLineValue,
185-
confidence: TerminalShellExecutionCommandLineConfidence.High
187+
confidence: TerminalShellExecutionCommandLineConfidence.High,
188+
isTrusted: true
186189
};
187190
const execution = that.startShellExecution(commandLine, that._cwd, true).value;
188191
that._ignoreNextExecution = true;

src/vs/workbench/contrib/terminal/browser/media/fish_xdg_data/fish/vendor_conf.d/shellIntegration.fish

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ end
7575
# Sent right before executing an interactive command.
7676
# Marks the beginning of command output.
7777
function __vsc_cmd_executed --on-event fish_preexec
78-
__vsc_esc C
7978
__vsc_esc E (__vsc_escape_value "$argv") $__vsc_nonce
79+
__vsc_esc C
8080

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

src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ __vsc_update_cwd() {
172172
}
173173

174174
__vsc_command_output_start() {
175-
builtin printf '\e]633;C\a'
176175
builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce
176+
builtin printf '\e]633;C\a'
177177
}
178178

179179
__vsc_continuation_start() {

src/vs/workbench/contrib/terminal/browser/media/shellIntegration-rc.zsh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ __vsc_update_cwd() {
112112
}
113113

114114
__vsc_command_output_start() {
115-
builtin printf '\e]633;C\a'
116115
builtin printf '\e]633;E;%s;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")" $__vsc_nonce
116+
builtin printf '\e]633;C\a'
117117
}
118118

119119
__vsc_continuation_start() {

src/vscode-dts/vscode.proposed.terminalShellIntegration.d.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ declare module 'vscode' {
6363

6464
/**
6565
* Whether the command line value came from a trusted source and is therefore safe to
66-
* execute without user additional confirmation (eg. a notification "Do you want to execute
67-
* (command)?".
66+
* execute without user additional confirmation, such as a notification that asks "Do you
67+
* want to execute (command)?".
6868
*
6969
* This is false when the command line was reported explicitly by the shell integration
7070
* script (ie. {@link TerminalShellExecutionCommandLineConfidence.High high confidence}),
@@ -85,10 +85,13 @@ declare module 'vscode' {
8585
enum TerminalShellExecutionCommandLineConfidence {
8686
/**
8787
* The command line value confidence is low. This means that the value was read from the
88-
* terminal buffer using markers reported by the shell integration script. Additionally the
89-
* command either started on the very left-most column which is unusual, or the command is
90-
* multi-line which is more difficult to accurately detect due to line continuation
91-
* characters and right prompts.
88+
* terminal buffer using markers reported by the shell integration script. Additionally one
89+
* of the following conditions will be met:
90+
*
91+
* - The command started on the very left-most column which is unusual, or
92+
* - The command is multi-line which is more difficult to accurately detect due to line
93+
* continuation characters and right prompts.
94+
* - Command line markers were not reported by the shell integration script.
9295
*/
9396
Low = 0,
9497

0 commit comments

Comments
 (0)