Skip to content

Commit 98a77dc

Browse files
authored
Merge pull request microsoft#162327 from microsoft/tyriar/162070_2
Fix both matching against wrapped lines and supporting scanning multiple lines at once
2 parents 9a25983 + 7ee9be6 commit 98a77dc

File tree

6 files changed

+49
-38
lines changed

6 files changed

+49
-38
lines changed

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,35 @@ export interface ITerminalCommand {
221221
commandStartLineContent?: string;
222222
markProperties?: IMarkProperties;
223223
getOutput(): string | undefined;
224-
getOutputMatch(outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }): RegExpMatchArray | undefined;
224+
getOutputMatch(outputMatcher: ITerminalOutputMatcher): RegExpMatchArray | undefined;
225225
hasOutput(): boolean;
226226
}
227227

228+
229+
/**
230+
* A matcher that runs on a sub-section of a terminal command's output
231+
*/
232+
export interface ITerminalOutputMatcher {
233+
/**
234+
* A string or regex to match against the unwrapped line. If this is a regex with the multiline
235+
* flag, it will scan an amount of lines equal to `\n` instances in the regex + 1.
236+
*/
237+
lineMatcher: string | RegExp;
238+
/**
239+
* Which side of the output to anchor the {@link offset} and {@link length} against.
240+
*/
241+
anchor: 'top' | 'bottom';
242+
/**
243+
* How far from either the top or the bottom of the butter to start matching against.
244+
*/
245+
offset: number;
246+
/**
247+
* The number of rows to match against, this should be as small as possible for performance
248+
* reasons.
249+
*/
250+
length: number;
251+
}
252+
228253
/**
229254
* A clone of the IMarker from xterm which cannot be imported from common
230255
*/

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { timeout } from 'vs/base/common/async';
77
import { debounce } from 'vs/base/common/decorators';
88
import { Emitter } from 'vs/base/common/event';
99
import { ILogService } from 'vs/platform/log/common/log';
10-
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, IHandleCommandOptions, ICommandInvalidationRequest, CommandInvalidationReason, ISerializedCommand, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
10+
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, IHandleCommandOptions, ICommandInvalidationRequest, CommandInvalidationReason, ISerializedCommand, ISerializedCommandDetectionCapability, ITerminalOutputMatcher } from 'vs/platform/terminal/common/capabilities/capabilities';
1111

1212
// Importing types is safe in any layer
1313
// eslint-disable-next-line local/code-import-patterns
@@ -490,7 +490,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
490490
commandStartLineContent: this._currentCommand.commandStartLineContent,
491491
hasOutput: () => !executedMarker?.isDisposed && !endMarker?.isDisposed && !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line),
492492
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
493-
getOutputMatch: (outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
493+
getOutputMatch: (outputMatcher: ITerminalOutputMatcher) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
494494
markProperties: options?.markProperties
495495
};
496496
this._commands.push(newCommand);
@@ -615,7 +615,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
615615
exitCode: e.exitCode,
616616
hasOutput: () => !executedMarker?.isDisposed && !endMarker?.isDisposed && !!(executedMarker && endMarker && executedMarker.line < endMarker.line),
617617
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
618-
getOutputMatch: (outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
618+
getOutputMatch: (outputMatcher: ITerminalOutputMatcher) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
619619
markProperties: e.markProperties
620620
};
621621
this._commands.push(newCommand);
@@ -647,7 +647,7 @@ function getOutputForCommand(executedMarker: IMarker | undefined, endMarker: IMa
647647
return output === '' ? undefined : output;
648648
}
649649

