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::AlternateScreen;
10//! use std::io::{Write, stdout};
11//!
12//! fn main() {
13//!     {
14//!         let mut screen = AlternateScreen::from(stdout());
15//!         write!(screen, "Writing to alternate screen!").unwrap();
16//!         screen.flush().unwrap();
17//!     }
18//!     println!("Writing to main screen.");
19//! }
20//! ```
21
22use std::io::{self, Write};
23use std::ops;
24use std::fmt;
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
54impl<W: Write> AlternateScreen<W> {
55    /// Create an alternate screen wrapper struct for the provided output and switch the terminal
56    /// to the alternate screen.
57    pub fn from(mut output: W) -> Self {
58        write!(output, "{}", ToAlternateScreen).expect("switch to alternate screen");
59        AlternateScreen { output: output }
60    }
61}
62
63impl<W: Write> Drop for AlternateScreen<W> {
64    fn drop(&mut self) {
65        write!(self, "{}", ToMainScreen).expect("switch to main screen");
66    }
67}
68
69impl<W: Write> ops::Deref for AlternateScreen<W> {
70    type Target = W;
71
72    fn deref(&self) -> &W {
73        &self.output
74    }
75}
76
77impl<W: Write> ops::DerefMut for AlternateScreen<W> {
78    fn deref_mut(&mut self) -> &mut W {
79        &mut self.output
80    }
81}
82
83impl<W: Write> Write for AlternateScreen<W> {
84    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
85        self.output.write(buf)
86    }
87
88    fn flush(&mut self) -> io::Result<()> {
89        self.output.flush()
90    }
91}