Skip to main content

bubbletea/
screen.rs

1//! Screen control commands.
2//!
3//! These commands control terminal display features like alternate screen,
4//! cursor visibility, mouse tracking, and more.
5
6use crate::command::Cmd;
7use crate::message::Message;
8
9// Internal message types for screen commands
10pub(crate) struct ClearScreenMsg;
11pub(crate) struct EnterAltScreenMsg;
12pub(crate) struct ExitAltScreenMsg;
13pub(crate) struct ShowCursorMsg;
14pub(crate) struct HideCursorMsg;
15pub(crate) struct EnableMouseCellMotionMsg;
16pub(crate) struct EnableMouseAllMotionMsg;
17pub(crate) struct DisableMouseMsg;
18pub(crate) struct EnableBracketedPasteMsg;
19pub(crate) struct DisableBracketedPasteMsg;
20pub(crate) struct EnableReportFocusMsg;
21pub(crate) struct DisableReportFocusMsg;
22pub(crate) struct ReleaseTerminalMsg;
23pub(crate) struct RestoreTerminalMsg;
24
25/// Command to clear the screen.
26pub fn clear_screen() -> Cmd {
27    Cmd::new(|| Message::new(ClearScreenMsg))
28}
29
30/// Command to enter alternate screen buffer.
31///
32/// This provides a separate screen that preserves the original terminal
33/// content when your program exits.
34pub fn enter_alt_screen() -> Cmd {
35    Cmd::new(|| Message::new(EnterAltScreenMsg))
36}
37
38/// Command to exit alternate screen buffer.
39pub fn exit_alt_screen() -> Cmd {
40    Cmd::new(|| Message::new(ExitAltScreenMsg))
41}
42
43/// Command to show the cursor.
44pub fn show_cursor() -> Cmd {
45    Cmd::new(|| Message::new(ShowCursorMsg))
46}
47
48/// Command to hide the cursor.
49pub fn hide_cursor() -> Cmd {
50    Cmd::new(|| Message::new(HideCursorMsg))
51}
52
53/// Command to enable mouse cell motion tracking.
54///
55/// This reports mouse clicks and drags.
56pub fn enable_mouse_cell_motion() -> Cmd {
57    Cmd::new(|| Message::new(EnableMouseCellMotionMsg))
58}
59
60/// Command to enable mouse all motion tracking.
61///
62/// This reports all mouse movement, including without button presses.
63pub fn enable_mouse_all_motion() -> Cmd {
64    Cmd::new(|| Message::new(EnableMouseAllMotionMsg))
65}
66
67/// Command to disable mouse tracking.
68pub fn disable_mouse() -> Cmd {
69    Cmd::new(|| Message::new(DisableMouseMsg))
70}
71
72/// Command to enable bracketed paste mode.
73///
74/// In bracketed paste mode, pasted text is wrapped in escape sequences,
75/// allowing the application to distinguish typed text from pasted text.
76pub fn enable_bracketed_paste() -> Cmd {
77    Cmd::new(|| Message::new(EnableBracketedPasteMsg))
78}
79
80/// Command to disable bracketed paste mode.
81pub fn disable_bracketed_paste() -> Cmd {
82    Cmd::new(|| Message::new(DisableBracketedPasteMsg))
83}
84
85/// Command to enable focus reporting.
86///
87/// When enabled, the terminal sends FocusMsg and BlurMsg events.
88pub fn enable_report_focus() -> Cmd {
89    Cmd::new(|| Message::new(EnableReportFocusMsg))
90}
91
92/// Command to disable focus reporting.
93pub fn disable_report_focus() -> Cmd {
94    Cmd::new(|| Message::new(DisableReportFocusMsg))
95}
96
97/// Command to release the terminal for external processes.
98///
99/// This restores the terminal to its normal state:
100/// - Disables raw mode
101/// - Shows the cursor
102/// - Exits alternate screen (if enabled)
103/// - Disables mouse tracking
104/// - Disables bracketed paste
105/// - Disables focus reporting
106///
107/// Use this before spawning external processes like text editors.
108/// Call `restore_terminal()` afterwards to resume the TUI.
109///
110/// # Example
111///
112/// ```rust,ignore
113/// use bubbletea::{Model, Message, Cmd, screen, sequence};
114/// use std::process::Command;
115///
116/// fn update(&mut self, msg: Message) -> Option<Cmd> {
117///     if msg.is::<EditMsg>() {
118///         return Some(sequence(vec![
119///             Some(screen::release_terminal()),
120///             Some(Cmd::new(|| {
121///                 // Run editor
122///                 Command::new("vim").arg("file.txt").status().ok();
123///                 Message::new(EditorDoneMsg)
124///             })),
125///             Some(screen::restore_terminal()),
126///         ]));
127///     }
128///     None
129/// }
130/// ```
131pub fn release_terminal() -> Cmd {
132    Cmd::new(|| Message::new(ReleaseTerminalMsg))
133}
134
135/// Command to restore the terminal after a release.
136///
137/// This re-enables the TUI state:
138/// - Enables raw mode
139/// - Hides the cursor
140/// - Enters alternate screen (if originally enabled)
141/// - Restores mouse tracking settings
142/// - Restores bracketed paste mode
143/// - Restores focus reporting
144///
145/// Use this after `release_terminal()` to resume the TUI.
146pub fn restore_terminal() -> Cmd {
147    Cmd::new(|| Message::new(RestoreTerminalMsg))
148}
149
150// Note: execute_screen_command could be used in the future for handling
151// screen commands dynamically. For now, screen control is handled directly
152// in the Program struct.
153
154#[cfg(test)]
155mod tests {
156    use super::*;
157
158    #[test]
159    fn test_screen_commands_create() {
160        // Just verify the commands can be created without panicking
161        let _ = clear_screen();
162        let _ = enter_alt_screen();
163        let _ = exit_alt_screen();
164        let _ = show_cursor();
165        let _ = hide_cursor();
166        let _ = enable_mouse_cell_motion();
167        let _ = enable_mouse_all_motion();
168        let _ = disable_mouse();
169        let _ = enable_bracketed_paste();
170        let _ = disable_bracketed_paste();
171        let _ = enable_report_focus();
172        let _ = disable_report_focus();
173        let _ = release_terminal();
174        let _ = restore_terminal();
175    }
176}