feat: crossterm backend can use alternate screen

This commit is contained in:
defiori 2019-02-08 13:03:18 +00:00 committed by Florian Dehau
parent 7290086fe9
commit b30cae0473

View file

@ -8,12 +8,20 @@ use crossterm::error::ErrorKind;
pub struct CrosstermBackend { pub struct CrosstermBackend {
screen: crossterm::Screen, screen: crossterm::Screen,
crossterm: crossterm::Crossterm,
// Need to keep the AlternateScreen around even when not using it directly,
// see https://github.com/TimonPost/crossterm/issues/88
alternate_screen: Option<crossterm::AlternateScreen>,
} }
impl Default for CrosstermBackend { impl Default for CrosstermBackend {
fn default() -> CrosstermBackend { fn default() -> CrosstermBackend {
let screen = crossterm::Screen::default();
let crossterm = crossterm::Crossterm::from_screen(&screen);
CrosstermBackend { CrosstermBackend {
screen: crossterm::Screen::default(), screen,
crossterm,
alternate_screen: None,
} }
} }
} }
@ -24,12 +32,38 @@ impl CrosstermBackend {
} }
pub fn with_screen(screen: crossterm::Screen) -> CrosstermBackend { pub fn with_screen(screen: crossterm::Screen) -> CrosstermBackend {
CrosstermBackend { screen: screen } let crossterm = crossterm::Crossterm::from_screen(&screen);
CrosstermBackend {
screen,
crossterm,
alternate_screen: None,
}
}
pub fn with_alternate_screen(screen: crossterm::Screen, raw_mode: bool) -> Result<CrosstermBackend, io::Error> {
let alternate_screen = screen.enable_alternate_modes(raw_mode)?;
let crossterm = crossterm::Crossterm::from_screen(&alternate_screen.screen);
Ok(CrosstermBackend {
screen,
crossterm,
alternate_screen: Some(alternate_screen),
})
} }
pub fn screen(&self) -> &crossterm::Screen { pub fn screen(&self) -> &crossterm::Screen {
&self.screen &self.screen
} }
pub fn alternate_screen(&self) -> Option<&crossterm::AlternateScreen> {
match &self.alternate_screen {
Some(alt_screen) => Some(&alt_screen),
None => None,
}
}
pub fn crossterm(&self) -> &crossterm::Crossterm {
&self.crossterm
}
} }
// TODO: consider associated Error type on Backend to allow custom error types // TODO: consider associated Error type on Backend to allow custom error types
@ -50,7 +84,7 @@ fn convert_error(error: ErrorKind) -> io::Error {
impl Backend for CrosstermBackend { impl Backend for CrosstermBackend {
fn clear(&mut self) -> io::Result<()> { fn clear(&mut self) -> io::Result<()> {
let terminal = crossterm::terminal(); let terminal = self.crossterm.terminal();
terminal terminal
.clear(crossterm::ClearType::All) .clear(crossterm::ClearType::All)
.map_err(convert_error)?; .map_err(convert_error)?;
@ -58,13 +92,13 @@ impl Backend for CrosstermBackend {
} }
fn hide_cursor(&mut self) -> io::Result<()> { fn hide_cursor(&mut self) -> io::Result<()> {
let cursor = crossterm::cursor(); let cursor = self.crossterm.cursor();
cursor.hide().map_err(convert_error)?; cursor.hide().map_err(convert_error)?;
Ok(()) Ok(())
} }
fn show_cursor(&mut self) -> io::Result<()> { fn show_cursor(&mut self) -> io::Result<()> {
let cursor = crossterm::cursor(); let cursor = self.crossterm.cursor();
cursor.show().map_err(convert_error)?; cursor.show().map_err(convert_error)?;
Ok(()) Ok(())
} }
@ -80,7 +114,7 @@ impl Backend for CrosstermBackend {
} }
fn size(&self) -> io::Result<Rect> { fn size(&self) -> io::Result<Rect> {
let terminal = crossterm::terminal(); let terminal = self.crossterm.terminal();
let (width, height) = terminal.terminal_size(); let (width, height) = terminal.terminal_size();
Ok(Rect::new(0, 0, width, height)) Ok(Rect::new(0, 0, width, height))
} }
@ -93,8 +127,7 @@ impl Backend for CrosstermBackend {
where where
I: Iterator<Item = (u16, u16, &'a Cell)>, I: Iterator<Item = (u16, u16, &'a Cell)>,
{ {
let cursor = crossterm::cursor(); let cursor = self.crossterm.cursor();
let crossterm = crossterm::Crossterm::from_screen(&self.screen);
let mut last_y = 0; let mut last_y = 0;
let mut last_x = 0; let mut last_x = 0;
let mut first = true; let mut first = true;
@ -105,8 +138,7 @@ impl Backend for CrosstermBackend {
} }
last_x = x; last_x = x;
last_y = y; last_y = y;
let mut s = self.crossterm.style(&cell.symbol);
let mut s = crossterm::style(&cell.symbol);
if let Some(color) = cell.style.fg.into() { if let Some(color) = cell.style.fg.into() {
s = s.with(color) s = s.with(color)
} }
@ -116,7 +148,7 @@ impl Backend for CrosstermBackend {
if let Some(attr) = cell.style.modifier.into() { if let Some(attr) = cell.style.modifier.into() {
s = s.attr(attr) s = s.attr(attr)
} }
crossterm.paint(s).map_err(convert_error)?; self.crossterm.paint(s).map_err(convert_error)?;
} }
Ok(()) Ok(())
} }