650-
export function getOutputMatchForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer, cols: number, outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }): RegExpMatchArray | undefined {
650+
export function getOutputMatchForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer, cols: number, outputMatcher: ITerminalOutputMatcher): RegExpMatchArray | undefined {
651651
if (!executedMarker || !endMarker) {
652652
return undefined;
653653
}
@@ -659,7 +659,13 @@ export function getOutputMatchForCommand(executedMarker: IMarker | undefined, en
659659
const lines: string[] = [];
660660
if (outputMatcher.anchor === 'bottom') {
661661
for (let i = endLine - (outputMatcher.offset || 0); i >= startLine; i--) {
662-
lines.unshift(getXtermLineContent(buffer, i, i, cols));
662+
let wrappedLineStart = i;
663+
const wrappedLineEnd = i;
664+
while (wrappedLineStart >= startLine && buffer.getLine(wrappedLineStart)?.isWrapped) {
665+
wrappedLineStart--;
666+
}
667+
i = wrappedLineStart;
668+
lines.unshift(getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols));
663669
if (lines.length > linesToCheck) {
664670
lines.pop();
665671
}
@@ -670,7 +676,13 @@ export function getOutputMatchForCommand(executedMarker: IMarker | undefined, en
670676
}
671677
} else {
672678
for (let i = startLine + (outputMatcher.offset || 0); i < endLine; i++) {
673-
lines.push(getXtermLineContent(buffer, i, i, cols));
679+
const wrappedLineStart = i;
680+
let wrappedLineEnd = i;
681+
while (wrappedLineEnd + 1 < endLine && buffer.getLine(wrappedLineEnd + 1)?.isWrapped) {
682+
wrappedLineEnd++;
683+
}
684+
i = wrappedLineEnd;
685+
lines.push(getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols));
674686
if (lines.length === linesToCheck) {
675687
lines.shift();
676688
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import { OperatingSystem } from 'vs/base/common/platform';
1212
import { URI } from 'vs/base/common/uri';
1313
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1414
import { IKeyMods } from 'vs/platform/quickinput/common/quickInput';
15-
import { IMarkProperties, ITerminalCapabilityStore, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities';
15+
import { IMarkProperties, ITerminalCapabilityStore, ITerminalCommand, ITerminalOutputMatcher } from 'vs/platform/terminal/common/capabilities/capabilities';
1616
import { IExtensionTerminalProfile, IReconnectionProperties, IShellIntegration, IShellLaunchConfig, ITerminalDimensions, ITerminalLaunchError, ITerminalProfile, ITerminalTabLayoutInfoById, TerminalExitReason, TerminalIcon, TerminalLocation, TerminalShellType, TerminalType, TitleEventSource, WaitOnExitValue } from 'vs/platform/terminal/common/terminal';
1717
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
1818
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
1919
import { IEditableData } from 'vs/workbench/common/views';
2020
import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget';
2121
import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList';
2222
import { ITerminalQuickFix } from 'vs/workbench/contrib/terminal/browser/xterm/quickFixAddon';
23-
import { INavigationMode, IRegisterContributedProfileArgs, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalBackend, ITerminalConfigHelper, ITerminalFont, ITerminalOutputMatcher, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
23+
import { INavigationMode, IRegisterContributedProfileArgs, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalBackend, ITerminalConfigHelper, ITerminalFont, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal';
2424
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
2525
import { IMarker } from 'xterm';
2626

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

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/e
1313
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1414
import { URI } from 'vs/base/common/uri';
1515
import { Registry } from 'vs/platform/registry/common/platform';
16-
import { IMarkProperties, ISerializedCommandDetectionCapability, ITerminalCapabilityStore, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
16+
import { IMarkProperties, ISerializedCommandDetectionCapability, ITerminalCapabilityStore, ITerminalOutputMatcher, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
1717
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
1818
import { IProcessDetails } from 'vs/platform/terminal/common/terminalProcess';
1919

@@ -96,30 +96,6 @@ export interface IShellLaunchConfigResolveOptions {
9696
allowAutomationShell?: boolean;
9797
}
9898

99-
/**
100-
* A matcher that runs on a sub-section of a terminal command's output
101-
*/
102-
export interface ITerminalOutputMatcher {
103-
/**
104-
* A string or regex to match against the unwrapped line. If this is a regex with the multiline
105-
* flag, it will scan an amount of lines equal to `\n` instances in the regex + 1.
106-
*/
107-
lineMatcher: string | RegExp;
108-
/**
109-
* Which side of the output to anchor the {@link offset} and {@link length} against.
110-
*/
111-
anchor: 'top' | 'bottom';
112-
/**
113-
* How far from either the top or the bottom of the butter to start matching against.
114-
*/
115-
offset: number;
116-
/**
117-
* The number of rows to match against, this should be as small as possible for performance
118-
* reasons.
119-
*/
120-
length: number;
121-
}
122-
12399
export interface ITerminalBackend {
124100
readonly remoteAuthority: string | undefined;
125101

src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkOpeners.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
1717
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
1818
import { TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminal/browser/links/links';
1919
import { TerminalLocalFileLinkOpener, TerminalLocalFolderInWorkspaceLinkOpener, TerminalSearchLinkOpener } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkOpeners';
20-
import { TerminalCapability, ITerminalCommand, IXtermMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
20+
import { TerminalCapability, ITerminalCommand, IXtermMarker, ITerminalOutputMatcher } from 'vs/platform/terminal/common/capabilities/capabilities';
2121
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
2222
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
2323
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
2424
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
2525
import { Terminal } from 'xterm';
2626
import { IFileQuery, ISearchComplete, ISearchService } from 'vs/workbench/services/search/common/search';
2727
import { SearchService } from 'vs/workbench/services/search/common/searchService';
28-
import { ITerminalOutputMatcher } from 'vs/workbench/contrib/terminal/common/terminal';
2928

3029
export interface ITerminalLinkActivationResult {
3130
source: 'editor' | 'search';

src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
1111
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
1212
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
1313
import { IOpenerService } from 'vs/platform/opener/common/opener';
14-
import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
14+
import { ITerminalCommand, ITerminalOutputMatcher, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
1515
import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability';
1616
import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore';
1717
import { ITerminalQuickFixAction, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
1818
import { freePort, FreePortOutputRegex, gitCreatePr, GitCreatePrOutputRegex, GitPushOutputRegex, gitPushSetUpstream, gitSimilarCommand, GitSimilarOutputRegex } from 'vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions';
1919
import { TerminalQuickFixAddon, getQuickFixes } from 'vs/workbench/contrib/terminal/browser/xterm/quickFixAddon';
20-
import { ITerminalOutputMatcher } from 'vs/workbench/contrib/terminal/common/terminal';
2120
import { Terminal } from 'xterm';
2221

2322
suite('QuickFixAddon', () => {

0 commit comments

Comments
 (0)