All files extract-output.ts

100% Statements 42/42
100% Branches 15/15
100% Functions 3/3
100% Lines 42/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65              1x 1x   1x 22x 22x   1x 1x           1x 10x         1x 12x 12x   12x 16x 4x 4x 3x 3x 3x 4x 1x 1x 1x 16x 12x 12x 4x 4x 4x 16x   12x   12x 12x 8x 7x 7x 12x 7x 7x   5x 12x 1x  
/**
 * Shell-integration-aware terminal output extraction (OSC 633 C/D markers).
 * VS Code injects sequences: 633;C → start of command output, 633;D → end.
 */
 
// Matches all ANSI/VT escape sequences including OSC, CSI, SS3, etc.
// OSC (\e]) MUST be the first alternative — see extension host comments.
export const ANSI_RE =
  /\x1B(?:\][^\x07\x1B]*(?:\x07|\x1B\\)|[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g;
 
export function stripAnsi(str: string): string {
  return str.replace(ANSI_RE, "").replace(/\r/g, "");
}
 
const C_MARKER = "\x1b]633;C\x07";
const D_RE = /\x1b\]633;D(?:;[^\x07]*)?\x07/;
 
/**
 * Stateful extractor for incremental terminal chunks (one instance per logical stream:
 * proposed global buffer, or one per shell execution read stream).
 */
export class ShellIntegrationAccumulator {
  private capturing = false;
 
  /**
   * Process one raw chunk; returns cleaned extract for this chunk given prior state.
   */
  process(raw: string): string {
    let output = "";
    let remaining = raw;
 
    while (remaining.length > 0) {
      if (this.capturing) {
        const dMatch = D_RE.exec(remaining);
        if (dMatch) {
          output += remaining.slice(0, dMatch.index);
          remaining = remaining.slice(dMatch.index + dMatch[0].length);
          this.capturing = false;
        } else {
          output += remaining;
          remaining = "";
        }
      } else {
        const cIdx = remaining.indexOf(C_MARKER);
        if (cIdx === -1) break;
        remaining = remaining.slice(cIdx + C_MARKER.length);
        this.capturing = true;
      }
    }
 
    const cleaned = stripAnsi(output).trim();
 
    if (
      cleaned === "" &&
      !raw.includes(C_MARKER) &&
      !D_RE.test(raw) &&
      !this.capturing
    ) {
      return stripAnsi(raw).trim();
    }
 
    return cleaned;
  }
}