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 66 67 68 69 70 71 72 73 | 1x 1x 1x 4x 4x 4x 4x 4x 1x 1x 3x 3x 3x 3x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 3x 3x 3x 2x 2x 3x 3x 3x 3x 2x 2x 3x 3x 3x 2x 2x 2x 2x 2x 2x 2x 2x 3x 3x 3x 3x | import * as vscode from "vscode";
import { ShellIntegrationAccumulator } from "./extract-output";
import type { TerminalOutputRegisterDeps } from "./types";
type WindowWithShellExec = typeof vscode.window & {
onDidStartTerminalShellExecution?: vscode.Event<vscode.TerminalShellExecutionStartEvent>;
};
/**
* Stable API: per-command terminal output via TerminalShellExecution.read().
* One ShellIntegrationAccumulator per execution (isolated state vs global proposed stream).
*/
export function registerStableShellExecutionTerminalOutput(
context: vscode.ExtensionContext,
deps: TerminalOutputRegisterDeps,
): boolean {
const w = vscode.window as WindowWithShellExec;
if (typeof w.onDidStartTerminalShellExecution !== "function") {
return false;
}
const { maxChars, debounceMs, emitOutput } = deps;
const subscription = w.onDidStartTerminalShellExecution!((e) => {
const exec = e.execution as vscode.TerminalShellExecution & {
read?: () => AsyncIterable<string>;
};
if (typeof exec.read !== "function") {
return;
}
void (async () => {
const acc = new ShellIntegrationAccumulator();
let rolling = "";
let timer: ReturnType<typeof setTimeout> | null = null;
const flush = (): void => {
timer = null;
const trimmed = rolling.trim();
if (!trimmed) return;
emitOutput(trimmed.slice(-maxChars));
};
const scheduleFlush = (): void => {
if (timer) clearTimeout(timer);
timer = setTimeout(flush, debounceMs);
};
try {
for await (const chunk of exec.read()) {
const piece = acc.process(chunk);
if (piece) {
rolling += piece;
if (rolling.length > maxChars * 4) {
rolling = rolling.slice(-maxChars * 2);
}
scheduleFlush();
}
}
} finally {
if (timer) {
clearTimeout(timer);
timer = null;
}
flush();
}
})();
});
context.subscriptions.push(subscription);
return true;
}
|