use crate::{backend, backends, Cursive, CursiveRunner};
type Initializer = dyn FnMut() -> Result<Box<dyn backend::Backend>, Box<dyn std::error::Error>>;
pub struct CursiveRunnable {
siv: Cursive,
backend_init: Box<Initializer>,
}
impl Default for CursiveRunnable {
fn default() -> Self {
Self::with_initializer(Box::new(backends::try_default))
}
}
impl std::ops::Deref for CursiveRunnable {
type Target = Cursive;
fn deref(&self) -> &Cursive {
&self.siv
}
}
impl std::ops::DerefMut for CursiveRunnable {
fn deref_mut(&mut self) -> &mut Cursive {
&mut self.siv
}
}
impl std::borrow::Borrow<Cursive> for CursiveRunnable {
fn borrow(&self) -> &Cursive {
self
}
}
impl std::borrow::BorrowMut<Cursive> for CursiveRunnable {
fn borrow_mut(&mut self) -> &mut Cursive {
self
}
}
fn boxed(e: impl std::error::Error + 'static) -> Box<dyn std::error::Error> {
Box::new(e)
}
impl CursiveRunnable {
fn with_initializer(backend_init: Box<Initializer>) -> Self {
let siv = Cursive::new();
Self { siv, backend_init }
}
pub fn new<E, F>(mut backend_init: F) -> Self
where
E: std::error::Error + 'static,
F: FnMut() -> Result<Box<dyn backend::Backend>, E> + 'static,
{
Self::with_initializer(Box::new(move || backend_init().map_err(boxed)))
}
pub fn run(&mut self) {
self.try_run().unwrap();
}
pub fn try_run(&mut self) -> Result<(), Box<dyn std::error::Error>> {
self.siv.try_run_with(&mut self.backend_init)
}
pub fn try_runner(
&mut self,
) -> Result<CursiveRunner<&mut Cursive>, Box<dyn std::error::Error>> {
Ok(self.siv.runner((self.backend_init)()?))
}
pub fn runner(&mut self) -> CursiveRunner<&mut Cursive> {
self.try_runner().unwrap()
}
pub fn try_into_runner(mut self) -> Result<CursiveRunner<Self>, Box<dyn std::error::Error>> {
let backend = (self.backend_init)()?;
Ok(CursiveRunner::new(self, backend))
}
pub fn into_runner(self) -> CursiveRunner<Self> {
self.try_into_runner().unwrap()
}
pub fn dummy() -> Self {
Self::new::<std::convert::Infallible, _>(|| Ok(cursive_core::backend::Dummy::init()))
}
#[cfg(feature = "ncurses-backend")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "ncurses-backend")))]
pub fn ncurses() -> Self {
Self::new(backends::curses::n::Backend::init)
}
#[cfg(feature = "pancurses-backend")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "pancurses-backend")))]
pub fn pancurses() -> Self {
Self::new(backends::curses::pan::Backend::init)
}
#[cfg(feature = "termion-backend")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "termion-backend")))]
pub fn termion() -> Self {
Self::new(backends::termion::Backend::init)
}
#[cfg(feature = "crossterm-backend")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "crossterm-backend")))]
pub fn crossterm() -> Self {
Self::new(backends::crossterm::Backend::init)
}
#[cfg(feature = "blt-backend")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "blt-backend")))]
pub fn blt() -> Self {
Self::new::<std::convert::Infallible, _>(|| Ok(backends::blt::Backend::init()))
}
}