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
//! This module contains all the logic for switching between alternate screen and main screen.
//!
//! *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
//! The alternate buffer is exactly the dimensions of the window, without any scrollback region.
//! For an example of this behavior, consider when vim is launched from bash.
//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
use super::commands::{self, IAlternateScreenCommand};
use super::{RawScreen, Screen, TerminalOutput};
use common::functions;
use std::convert::From;
use std::io;
/// With this type you will be able to switch to alternate screen and back to main screen.
/// Check also the Screen type for swishing to alternate mode.
///
/// Although this type is available for you to use I would recommend using `Screen` instead.
pub struct AlternateScreen {
command: Box<IAlternateScreenCommand + Sync + Send>,
pub screen: Screen,
}
impl AlternateScreen {
/// Create new instance of alternate screen.
pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self {
AlternateScreen { command, screen }
}
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
///
/// The bool specifies whether the screen should be in raw mode or not.
///
/// # What is Alternate screen?
/// *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
/// The alternate buffer is exactly the dimensions of the window, without any scrollback region.
/// For an example of this behavior, consider when vim is launched from bash.
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
pub fn to_alternate_screen(
stdout: TerminalOutput,
raw_mode: bool,
) -> io::Result<AlternateScreen> {
#[cfg(target_os = "windows")]
let command =
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
)
.unwrap();
#[cfg(not(target_os = "windows"))]
let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new());
let mut stdout = stdout;
command.enable(&mut stdout)?;
let screen = Screen::from(stdout);
if raw_mode {
RawScreen::into_raw_mode()?;
}
Ok(AlternateScreen::new(command, screen))
}
/// Switch the alternate screen back to main screen.
pub fn to_main_screen(&self) -> io::Result<()> {
self.command.disable(&self.screen.stdout)?;
Ok(())
}
}
impl Drop for AlternateScreen {
/// This will switch back to main screen on drop.
fn drop(&mut self) {
self.to_main_screen().unwrap();
}
}