Skip to content

Commit 177a6ea

Browse files
authored
Merge pull request microsoft#250873 from microsoft/tyriar/build
Revert bad change and add picker to sendSequence command
2 parents a76a1c4 + 7546740 commit 177a6ea

File tree

7 files changed

+89
-52
lines changed

7 files changed

+89
-52
lines changed

src/vs/workbench/contrib/terminal/browser/terminalActions.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -121,49 +121,48 @@ export async function getCwdForSplit(
121121
}
122122

123123
export const terminalSendSequenceCommand = async (accessor: ServicesAccessor, args: unknown) => {
124+
const quickInputService = accessor.get(IQuickInputService);
124125
const configurationResolverService = accessor.get(IConfigurationResolverService);
126+
const workspaceContextService = accessor.get(IWorkspaceContextService);
125127
const historyService = accessor.get(IHistoryService);
126-
const quickInputService = accessor.get(IQuickInputService);
127128
const terminalService = accessor.get(ITerminalService);
128-
const workspaceContextService = accessor.get(IWorkspaceContextService);
129129

130-
const instance = terminalService.activeInstance || await terminalService.getActiveOrCreateInstance();
131-
if (!instance) {
132-
return;
133-
}
134-
135-
let text = isObject(args) && 'text' in args ? toOptionalString(args.text) : undefined;
130+
const instance = terminalService.activeInstance;
131+
if (instance) {
132+
let text = isObject(args) && 'text' in args ? toOptionalString(args.text) : undefined;
136133

137-
// If no text provided, prompt user for input
138-
if (!text) {
139-
text = await quickInputService.input({
140-
value: '',
141-
placeHolder: 'Enter sequence to send (supports \\n, \\r, \\x escape sequences)',
142-
prompt: localize('workbench.action.terminal.sendSequence.prompt', "Enter sequence to send to the terminal"),
143-
});
134+
// If no text provided, prompt user for input and process special characters
144135
if (!text) {
145-
return;
146-
}
147-
}
148-
149-
// Process escape sequences
150-
let processedText = text
151-
.replace(/\\n/g, '\n')
152-
.replace(/\\r/g, '\r');
136+
text = await quickInputService.input({
137+
value: '',
138+
placeHolder: 'Enter sequence to send (supports \\n, \\r, \\x{AB})',
139+
prompt: localize('workbench.action.terminal.sendSequence.prompt', "Enter sequence to send to the terminal"),
140+
});
141+
if (!text) {
142+
return;
143+
}
144+
// Process escape sequences
145+
let processedText = text
146+
.replace(/\\n/g, '\n')
147+
.replace(/\\r/g, '\r');
148+
149+
// Process hex escape sequences (\xNN)
150+
while (true) {
151+
const match = processedText.match(/\\x([0-9a-fA-F]{2})/);
152+
if (match === null || match.index === undefined || match.length < 2) {
153+
break;
154+
}
155+
processedText = processedText.slice(0, match.index) + String.fromCharCode(parseInt(match[1], 16)) + processedText.slice(match.index + 4);
156+
}
153157

154-
// Process hex escape sequences (\xNN)
155-
while (true) {
156-
const match = processedText.match(/\\x([0-9a-fA-F]{2})/);
157-
if (match === null || match.index === undefined || match.length < 2) {
158-
break;
158+
text = processedText;
159159
}
160-
processedText = processedText.slice(0, match.index) + String.fromCharCode(parseInt(match[1], 16)) + processedText.slice(match.index + 4);
161-
}
162160

163-
const activeWorkspaceRootUri = historyService.getLastActiveWorkspaceRoot(instance.isRemote ? Schemas.vscodeRemote : Schemas.file);
164-
const lastActiveWorkspaceRoot = activeWorkspaceRootUri ? workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) ?? undefined : undefined;
165-
const resolvedText = await configurationResolverService.resolveAsync(lastActiveWorkspaceRoot, processedText);
166-
instance.sendText(resolvedText, false);
161+
const activeWorkspaceRootUri = historyService.getLastActiveWorkspaceRoot(instance.isRemote ? Schemas.vscodeRemote : Schemas.file);
162+
const lastActiveWorkspaceRoot = activeWorkspaceRootUri ? workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) ?? undefined : undefined;
163+
const resolvedText = await configurationResolverService.resolveAsync(lastActiveWorkspaceRoot, text);
164+
instance.sendText(resolvedText, false);
165+
}
167166
};
168167

