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}