Skip to content

Commit 4486bcb

Browse files
committed
cp dines
1 parent c215b32 commit 4486bcb

9 files changed

Lines changed: 53 additions & 25 deletions

File tree

src/cli.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ const packageJson = JSON.parse(
1919
);
2020
export const VERSION = packageJson.version;
2121

22+
import { exitAlternateScreen } from "./utils/screen.js";
23+
2224
// Global Ctrl+C handler to ensure it always exits
2325
process.on("SIGINT", () => {
2426
// Force exit immediately, clearing alternate screen buffer
25-
process.stdout.write("\x1b[?1049l");
27+
exitAlternateScreen();
2628
process.stdout.write("\n");
2729
process.exit(130); // Standard exit code for SIGINT
2830
});

src/commands/blueprint/list.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { getBlueprintUrl } from "../../utils/url.js";
1818
import { colors } from "../../utils/theme.js";
1919
import { getStatusDisplay } from "../../components/StatusBadge.js";
2020
import { DevboxCreatePage } from "../../components/DevboxCreatePage.js";
21+
import { exitAlternateScreen } from "../../utils/screen.js";
2122

2223
const PAGE_SIZE = 10;
2324
const MAX_FETCH = 100;
@@ -316,7 +317,7 @@ const ListBlueprintsUI = ({
316317

317318
// Handle Ctrl+C to force exit
318319
if (key.ctrl && input === "c") {
319-
process.stdout.write("\x1b[?1049l"); // Exit alternate screen
320+
exitAlternateScreen(); // Exit alternate screen
320321
process.exit(130);
321322
}
322323

src/commands/devbox/list.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { ResourceActionsMenu } from "../../components/ResourceActionsMenu.js";
1818
import { ActionsPopup } from "../../components/ActionsPopup.js";
1919
import { getDevboxUrl } from "../../utils/url.js";
2020
import { useViewportHeight } from "../../hooks/useViewportHeight.js";
21+
import { exitAlternateScreen } from "../../utils/screen.js";
2122
import {
2223
runSSHSession,
2324
type SSHSessionConfig,
@@ -556,7 +557,7 @@ const ListDevboxesUI = ({
556557
useInput((input, key) => {
557558
// Handle Ctrl+C to force exit
558559
if (key.ctrl && input === "c") {
559-
process.stdout.write("\x1b[?1049l"); // Exit alternate screen
560+
exitAlternateScreen(); // Exit alternate screen
560561
process.exit(130);
561562
}
562563

src/commands/menu.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import React from "react";
22
import { render } from "ink";
33
import { runSSHSession, type SSHSessionConfig } from "../utils/sshSession.js";
4+
import { enterAlternateScreen, exitAlternateScreen } from "../utils/screen.js";
45

56
import { Router } from "../router/Router.js";
6-
import {
7-
NavigationProvider,
8-
useNavigation,
9-
} from "../store/navigationStore.js";
7+
import { NavigationProvider } from "../store/navigationStore.js";
108
import type { ScreenName } from "../store/navigationStore.js";
119

1210
interface AppProps {
@@ -45,7 +43,7 @@ export async function runMainMenu(
4543
focusDevboxId?: string,
4644
) {
4745
// Enter alternate screen buffer for fullscreen experience (like top/vim)
48-
//process.stdout.write("\x1b[?1049h");
46+
enterAlternateScreen();
4947

5048
let sshSessionConfig: SSHSessionConfig | null = null;
5149
let shouldContinue = true;
@@ -68,14 +66,6 @@ export async function runMainMenu(
6866
{
6967
patchConsole: false,
7068
exitOnCtrlC: false,
71-
//debug: true,
72-
// onRender: (metrics) => {
73-
// console.log(
74-
// "==== onRender ====",
75-
// new Date().toISOString(),
76-
// metrics,
77-
// );
78-
// },
7969
},
8070
);
8171
await waitUntilExit();
@@ -106,7 +96,7 @@ export async function runMainMenu(
10696
// disableSynchronousUpdates();
10797

10898
// Exit alternate screen buffer
109-
//process.stdout.write("\x1b[?1049l");
99+
exitAlternateScreen();
110100

111101
process.exit(0);
112102
}

src/components/MainMenu.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Breadcrumb } from "./Breadcrumb.js";
66
import { VERSION } from "../cli.js";
77
import { colors } from "../utils/theme.js";
88
import { useViewportHeight } from "../hooks/useViewportHeight.js";
9+
import { exitAlternateScreen } from "../utils/screen.js";
910

1011
interface MenuItem {
1112
key: string;
@@ -65,6 +66,9 @@ export const MainMenu = ({ onSelect }: MainMenuProps) => {
6566
onSelect("blueprints");
6667
} else if (input === "s" || input === "3") {
6768
onSelect("snapshots");
69+
} else if (key.ctrl && input === "c") {
70+
exitAlternateScreen();
71+
process.exit(130);
6872
}
6973
});
7074

src/components/ResourceListView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ErrorMessage } from "./ErrorMessage.js";
88
import { Table, Column } from "./Table.js";
99
import { colors } from "../utils/theme.js";
1010
import { useViewportHeight } from "../hooks/useViewportHeight.js";
11+
import { exitAlternateScreen } from "../utils/screen.js";
1112

1213
// Format time ago in a succinct way
1314
export const formatTimeAgo = (timestamp: number): string => {
@@ -217,7 +218,7 @@ export function ResourceListView<T>({ config }: ResourceListViewProps<T>) {
217218

218219
// Handle Ctrl+C to force exit
219220
if (key.ctrl && input === "c") {
220-
process.stdout.write("\x1b[?1049l"); // Exit alternate screen
221+
exitAlternateScreen(); // Exit alternate screen
221222
process.exit(130);
222223
}
223224

src/utils/CommandExecutor.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
OutputOptions,
1414
} from "./output.js";
1515
import { enableSynchronousUpdates, disableSynchronousUpdates } from "./terminalSync.js";
16+
import { exitAlternateScreen, enterAlternateScreen } from "./screen.js";
1617
import YAML from "yaml";
1718

1819
export class CommandExecutor<T = unknown> {
@@ -56,7 +57,7 @@ export class CommandExecutor<T = unknown> {
5657

5758
// Exit alternate screen buffer
5859
disableSynchronousUpdates();
59-
process.stdout.write("\x1b[?1049l");
60+
exitAlternateScreen();
6061
}
6162

6263
/**
@@ -78,7 +79,7 @@ export class CommandExecutor<T = unknown> {
7879

7980
// Interactive mode
8081
// Enter alternate screen buffer (this automatically clears the screen)
81-
process.stdout.write("\x1b[?1049h");
82+
enterAlternateScreen();
8283
enableSynchronousUpdates();
8384

8485
const { waitUntilExit } = render(renderUI(), {
@@ -89,7 +90,7 @@ export class CommandExecutor<T = unknown> {
8990

9091
// Exit alternate screen buffer
9192
disableSynchronousUpdates();
92-
process.stdout.write("\x1b[?1049l");
93+
exitAlternateScreen();
9394
}
9495

9596
/**
@@ -112,7 +113,7 @@ export class CommandExecutor<T = unknown> {
112113

113114
// Interactive mode
114115
// Enter alternate screen buffer
115-
process.stdout.write("\x1b[?1049h");
116+
enterAlternateScreen();
116117
enableSynchronousUpdates();
117118

118119
const { waitUntilExit } = render(renderUI(), {
@@ -123,7 +124,7 @@ export class CommandExecutor<T = unknown> {
123124

124125
// Exit alternate screen buffer
125126
disableSynchronousUpdates();
126-
process.stdout.write("\x1b[?1049l");
127+
exitAlternateScreen();
127128
}
128129

129130
/**

src/utils/interactiveCommand.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
import { enterAlternateScreen, exitAlternateScreen } from "./screen.js";
2+
13
/**
24
* Wrapper for interactive commands that need alternate screen buffer management
35
*/
46
export async function runInteractiveCommand(command: () => Promise<void>) {
57
// Enter alternate screen buffer
6-
process.stdout.write("\x1b[?1049h");
8+
enterAlternateScreen();
79

810
try {
911
await command();
1012
} finally {
1113
// Exit alternate screen buffer
12-
process.stdout.write("\x1b[?1049l");
14+
exitAlternateScreen();
1315
}
1416
}

src/utils/screen.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Terminal screen buffer utilities.
3+
*
4+
* The alternate screen buffer provides a fullscreen experience similar to
5+
* applications like vim, top, or htop. When enabled, the terminal saves
6+
* the current screen content and switches to a clean buffer. Upon exit,
7+
* the original screen content is restored.
8+
*/
9+
10+
/**
11+
* Enter the alternate screen buffer.
12+
* This provides a fullscreen experience where content won't mix with
13+
* previous terminal output. Like vim or top.
14+
*/
15+
export function enterAlternateScreen(): void {
16+
process.stdout.write("\x1b[?1049h");
17+
}
18+
19+
/**
20+
* Exit the alternate screen buffer and restore the previous screen content.
21+
* This returns the terminal to its original state before enterAlternateScreen() was called.
22+
*/
23+
export function exitAlternateScreen(): void {
24+
process.stdout.write("\x1b[?1049l");
25+
}
26+

0 commit comments

Comments
 (0)