termion/
screen.rs

1//! Managing switching between main and alternate screen buffers.
2//!
3//! Note that this implementation uses xterm's new escape sequences for screen switching and thus
4//! only works for xterm compatible terminals (which should be most terminals nowadays).
5//!
6//! # Example
7//!
8//! ```rust
9//! use termion::screen::IntoAlternateScreen;
10//! use std::io::{Write, stdout};
11//!
12//! fn main() {
13//!     {
14//!         let mut screen = stdout().into_alternate_screen().unwrap();
15//!         write!(screen, "Writing to alternate screen!").unwrap();
16//!         screen.flush().unwrap();
17//!     }
18//!     println!("Writing to main screen.");
19//! }
20//! ```
21
22use std::fmt;
23use std::io::{self, Write};
24use std::ops;
25
26/// Switch to the main screen buffer of the terminal.
27pub struct ToMainScreen;
28
29impl fmt::Display for ToMainScreen {
30    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31        write!(f, csi!("?1049l"))
32    }
33}
34
35/// Switch to the alternate screen buffer of the terminal.
36pub struct ToAlternateScreen;
37
38impl fmt::Display for ToAlternateScreen {
39    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40        write!(f, csi!("?1049h"))
41    }
42}
43
44/// A terminal restorer, which wraps a type implementing Write, and causes all writes to be written
45/// to an alternate screen.
46///
47/// This is achieved by switching the terminal to the alternate screen on creation and
48/// automatically switching it back to the original screen on drop.
49pub struct AlternateScreen<W: Write> {
50    /// The output target.
51    output: W,
52}
53
54/// Extension trait for writers, providing the `into_alternate_screen` function.
55pub trait IntoAlternateScreen: Write + Sized {
56    /// Switch the terminal controlled by this writer to use the alternate screen. The terminal will be
57    /// restored to the main screen when the `AlternateScreen` returned by this function is
58    /// dropped.
59    fn into_alternate_screen(mut self) -> io::Result<AlternateScreen<Self>> {
60        write!(self, "{}", ToAlternateScreen)?;
61        Ok(AlternateScreen { output: self })
62    }
63}
64
65impl<W: Write> IntoAlternateScreen for W {}
66
67impl<W: Write> Drop for AlternateScreen<W> {
68    fn drop(&mut self) {
69        let _ = write!(self, "{}", ToMainScreen);
70    }
71}
72
73impl<W: Write> ops::Deref for AlternateScreen<W> {
74    type Target = W;
75
76    fn deref(&self) -> &W {
77        &self.output
78    }
79}
80
81impl<W: Write> ops::DerefMut for AlternateScreen<W> {
82    fn deref_mut(&mut self) -> &mut W {
83        &mut self.output
84    }
85}
86
87impl<W: Write> Write for AlternateScreen<W> {
88    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
89        self.output.write(buf)
90    }
91
92    fn flush(&mut self) -> io::Result<()> {
93        self.output.flush()
94    }
95}