Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/desktop/src/main/lib/terminal-escape-filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe("extractContentAfterClear", () => {
});

it("should not confuse similar sequences", () => {
// ESC[3 (without J) is not a clear sequence
expect(extractContentAfterClear(`${ESC}[3mtext`)).toBe(`${ESC}[3mtext`);
});
});
Expand Down
12 changes: 9 additions & 3 deletions apps/desktop/src/main/lib/terminal-escape-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
*/

const ESC = "\x1b";
const ED3_SEQUENCE = `${ESC}[3J`;

/**
* Pattern to detect clear scrollback sequences (ED3 only).
* ESC c (RIS) is intentionally excluded - TUI apps use it for repaints.
* Pattern to detect clear scrollback sequences:
* - ESC [ 3 J - Clear scrollback buffer (ED3)
*
* Note: We intentionally do NOT include ESC c (RIS - Reset to Initial State)
* because TUI applications (vim, htop, etc.) commonly use RIS for screen
* repaints/refreshes. Only ED3 is a deliberate "clear scrollback" action
* triggered by commands like `clear` or Cmd+K.
*/
const CLEAR_SCROLLBACK_PATTERN = new RegExp(`${ESC}\\[3J`);

const ED3_SEQUENCE = `${ESC}[3J`;

/**
* Checks if data contains sequences that clear the scrollback buffer.
* Used to detect when the shell sends clear commands (e.g., from `clear` command or Cmd+K).
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/main/lib/terminal/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export function setupDataHandler(
let commandsSent = false;

session.pty.onData((data) => {
// Recreate headless on clear because xterm.clear() is async and unreliable
// Recreate headless on clear (xterm writes are async, so clear() alone is unreliable)
if (containsClearScrollbackSequence(data)) {
session.headless.dispose();
const { headless, serializer } = createHeadlessTerminal({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Terminal as XTerm } from "@xterm/xterm";
import { useCallback, useRef } from "react";
import { DEBUG_TERMINAL } from "../config";
import type { CreateOrAttachResult, TerminalStreamEvent } from "../types";
import { scrollToBottom, stripClearScrollbackSequence } from "../utils";
import { scrollToBottom } from "../utils";

export interface UseTerminalRestoreOptions {
paneId: string;
Expand Down Expand Up @@ -92,7 +92,7 @@ export function useTerminalRestore({
for (const event of events) {
if (event.type === "data") {
updateModesRef.current(event.data);
xterm.write(stripClearScrollbackSequence(event.data));
xterm.write(event.data);
updateCwdRef.current(event.data);
} else if (event.type === "exit") {
onExitEventRef.current(event.exitCode, xterm);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { Terminal } from "@xterm/xterm";
import { quote } from "shell-quote";

export { stripClearScrollbackSequence } from "shared/terminal-escape";

export function shellEscapePaths(paths: string[]): string {
return quote(paths);
}
Expand Down
61 changes: 0 additions & 61 deletions apps/desktop/src/shared/terminal-escape.test.ts

This file was deleted.

7 changes: 0 additions & 7 deletions apps/desktop/src/shared/terminal-escape.ts

This file was deleted.

Loading