11/**
22 * start-tui.ts — Sets up the Ink TUI renderer and InkUI.
3+ *
4+ * Renders in the terminal's alternate screen buffer so the wizard
5+ * doesn't pollute scrollback history. On exit, the previous terminal
6+ * content is restored and a single exit summary line is printed.
37 */
48
59import { render } from 'ink' ;
@@ -8,15 +12,31 @@ import { WizardStore, Flow } from './store.js';
812import { InkUI } from './ink-ui.js' ;
913import { setUI } from '../index.js' ;
1014import { App } from './App.js' ;
15+ import { OutroKind } from '../../lib/wizard-session.js' ;
1116
1217// ANSI escape sequences
1318const RESET_ATTRS = '\x1b[0m' ;
1419const CLEAR_SCREEN = '\x1b[2J' ;
1520const CURSOR_HOME = '\x1b[H' ;
1621const BG_BLACK = '\x1b[48;2;0;0;0m' ;
22+ const ENTER_ALT_SCREEN = '\x1b[?1049h' ;
23+ const LEAVE_ALT_SCREEN = '\x1b[?1049l' ;
24+ const GREEN = '\x1b[32m' ;
25+ const BOLD = '\x1b[1m' ;
26+ const DIM = '\x1b[2m' ;
1727
18- /** Set background to true black, clear screen, cursor to top-left. */
19- const FORCE_DARK = BG_BLACK + CLEAR_SCREEN + CURSOR_HOME ;
28+ function getExitLine ( store : WizardStore ) : string {
29+ const outro = store . session . outroData ;
30+ const label = store . session . workflowLabel ?? 'Wizard' ;
31+
32+ if ( outro ?. kind === OutroKind . Success ) {
33+ return `${ GREEN } ${ BOLD } \u2714${ RESET_ATTRS } ${
34+ outro . message ?? `${ label } completed successfully.`
35+ } `;
36+ }
37+
38+ return `${ DIM } ${ label } exited.${ RESET_ATTRS } ` ;
39+ }
2040
2141export function startTUI (
2242 version : string ,
@@ -26,8 +46,10 @@ export function startTUI(
2646 store : WizardStore ;
2747 waitForSetup : ( ) => Promise < void > ;
2848} {
29- // Force dark background regardless of terminal theme
30- process . stdout . write ( FORCE_DARK ) ;
49+ // Enter alternate screen buffer, then set up dark background
50+ process . stdout . write (
51+ ENTER_ALT_SCREEN + BG_BLACK + CLEAR_SCREEN + CURSOR_HOME ,
52+ ) ;
3153
3254 const store = new WizardStore ( flow ) ;
3355 store . version = version ;
@@ -39,17 +61,20 @@ export function startTUI(
3961 // Render the Ink app
4062 const { unmount : inkUnmount } = render ( createElement ( App , { store } ) ) ;
4163
42- // Reset terminal on exit
64+ // On exit: unmount Ink, leave alt screen (restores previous content),
65+ // then print exit summary line into the main buffer.
66+ let cleaned = false ;
4367 const cleanup = ( ) => {
44- process . stdout . write ( RESET_ATTRS + CLEAR_SCREEN + CURSOR_HOME ) ;
68+ if ( cleaned ) return ;
69+ cleaned = true ;
70+ inkUnmount ( ) ;
71+ process . stdout . write ( RESET_ATTRS + LEAVE_ALT_SCREEN ) ;
72+ process . stdout . write ( getExitLine ( store ) + '\n' ) ;
4573 } ;
4674 process . on ( 'exit' , cleanup ) ;
4775
4876 return {
49- unmount : ( ) => {
50- inkUnmount ( ) ;
51- cleanup ( ) ;
52- } ,
77+ unmount : cleanup ,
5378 store,
5479 waitForSetup : ( ) => store . getGate ( 'intro' ) ,
5580 } ;
0 commit comments