Change:
I don't think that's the same issue. Here's a recording: https://user- Originally posted by in
had you cleared the terminal?
can reproduce after clearing the terminal on windows via EDIT: only works when the lightbulb is on the very bottom of the terminal - we have the wrong line demand it seems / offset
here's the only place it works for me on windows !
probably something wrong/unexpected happening with the constraints !
the problem is the lightbulb doesn't show? What's the problem there?
I had cleared that terminal, but this reproduces for me on a fresh terminal without clearing
Ah, I broke this for all platforms in

Discussion:
commandStartLineContent: this._currentCommand.commandStartLineContent, hasOutput: () => !executedMarker?.isDisposed && !endMarker?.isDisposed && !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line), getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer), <del> getOutputMatch: (outputMatcher?: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher), </del> <ins> getOutputMatch: (outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher), </ins> markProperties: options?.markProperties }; this._commands.push(newCommand);

return output === '' ? undefined : output; } <del> export function getOutputMatchForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer, cols: number, outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number } | undefined): RegExpMatchArray | undefined { </del> <ins> 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 { </ins> if (!executedMarker || !endMarker) { return undefined; } const startLine = executedMarker.line; const endLine = endMarker.line; <del> if (startLine === endLine) { return undefined; } let line: string | undefined; if (outputMatcher?.anchor === 'bottom') { </del> <ins> const matcher = outputMatcher.lineMatcher; const linesToCheck = typeof matcher === 'string' ? 1 : countNewLines(matcher); const lines: string[] = []; if (outputMatcher.anchor === 'bottom') { </ins> for (let i = endLine - (outputMatcher.offset || 0); i >= startLine; i--) { <del> let wrappedLineStart = i; const wrappedLineEnd = i; while (wrappedLineStart >= startLine && buffer.getLine(wrappedLineStart)?.isWrapped) { wrappedLineStart--; </del> <ins> lines.unshift(getXtermLineContent(buffer, i, i, cols)); if (lines.length > linesToCheck) { lines.pop(); </ins> } <del> i = wrappedLineStart; line = getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols); const match = line.match(outputMatcher.lineMatcher); </del> <ins> const match = lines.join('n').match(matcher); </ins> if (match) { return match; } } } else { <del> for (let i = startLine + (outputMatcher?.offset || 0); i < endLine; i++) { const wrappedLineStart = i; let wrappedLineEnd = i; while (wrappedLineEnd + 1 < endLine && buffer.getLine(wrappedLineEnd + 1)?.isWrapped) { wrappedLineEnd++; </del> <ins> for (let i = startLine + (outputMatcher.offset || 0); i < endLine; i++) { lines.push(getXtermLineContent(buffer, i, i, cols)); if (lines.length === linesToCheck) { lines.shift(); </ins> } <del> i = wrappedLineEnd; line = getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols); </del> if (outputMatcher) { <del> const match = line.match(outputMatcher.lineMatcher); </del> <ins> const match = lines.join('n').match(matcher); </ins> if (match) { return match; }

} return content; } <ins> function countNewLines(regex: RegExp): number { if (!regex.multiline) { return 1; } const source = regex.source; let count = 1; let i = source.indexOf('n'); while (i !== -1) { count++; i = source.indexOf('n', i + 1); } return count; } </ins>

import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { ITerminalQuickFix } from 'vs/workbench/contrib/terminal/browser/xterm/quickFixAddon'; <del> import { INavigationMode, IRegisterContributedProfileArgs, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalBackend, ITerminalConfigHelper, ITerminalFont, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; </del> <ins> import { INavigationMode, IRegisterContributedProfileArgs, IRemoteTerminalAttachTarget, IStartExtensionTerminalRequest, ITerminalBackend, ITerminalConfigHelper, ITerminalFont, ITerminalOutputMatcher, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; </ins> import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { IMarker } from 'xterm';

addNewLine?: boolean; } <del> /** * A matcher that runs on a sub-section of a terminal command's output */ export interface ITerminalOutputMatcher { /** * A string or regex to match against the unwrapped line. */ lineMatcher: string | RegExp; /** * Which side of the output to anchor the {@link offset} and {@link length} against. */ anchor: 'top' | 'bottom'; /** * How far from either the top or the bottom of the butter to start matching against. */ offset: number; /** * The number of rows to match against, this should be as small as possible for performance * reasons. */ length: number; } </del> export interface IXtermTerminal { /** * An object that tracks when commands are run and enables navigating and selecting between

export const GitCommandLineRegex = /git/; export const GitPushCommandLineRegex = /gits+push/; export const AnyCommandLineRegex = /.+/; <del> export const GitSimilarOutputRegex = /most similar command iss*([^s]{3,})/; </del> <ins> export const GitSimilarOutputRegex = /most similar command iss*ns*([^s]{3,})/m; </ins> export const FreePortOutputRegex = /address already in use d+.d+.d+.d+:(d{4,5})|Unable to bind [^ ]*:(d{4,5})|can't listen on port (d{4,5})|listen EADDRINUSE [^ ]*:(d{4,5})/; export const GitPushOutputRegex = /git push --set-upstream origin ([^s]+)/; // The previous line starts with "Create a pull request for '([^s]+)' on GitHub by visiting:s*",

allowAutomationShell?: boolean; } <ins> /** * A matcher that runs on a sub-section of a terminal command's output */ </ins> export interface ITerminalOutputMatcher { <ins> /** * A string or regex to match against the unwrapped line. If this is a regex with the multiline * flag, it will scan an amount of lines equal to `n` instances in the regex + 1. */ </ins> lineMatcher: string | RegExp; <del> anchor?: 'top' | 'bottom'; offset?: number; length?: number; </del> <ins> /** * Which side of the output to anchor the {@link offset} and {@link length} against. */ anchor: 'top' | 'bottom'; /** * How far from either the top or the bottom of the butter to start matching against. */ offset: number; /** * The number of rows to match against, this should be as small as possible for performance * reasons. */ length: number; </ins> } export interface ITerminalBackend {

import { ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; import { CommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/commandDetectionCapability'; import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilities/terminalCapabilityStore'; <del> import { ITerminalQuickFixAction, ITerminalInstance, ITerminalOutputMatcher } from 'vs/workbench/contrib/terminal/browser/terminal'; </del> <ins> import { ITerminalQuickFixAction, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; </ins> import { freePort, FreePortOutputRegex, gitCreatePr, GitCreatePrOutputRegex, GitPushOutputRegex, gitPushSetUpstream, gitSimilarCommand, GitSimilarOutputRegex } from 'vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions'; import { TerminalQuickFixAddon, getQuickFixes } from 'vs/workbench/contrib/terminal/browser/xterm/quickFixAddon'; <ins> import { ITerminalOutputMatcher } from 'vs/workbench/contrib/terminal/common/terminal'; </ins> import { Terminal } from 'xterm'; suite('QuickFixAddon', () => {