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}