use std::io::{self, IsTerminal, stdout};
use crate::{Event, Frame, pos::Size};
#[cfg(feature = "backend-ansi")]
pub mod ansi;
pub trait Backend {
fn step(&mut self) -> io::Result<Frame<'_, Event>>;
fn title(&mut self, title: &str) -> io::Result<()>;
}
pub fn open() -> io::Result<Box<dyn Backend>> {
#[allow(unused_assignments)]
let mut error = None;
macro_rules! attempt {
($($feat:literal),* => $ex:expr) => {
#[cfg(all($(feature = $feat)*))]
{
match $ex {
Ok(b) => return Ok(Box::new(b)),
Err(e) => error = Some(e),
}
}
}
}
attempt!("backend-ansi" => if stdout().is_terminal() {
ansi::Term::excl()
} else {
Err(io::Error::other("won't default to ansi terminal in non-TTY"))
});
match error {
None => unreachable!("attempted to `open` with no configured backends"),
Some(e) => Err(e),
}
}
impl Backend for () {
fn step(&mut self) -> io::Result<Frame<'_, Event>> {
Ok(Frame::null(Event::Close, Size::ZERO))
}
fn title(&mut self, _: &str) -> io::Result<()> {
Ok(())
}
}