use crossterm_utils::TerminalOutput;
use std::fmt::Display;
use std::io::{self, Write};
use std::sync::Arc;
pub struct Crossterm {
stdout: Option<Arc<TerminalOutput>>,
}
impl<'crossterm> Crossterm {
pub fn new() -> Crossterm {
Crossterm { stdout: None }
}
#[cfg(feature = "screen")]
pub fn from_screen(screen: &crossterm_screen::Screen) -> Crossterm {
Crossterm {
stdout: Some(screen.stdout.clone()),
}
}
#[cfg(feature = "cursor")]
pub fn cursor(&self) -> crossterm_cursor::TerminalCursor {
match &self.stdout {
None => crossterm_cursor::TerminalCursor::new(),
Some(stdout) => crossterm_cursor::TerminalCursor::from_output(&stdout),
}
}
#[cfg(feature = "input")]
pub fn input(&self) -> crossterm_input::TerminalInput {
match &self.stdout {
None => crossterm_input::TerminalInput::new(),
Some(stdout) => crossterm_input::TerminalInput::from_output(&stdout),
}
}
#[cfg(feature = "terminal")]
pub fn terminal(&self) -> crossterm_terminal::Terminal {
match &self.stdout {
None => crossterm_terminal::Terminal::new(),
Some(stdout) => crossterm_terminal::Terminal::from_output(&stdout),
}
}
#[cfg(feature = "style")]
pub fn color(&self) -> crossterm_style::TerminalColor {
match &self.stdout {
None => crossterm_style::TerminalColor::new(),
Some(stdout) => crossterm_style::TerminalColor::from_output(&stdout),
}
}
#[cfg(feature = "style")]
pub fn style<D>(&self, val: D) -> crossterm_style::StyledObject<D>
where
D: Display,
{
crossterm_style::ObjectStyle::new().apply_to(val)
}
#[cfg(feature = "style")]
#[cfg(feature = "screen")]
pub fn paint<'a, D: Display + 'a>(
&self,
styled_object: crossterm_style::StyledObject<D>,
) -> super::crossterm_utils::Result<()> {
let colored_terminal = match &self.stdout {
Some(stdout) => super::TerminalColor::from_output(stdout),
None => super::TerminalColor::new(),
};
let mut reset = false;
if let Some(bg) = styled_object.object_style.bg_color {
colored_terminal.set_bg(bg)?;
reset = true;
}
if let Some(fg) = styled_object.object_style.fg_color {
colored_terminal.set_fg(fg)?;
reset = true;
}
match self.stdout {
None => {
let mut stdout = io::stdout();
for attr in styled_object.object_style.attrs.iter() {
write!(stdout, "{}", format!(csi!("{}m"), *attr as i16))?;
reset = true;
}
write!(stdout, "{}", styled_object.content)?;
}
Some(ref stdout) => {
for attr in styled_object.object_style.attrs.iter() {
stdout.write_string(format!(csi!("{}m"), *attr as i16))?;
reset = true;
}
use std::fmt::Write;
let mut content = String::new();
write!(content, "{}", styled_object.content)?;
stdout.write_string(content)?;
stdout.flush()?;
}
}
if reset {
colored_terminal.reset()?;
}
Ok(())
}
}
impl From<Arc<TerminalOutput>> for Crossterm {
fn from(stdout: Arc<TerminalOutput>) -> Self {
Crossterm {
stdout: Some(stdout),
}
}
}