1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
#![deny(unused_imports, unused_must_use)] //! # Screen //! //! **The `crossterm_screen` crate is deprecated and no longer maintained. The GitHub repository will //! be archived soon. All the code is being moved to the `crossterm` //! [crate](https://github.com/crossterm-rs/crossterm). You can learn more in //! the [Merge sub-crates to the crossterm crate](https://github.com/crossterm-rs/crossterm/issues/265) //! issue.** //! //! The `crossterm_screen` crate provides the functionality to work with the terminal screen. //! //! This documentation does not contain a lot of examples. The reason is that it's fairly //! obvious how to use this crate. Although, we do provide //! [examples](https://github.com/crossterm-rs/examples) repository //! to demonstrate the capabilities. //! //! ## Screen Buffer //! //! A screen buffer is a two-dimensional array of characters and color data to be output in a console window. //! A terminal can have multiple of those screen buffers, and the active screen buffer is the one that is //! displayed on the screen. //! //! Crossterm allows you to switch between those buffers; the screen you are working in is called the //! 'main screen'. We call the other screen the 'alternate screen'. One note to take is that crossterm //! does not support the creation and switching between several buffers. //! //! ### Alternate Screen //! //! Normally you are working on the main screen but an alternate screen is somewhat different from a //! normal screen. For example, it has the exact dimensions of the terminal window, without any //! scroll back region. An example of this is vim when it is launched from bash. //! //! Vim uses the entirety of the screen to edit the file, then exits to bash leaving the original buffer unchanged. //! //! Crossterm provides the ability to switch to the alternate screen, make some changes, and then go back //! to the main screen. The main screen will still have its original data since we made all the edits on //! the alternate screen. //! //! ### Raw Mode //! //! By default, the terminal behaves in a certain way. //! You can think of going to a new line if the input is at the end of the current line, or interpreting backspace //! to remove letters. Sometimes it can be useful to disable these modes because this is undesirable. //! This may be undesirable if your application wants to read the input without it being shown on the screen. //! Raw modes are the modes to create this possibility. // //! Those modes will be set when enabling raw modes: //! //! - Input will not be forwarded to screen //! - Input will not be processed on enter press //! - Input will not be line buffered (input sent byte-by-byte to input buffer) //! - Special keys like backspace and CTL+C will not be processed by terminal driver //! - New line character will not be processed therefore `println!` can't be used, use `write!` instead // This brings the trait into scope, so we're able to call enter()/leave(), // but it it's false positive for unused_imports check #[allow(unused_imports)] use alternate::AlternateScreen as _; #[doc(no_inline)] pub use crossterm_utils::{ execute, queue, Command, ErrorKind, ExecutableCommand, QueueableCommand, Result, }; pub use self::raw::{IntoRawMode, RawScreen}; mod alternate; mod raw; mod sys; /// An alternate screen. /// /// With this type, you will be able to switch to the alternate screen and then back to /// the main screen. /// /// Be aware that you'll be switched back to the main screen when you drop the /// `AlternateScreen` value. /// /// It's recommended to use the command API. See the /// [`EnterAlternateScreen`](struct.EnterAlternateScreen.html) /// and [`LeaveAlternateScreen`](struct.LeaveAlternateScreen.html) /// commands documentation for more info. /// /// # Examples /// /// Alternate screen with raw mode enabled: /// /// ```no_run /// use crossterm_screen::AlternateScreen; /// use crossterm_utils::Result; /// /// fn main() -> Result<()> { /// let _alternate = AlternateScreen::to_alternate(true)?; /// /// // Do something on the alternate screen in the raw mode /// /// Ok(()) /// } // `_alternate` dropped here <- raw mode disabled & back to main screen /// ``` pub struct AlternateScreen { #[cfg(windows)] alternate: Box<(dyn alternate::AlternateScreen + Sync + Send)>, #[cfg(unix)] alternate: alternate::AnsiAlternateScreen, raw_screen: Option<RawScreen>, } impl AlternateScreen { /// Switches to the alternate screen. /// /// # Arguments /// /// * `raw_mode` - `true` enables the raw mode as well /// /// # Notes /// /// You'll be automatically switched to the main screen if this function /// fails. pub fn to_alternate(raw_mode: bool) -> Result<AlternateScreen> { let alternate = alternate::alternate_screen(); alternate.enter()?; let mut alternate = AlternateScreen { alternate, raw_screen: None, }; if raw_mode { // If into_raw_mode fails, `alternate` will be dropped and // we'll switch back to the main screen. alternate.raw_screen = Some(RawScreen::into_raw_mode()?); } Ok(alternate) } /// Switches to the main screen. pub fn to_main(&self) -> Result<()> { self.alternate.leave() } } impl Drop for AlternateScreen { fn drop(&mut self) { let _ = self.to_main(); } } /// A command to switch to the alternate screen. /// /// # Notes /// /// Commands must be executed/queued for execution otherwise they do nothing. /// /// # Examples /// /// ```no_run /// use std::io::{stdout, Write}; /// use crossterm_screen::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen}; /// /// fn main() -> Result<()> { /// execute!(stdout(), EnterAlternateScreen)?; /// /// // Do anything on the alternate screen /// /// execute!(stdout(), LeaveAlternateScreen) /// } /// ``` pub struct EnterAlternateScreen; impl Command for EnterAlternateScreen { type AnsiType = &'static str; fn ansi_code(&self) -> Self::AnsiType { alternate::ansi::ENTER_ALTERNATE_SCREEN_CSI_SEQUENCE } #[cfg(windows)] fn execute_winapi(&self) -> Result<()> { let alternate = alternate::alternate_screen(); alternate.enter() } } /// A command to switch back to the main screen. /// /// # Notes /// /// Commands must be executed/queued for execution otherwise they do nothing. /// /// # Examples /// /// ```no_run /// use std::io::{stdout, Write}; /// use crossterm_screen::{execute, Result, EnterAlternateScreen, LeaveAlternateScreen}; /// /// fn main() -> Result<()> { /// execute!(stdout(), EnterAlternateScreen)?; /// /// // Do anything on the alternate screen /// /// execute!(stdout(), LeaveAlternateScreen) /// } /// ``` pub struct LeaveAlternateScreen; impl Command for LeaveAlternateScreen { type AnsiType = &'static str; fn ansi_code(&self) -> Self::AnsiType { alternate::ansi::LEAVE_ALTERNATE_SCREEN_CSI_SEQUENCE } #[cfg(windows)] fn execute_winapi(&self) -> Result<()> { let alternate = alternate::alternate_screen(); alternate.leave() } }