diff --git a/scripts/e2e-terminal-stop.test.mjs b/scripts/e2e-terminal-stop.test.mjs index bcf5fe2..47f93fd 100644 --- a/scripts/e2e-terminal-stop.test.mjs +++ b/scripts/e2e-terminal-stop.test.mjs @@ -9,6 +9,7 @@ import { onRunStart, onRunResult, printInfo, + resetTerminalSession, showInitialPrompt, startRun, stopRun, @@ -20,13 +21,14 @@ function setupTerminalHarness({ onRun, } = {}) { const writes = []; + const clearCalls = []; const runStateChanges = []; const runPreparationChanges = []; const stopCalls = []; const runCalls = []; const stdinMessages = []; const fakeTerm = { - clear() {}, + clear() { clearCalls.push(true); }, write(text) { writes.push(text); }, }; @@ -46,6 +48,7 @@ function setupTerminalHarness({ return { writes, + clearCalls, runStateChanges, runPreparationChanges, stopCalls, @@ -87,6 +90,27 @@ test('e2e: initial terminal prompt is only written once', () => { assert.equal(output.match(/browser\.cpp/g)?.length, 1); }); +test('e2e: resetting a terminal session clears output and redraws one prompt', () => { + const ctx = setupTerminalHarness(); + showInitialPrompt(); + printInfo('stale output'); + + resetTerminalSession({ name: 'project', entries: [] }); + + assert.equal(ctx.clearCalls.length, 1); + assert.equal(ctx.writes.at(-1).match(/browser\.cpp/g)?.length, 1); + assert.match(ctx.writes.at(-1), /browser\.cpp.*:~\$ /); +}); + +test('e2e: resetting before compiler readiness does not print a prompt', () => { + const ctx = setupTerminalHarness(); + + resetTerminalSession(); + + assert.equal(ctx.clearCalls.length, 1); + assert.equal(ctx.writes.length, 0); +}); + test('e2e: clearing during startup does not reveal the initial prompt early', () => { const ctx = setupTerminalHarness(); diff --git a/src/ui/terminal.js b/src/ui/terminal.js index f352c91..707e620 100644 --- a/src/ui/terminal.js +++ b/src/ui/terminal.js @@ -362,6 +362,19 @@ export function clearTerminal() { writePrompt(); } +/** + * Start a clean terminal session for a workspace transition. + * Unlike clearTerminal(), this also resets the workspace prompt context and + * input line before drawing at most one prompt. + */ +export function resetTerminalSession(workspace = null) { + inputBuffer = ''; + historyIdx = -1; + setWorkspace(workspace); + term?.clear(); + if (initialPromptShown) writePrompt(); +} + /** Write the first shell prompt after compiler startup has reached a terminal state. */ export function showInitialPrompt() { if (initialPromptShown) return; diff --git a/src/ui/toolbar.js b/src/ui/toolbar.js index c170cbe..8a62b3b 100644 --- a/src/ui/toolbar.js +++ b/src/ui/toolbar.js @@ -599,7 +599,6 @@ function clearTransientProjectState() { _runAfterSuccessfulCompile = false; _runPreparationActive = false; _lastRunBinaryBytes = null; - _terminalAPI.clearTerminal?.(); _editorAPI.clearDiagnostics?.(); } @@ -608,6 +607,7 @@ export function restoreNoWorkspaceSource(source) { closeAllTabs(); _fsAPI.newFile(); clearWorkspaceMode(); + _terminalAPI.resetTerminalSession?.(null); openTabForFile(UNSAVED_TAB_PATH, source); markDirty(false); } @@ -1097,7 +1097,7 @@ function showOpenError(err) { function setWorkspaceMode(workspace) { _workspace = workspace; _expandedWorkspaceDirectories.clear(); - _terminalAPI.setWorkspace?.(workspace); + _terminalAPI.resetTerminalSession?.(workspace); updateCompileButtons(); startWorkspaceSyncPolling(); } @@ -1105,7 +1105,6 @@ function setWorkspaceMode(workspace) { function clearWorkspaceMode() { _workspace = null; _expandedWorkspaceDirectories.clear(); - _terminalAPI.setWorkspace?.(null); const tree = document.getElementById('file-tree'); if (tree) tree.innerHTML = ''; updateCompileButtons(false);