@@ -72,6 +72,10 @@ type Screen interface {
7272
7373 // This channel is what your main loop should be checking.
7474 Events () chan Event
75+
76+ // Pause the screen, run the given function, then resume the screen. Blocks
77+ // until the function has completed and the screen has been resumed again.
78+ PauseAndCall (run func () error ) error
7579}
7680
7781type interruptableReader interface {
@@ -1132,3 +1136,43 @@ func (screen *UnixScreen) showNLines(width int, height int, clearFirst bool) {
11321136 screen .writeLocked (builder .String ())
11331137 screen .snapshotLastRenderedLocked ()
11341138}
1139+
1140+ // Pause the screen, run the given function, then resume the screen. Blocks
1141+ // until the function has completed and the screen has been resumed again.
1142+ //
1143+ // Error returns mean that either pausing failed or the run function failed. If
1144+ // resuming fails, this method will panic.
1145+ func (screen * UnixScreen ) PauseAndCall (run func () error ) error {
1146+ screen .leaveAlternateScreenSession ()
1147+
1148+ err := screen .restoreTtyInTtyOut ()
1149+ if err != nil {
1150+ return fmt .Errorf ("failed to restore terminal state before pause: %w" , err )
1151+ }
1152+
1153+ runErr := run ()
1154+
1155+ restoreRawErr := screen .restoreRawModeAfterResume ()
1156+ if restoreRawErr != nil {
1157+ panic (fmt .Errorf ("failed to resume screen after paused operation (%v): %w" , runErr , restoreRawErr ))
1158+ }
1159+
1160+ screen .enterAlternateScreenSession ()
1161+ screen .onWindowResized ()
1162+
1163+ if runErr != nil {
1164+ return runErr
1165+ }
1166+
1167+ return nil
1168+ }
1169+
1170+ func (screen * UnixScreen ) restoreRawModeAfterResume () error {
1171+ terminalState , err := term .MakeRaw (int (screen .ttyIn .Fd ()))
1172+ if err != nil {
1173+ return fmt .Errorf ("failed to re-enter raw mode after suspend: %w" , err )
1174+ }
1175+
1176+ screen .oldTerminalState = terminalState
1177+ return nil
1178+ }
0 commit comments