Consolidate ansi functions into strings.ts

This commit is contained in:
Daniel Imms
2024-04-26 07:22:16 -07:00
parent bc61f659dd
commit c398f717a9
7 changed files with 34 additions and 74 deletions

View File

@@ -953,8 +953,8 @@ function sanitizeData(data: string): string {
// Strip escape sequences so winpty/conpty doesn't cause flakiness, do for all platforms for
// consistency
const terminalCodesRegex = /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g;
data = data.replace(terminalCodesRegex, '');
const CSI_SEQUENCE = /(:?(:?\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~])|(:?\x1b\].*?\x07)/g;
data = data.replace(CSI_SEQUENCE, '');
return data;
}

View File

@@ -1,35 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Lazy } from 'vs/base/common/lazy';
const ansiEscapeSequenceRegex = new Lazy(() => /(?:\u001B|\u009B)[\[\]()#;?]*(?:(?:(?:[a-zA-Z0-9]*(?:;[a-zA-Z0-9]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-PR-TZcf-ntqry=><~]))/g);
const promptNonPrintableCharactersRegex = new Lazy(() => /\\\[.*?\\\]/g);
/**
* Strips ANSI escape sequences from a string.
* @param data The data to strip the ANSI escape sequences from.
*
* @example
* stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m');
* // 'Hello, World!'
*/
export function stripAnsiEscapeSequences(data: string): string {
return data.replace(ansiEscapeSequenceRegex.value, '');
}
/**
* Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`).
* @param data The data to strip the ANSI escape sequences from.
*
* @example
* stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]');
* // '\n\\w\n> '
*/
export function stripAnsiEscapeSequencesFromPrompt(data: string): string {
return (data
.replace(ansiEscapeSequenceRegex.value, '')
.replace(promptNonPrintableCharactersRegex.value, ''));
}

View File

@@ -786,6 +786,14 @@ export function* forAnsiStringParts(str: string) {
}
}
/**
* Strips ANSI escape sequences from a string.
* @param str The dastringa stringo strip the ANSI escape sequences from.
*
* @example
* removeAnsiEscapeCodes('\u001b[31mHello, World!\u001b[0m');
* // 'Hello, World!'
*/
export function removeAnsiEscapeCodes(str: string): string {
if (str) {
str = str.replace(CSI_SEQUENCE, '');
@@ -794,6 +802,21 @@ export function removeAnsiEscapeCodes(str: string): string {
return str;
}
const PROMPT_NON_PRINTABLE = /\\\[.*?\\\]/g;
/**
* Strips ANSI escape sequences from a UNIX-style prompt string (eg. `$PS1`).
* @param str The string to strip the ANSI escape sequences from.
*
* @example
* removeAnsiEscapeCodesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]');
* // '\n\\w\n> '
*/
export function removeAnsiEscapeCodesFromPrompt(str: string): string {
return removeAnsiEscapeCodes(str).replace(PROMPT_NON_PRINTABLE, '');
}
// -- UTF-8 BOM
export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM);

View File

@@ -1,33 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { strictEqual } from 'assert';
import { stripAnsiEscapeSequences, stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('ansi', () => {
ensureNoDisposablesAreLeakedInTestSuite();
suite('stripAnsiEscapeSequences', () => {
test('should strip simple SGR escape sequences', () => {
strictEqual(stripAnsiEscapeSequences('\u001b[31mHello, World!\u001b[0m'), 'Hello, World!');
});
test('should strip complex SGR escape sequences', () => {
strictEqual(stripAnsiEscapeSequences('\u001b[38;2;255;82;197;48;2;155;106;0mHello, World!\u001b[0m'), 'Hello, World!');
});
test('should strip ED, EL escape sequences', () => {
strictEqual(stripAnsiEscapeSequences('\u001b[KHello, World!\r\n\u001b[2J'), 'Hello, World!\r\n');
});
});
suite('stripAnsiEscapeSequencesFromPrompt', () => {
test('should strip simple SGR escape sequences', () => {
strictEqual(stripAnsiEscapeSequences('\u001b[31m$ \u001b[0m'), '$ ');
});
test('should strip \[ and \] chars and their contents', () => {
strictEqual(stripAnsiEscapeSequencesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'), '\n\\w\n> ');
});
});
});

View File

@@ -538,6 +538,11 @@ suite('Strings', () => {
}
});
test('removeAnsiEscapeCodesFromPrompt', () => {
assert.strictEqual(strings.removeAnsiEscapeCodesFromPrompt('\u001b[31m$ \u001b[0m'), '$ ');
assert.strictEqual(strings.removeAnsiEscapeCodesFromPrompt('\n\\[\u001b[01;34m\\]\\w\\[\u001b[00m\\]\n\\[\u001b[1;32m\\]> \\[\u001b[0m\\]'), '\n\\w\n> ');
});
ensureNoDisposablesAreLeakedInTestSuite();
});

View File

@@ -21,7 +21,7 @@ import { BufferMarkCapability } from 'vs/platform/terminal/common/capabilities/b
import type { ITerminalAddon, Terminal } from '@xterm/headless';
import { URI } from 'vs/base/common/uri';
import { sanitizeCwd } from 'vs/platform/terminal/common/terminalEnvironment';
import { stripAnsiEscapeSequencesFromPrompt } from 'vs/base/common/ansi';
import { removeAnsiEscapeCodesFromPrompt } from 'vs/base/common/strings';
/**
@@ -383,7 +383,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
}
switch (key) {
case 'ContinuationPrompt': {
this._updateContinuationPrompt(stripAnsiEscapeSequencesFromPrompt(value));
this._updateContinuationPrompt(removeAnsiEscapeCodesFromPrompt(value));
return true;
}
case 'Cwd': {

View File

@@ -7,7 +7,7 @@ import { ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/termin
import { Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, IDebugSession, IReplElement } from 'vs/workbench/contrib/debug/common/debug';
import { stripAnsiEscapeSequences } from 'vs/base/common/ansi';
import { removeAnsiEscapeCodes } from 'vs/base/common/strings';
export class UrlFinder extends Disposable {
/**
@@ -99,7 +99,7 @@ export class UrlFinder extends Disposable {
private processData(data: string) {
// strip ANSI terminal codes
data = stripAnsiEscapeSequences(data);
data = removeAnsiEscapeCodes(data);
const urlMatches = data.match(UrlFinder.localUrlRegex) || [];
if (urlMatches && urlMatches.length > 0) {
urlMatches.forEach((match) => {