Always create DecorationAddon, synthetic data tests

This commit is contained in:
Daniel Imms 2022-06-20 10:30:41 -07:00
parent 980fc67973
commit d0ca1d2110
No known key found for this signature in database
GPG key ID: E5CF412B63651C69
5 changed files with 86 additions and 35 deletions

View file

@ -2135,10 +2135,12 @@ export function registerTerminalActions() {
if (!data) {
return;
}
let escapedData = data;
let escapedData = data
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r');
while (true) {
const match = escapedData.match(/\\x([0-9a-fA-F]{2})/);
if (!match?.index || match.length < 2) {
if (match === null || match.index === undefined || match.length < 2) {
break;
}
escapedData = escapedData.slice(0, match.index) + String.fromCharCode(parseInt(match[1], 16)) + escapedData.slice(match.index + 4);

View file

@ -194,6 +194,7 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
}
registerCommandDecoration(command: ITerminalCommand, beforeCommandExecution?: boolean): IDecoration | undefined {
console.log('registerCommandDecoration');
if (!this._terminal) {
return undefined;
}

View file

@ -61,7 +61,7 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, II
// Always on addons
private _commandNavigationAddon: CommandNavigationAddon;
private _shellIntegrationAddon: ShellIntegrationAddon;
private _decorationAddon: DecorationAddon | undefined;
private _decorationAddon: DecorationAddon;
// Optional addons
private _searchAddon?: SearchAddonType;
@ -155,17 +155,13 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, II
if (e.affectsConfiguration(TerminalSettingId.UnicodeVersion)) {
this._updateUnicodeVersion();
}
if (e.affectsConfiguration(TerminalSettingId.ShellIntegrationDecorationsEnabled) ||
e.affectsConfiguration(TerminalSettingId.ShellIntegrationEnabled)) {
this._updateShellIntegrationAddons();
}
}));
this.add(this._themeService.onDidColorThemeChange(theme => this._updateTheme(theme)));
this.add(this._viewDescriptorService.onDidChangeLocation(({ views }) => {
if (views.some(v => v.id === TERMINAL_VIEW_ID)) {
this._updateTheme();
this._decorationAddon?.refreshLayouts();
this._decorationAddon.refreshLayouts();
}
}));
@ -176,17 +172,16 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, II
this._updateUnicodeVersion();
this._commandNavigationAddon = this._instantiationService.createInstance(CommandNavigationAddon, _capabilities);
this.raw.loadAddon(this._commandNavigationAddon);
this._shellIntegrationAddon = this._instantiationService.createInstance(ShellIntegrationAddon, disableShellIntegrationReporting, this._telemetryService);
this.raw.loadAddon(this._shellIntegrationAddon);
this._updateShellIntegrationAddons();
}
private _createDecorationAddon(): void {
this._decorationAddon = this._instantiationService.createInstance(DecorationAddon, this._capabilities);
this._decorationAddon.onDidRequestRunCommand(e => this._onDidRequestRunCommand.fire(e));
this.raw.loadAddon(this._decorationAddon);
this._shellIntegrationAddon = this._instantiationService.createInstance(ShellIntegrationAddon, disableShellIntegrationReporting, this._telemetryService);
this.raw.loadAddon(this._shellIntegrationAddon);
}
// private _createDecorationAddon(): void {
// }
async getSelectionAsHtml(command?: ITerminalCommand): Promise<string> {
if (!this._serializeAddon) {
const Addon = await this._getSerializeAddonConstructor();
@ -612,24 +607,6 @@ export class XtermTerminal extends DisposableStore implements IXtermTerminal, II
}
}
private _updateShellIntegrationAddons(): void {
const shellIntegrationEnabled = this._configurationService.getValue(TerminalSettingId.ShellIntegrationEnabled);
const decorationsEnabled = this._configurationService.getValue(TerminalSettingId.ShellIntegrationDecorationsEnabled);
if (shellIntegrationEnabled) {
if (decorationsEnabled && !this._decorationAddon) {
this._createDecorationAddon();
} else if (this._decorationAddon && !decorationsEnabled) {
this._decorationAddon.dispose();
this._decorationAddon = undefined;
}
return;
}
if (this._decorationAddon) {
this._decorationAddon.dispose();
this._decorationAddon = undefined;
}
}
// eslint-disable-next-line @typescript-eslint/naming-convention
_writeText(data: string): void {
this.raw.write(data);

View file

@ -37,7 +37,8 @@ export enum TerminalCommandIdWithValue {
ChangeIcon = 'workbench.action.terminal.changeIcon',
NewWithProfile = 'workbench.action.terminal.newWithProfile',
SelectDefaultProfile = 'workbench.action.terminal.selectDefaultShell',
AttachToSession = 'workbench.action.terminal.attachToSession'
AttachToSession = 'workbench.action.terminal.attachToSession',
WriteDataToTerminal = 'workbench.action.terminal.writeDataToTerminal'
}
/**
@ -112,6 +113,9 @@ export class Terminal {
}
await this.code.dispatchKeybinding(altKey ? 'Alt+Enter' : 'enter');
await this.quickinput.waitForQuickInputClosed();
if (commandId === TerminalCommandIdWithValue.NewWithProfile) {
await this._waitForTerminal();
}
}
async runCommandInTerminal(commandText: string, skipEnter?: boolean): Promise<void> {

View file

@ -16,7 +16,6 @@ export function setup() {
app = this.app as Application;
terminal = app.workbench.terminal;
settingsEditor = app.workbench.settingsEditor;
await setTerminalTestSettings(app, [['terminal.integrated.shellIntegration.enabled', 'true']]);
});
afterEach(async function () {
@ -31,8 +30,15 @@ export function setup() {
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, process.platform === 'win32' ? 'PowerShell' : 'bash');
}
async function createSimpleProfile() {
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, process.platform === 'win32' ? 'Command Prompt' : 'sh');
}
// TODO: Some agents may not have pwsh installed?
(process.platform === 'win32' ? describe.skip : describe)(`Shell integration`, function () {
(process.platform === 'win32' ? describe.skip : describe)(`Process-based tests`, function () {
before(async function () {
await setTerminalTestSettings(app, [['terminal.integrated.shellIntegration.enabled', 'true']]);
});
describe('Decorations', function () {
describe('Should show default icons', function () {
@ -66,5 +72,66 @@ export function setup() {
});
});
});
describe('Write data-based tests', () => {
before(async function () {
await setTerminalTestSettings(app);
});
beforeEach(async function () {
// Create the simplest system profile to get as little process interaction as possible
await createSimpleProfile();
// Erase all content and reset cursor to top
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${csi('2J')}${csi('H')}`);
});
describe('VS Code sequences', () => {
it('should handle the simple case', async () => {
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 0`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Success\\r\\n${vsc('D;0')}`);
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 1`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Failure\\r\\n${vsc('D;1')}`);
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 1`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
});
});
// TODO: This depends on https://github.com/microsoft/vscode/issues/146587
describe.skip('Final Term sequences', () => {
it('should handle the simple case', async () => {
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 0`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Success\\r\\n${ft('D;0')}`);
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Failure\\r\\n${ft('D;1')}`);
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
});
});
});
});
}
function ft(data: string) {
return setTextParams(`133;${data}`);
}
function vsc(data: string) {
return setTextParams(`633;${data}`);
}
function setTextParams(data: string) {
return osc(`${data}\\x07`);
}
function osc(data: string) {
return `\\x1b]${data}`;
}
function csi(data: string) {
return `\\x1b[${data}`;
}