169168
export const terminalSendSignalCommand = async (accessor: ServicesAccessor, args: unknown) => {
@@ -1043,6 +1042,7 @@ export function registerTerminalActions() {
10431042
name: 'args',
10441043
schema: {
10451044
type: 'object',
1045+
required: ['text'],
10461046
properties: {
10471047
text: {
10481048
description: localize('sendSequence', "The sequence of text to send to the terminal"),

src/vs/workbench/contrib/terminal/common/terminalStrings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const terminalStrings = {
3636
rename: localize2('workbench.action.terminal.rename', "Rename..."),
3737
toggleSizeToContentWidth: localize2('workbench.action.terminal.sizeToContentWidthInstance', "Toggle Size to Content Width"),
3838
focusHover: localize2('workbench.action.terminal.focusHover', "Focus Hover"),
39-
sendSequence: localize2('workbench.action.terminal.sendSequence', "Send Custom Sequence to Terminal"),
39+
sendSequence: localize2('workbench.action.terminal.sendSequence', "Send Sequence"),
4040
sendSignal: localize2('workbench.action.terminal.sendSignal', "Send Signal"),
4141
newWithCwd: localize2('workbench.action.terminal.newWithCwd', "Create New Terminal Starting in a Custom Working Directory"),
4242
renameWithArgs: localize2('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal"),

src/vs/workbench/contrib/terminalContrib/developer/browser/terminal.developer.contribution.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ import { IConfigurationService } from '../../../../../platform/configuration/com
1717
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
1818
import { IFileService } from '../../../../../platform/files/common/files.js';
1919
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
20+
import { IQuickInputService } from '../../../../../platform/quickinput/common/quickInput.js';
2021
import { ITerminalCommand, TerminalCapability } from '../../../../../platform/terminal/common/capabilities/capabilities.js';
2122
import { ITerminalLogService, TerminalSettingId } from '../../../../../platform/terminal/common/terminal.js';
2223
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
2324
import { IStatusbarService, StatusbarAlignment, type IStatusbarEntry } from '../../../../services/statusbar/browser/statusbar.js';
24-
import { ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
25+
import { IInternalXtermTerminal, ITerminalContribution, ITerminalInstance, IXtermTerminal } from '../../../terminal/browser/terminal.js';
2526
import { registerTerminalAction } from '../../../terminal/browser/terminalActions.js';
2627
import { registerTerminalContribution, type ITerminalContributionContext } from '../../../terminal/browser/terminalExtensions.js';
2728
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
@@ -60,6 +61,41 @@ registerTerminalAction({
6061
}
6162
});
6263

64+
registerTerminalAction({
65+
id: TerminalDeveloperCommandId.WriteDataToTerminal,
66+
title: localize2('workbench.action.terminal.writeDataToTerminal', 'Write Data to Terminal'),
67+
category: Categories.Developer,
68+
run: async (c, accessor) => {
69+
const quickInputService = accessor.get(IQuickInputService);
70+
const instance = await c.service.getActiveOrCreateInstance();
71+
await c.service.revealActiveTerminal();
72+
await instance.processReady;
73+
if (!instance.xterm) {
74+
throw new Error('Cannot write data to terminal if xterm isn\'t initialized');
75+
}
76+
const data = await quickInputService.input({
77+
value: '',
78+
placeHolder: 'Enter data, use \\x to escape',
79+
prompt: localize('workbench.action.terminal.writeDataToTerminal.prompt', "Enter data to write directly to the terminal, bypassing the pty"),
80+
});
81+
if (!data) {
82+
return;
83+
}
84+
let escapedData = data
85+
.replace(/\\n/g, '\n')
86+
.replace(/\\r/g, '\r');
87+
while (true) {
88+
const match = escapedData.match(/\\x([0-9a-fA-F]{2})/);
89+
if (match === null || match.index === undefined || match.length < 2) {
90+
break;
91+
}
92+
escapedData = escapedData.slice(0, match.index) + String.fromCharCode(parseInt(match[1], 16)) + escapedData.slice(match.index + 4);
93+
}
94+
const xterm = instance.xterm as any as IInternalXtermTerminal;
95+
xterm._writeText(escapedData);
96+
}
97+
});
98+
6399
registerTerminalAction({
64100
id: TerminalDeveloperCommandId.RecordSession,
65101
title: localize2('workbench.action.terminal.recordSession', 'Record Terminal Session'),

src/vs/workbench/contrib/terminalContrib/developer/common/terminal.developer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
export const enum TerminalDeveloperCommandId {
7+
WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal',
78
RecordSession = 'workbench.action.terminal.recordSession',
89
ShowTextureAtlas = 'workbench.action.terminal.showTextureAtlas',
910
RestartPtyHost = 'workbench.action.terminal.restartPtyHost',

test/automation/src/terminal.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export enum TerminalCommandIdWithValue {
4141
NewWithProfile = 'workbench.action.terminal.newWithProfile',
4242
SelectDefaultProfile = 'workbench.action.terminal.selectDefaultShell',
4343
AttachToSession = 'workbench.action.terminal.attachToSession',
44-
SendSequence = 'workbench.action.terminal.sendSequence'
44+
WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal'
4545
}
4646

4747
/**
@@ -156,7 +156,7 @@ export class Terminal {
156156
/**
157157
* Creates an empty terminal by opening a regular terminal and resetting its state such that it
158158
* essentially acts like an Pseudoterminal extension API-based terminal. This can then be paired
159-
* with `TerminalCommandIdWithValue.SendSequence` to make more reliable tests.
159+
* with `TerminalCommandIdWithValue.WriteDataToTerminal` to make more reliable tests.
160160
*/
161161
async createEmptyTerminal(expectedLocation?: 'editor' | 'panel'): Promise<void> {
162162
await this.createTerminal(expectedLocation);
@@ -167,11 +167,11 @@ export class Terminal {
167167
await this.waitForTerminalText(buffer => buffer.some(line => line.startsWith('initialized')));
168168

169169
// Erase all content and reset cursor to top
170-
await this.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${csi('2J')}${csi('H')}`);
170+
await this.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${csi('2J')}${csi('H')}`);
171171

172172
// Force windows pty mode off; assume all sequences are rendered in correct position
173173
if (process.platform === 'win32') {
174-
await this.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${vsc('P;IsWindows=False')}`);
174+
await this.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('P;IsWindows=False')}`);
175175
}
176176
}
177177

test/smoke/src/areas/terminal/terminal-shellIntegration.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,33 +98,33 @@ export function setup(options?: { skipSuite: boolean }) {
9898
// Use the simplest profile to get as little process interaction as possible
9999
await terminal.createEmptyTerminal();
100100
// Erase all content and reset cursor to top
101-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${csi('2J')}${csi('H')}`);
101+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${csi('2J')}${csi('H')}`);
102102
});
103103
describe('VS Code sequences', () => {
104104
it('should handle the simple case', async () => {
105-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${vsc('A')}Prompt> ${vsc('B')}exitcode 0`);
105+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 0`);
106106
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
107-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `\\r\\n${vsc('C')}Success\\r\\n${vsc('D;0')}`);
107+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Success\\r\\n${vsc('D;0')}`);
108108
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
109-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${vsc('A')}Prompt> ${vsc('B')}exitcode 1`);
109+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 1`);
110110
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
111-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `\\r\\n${vsc('C')}Failure\\r\\n${vsc('D;1')}`);
111+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Failure\\r\\n${vsc('D;1')}`);
112112
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
113-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${vsc('A')}Prompt> ${vsc('B')}`);
113+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}`);
114114
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
115115
});
116116
});
117117
describe('Final Term sequences', () => {
118118
it('should handle the simple case', async () => {
119-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${ft('A')}Prompt> ${ft('B')}exitcode 0`);
119+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 0`);
120120
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
121-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `\\r\\n${ft('C')}Success\\r\\n${ft('D;0')}`);
121+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Success\\r\\n${ft('D;0')}`);
122122
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
123-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
123+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
124124
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
125-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `\\r\\n${ft('C')}Failure\\r\\n${ft('D;1')}`);
125+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Failure\\r\\n${ft('D;1')}`);
126126
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
127-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
127+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
128128
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
129129
});
130130
});

test/smoke/src/areas/terminal/terminal-stickyScroll.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function setup(options?: { skipSuite: boolean }) {
3535
expectedLineCount: number = 1
3636
): Promise<void> {
3737
const data = generateCommandAndOutput(prompt, command, exitCode);
38-
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SendSequence, data);
38+
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, data);
3939
// Verify line count
4040
await app.code.waitForElements('.terminal-sticky-scroll .xterm-rows > *', true, e => e.length === expectedLineCount);
4141
// Verify content

0 commit comments

Comments
 (0)