Cursive::ncurses & cie now return io::Result<Self>

This commit is contained in:
Alexandre Bury 2019-03-03 19:24:39 -08:00
parent dcee6da16a
commit f765e9ac07
6 changed files with 46 additions and 31 deletions

View File

@ -8,6 +8,9 @@
`find_id()` was added instead.
- Breaking change: replaced `set_fps(i32)` with `set_autorefresh(bool)`
- Breaking change: updated the Backend trait for a simpler input system
- Breaking change: `Cursive::{ncurses, pancurses, termion}` now return
`io::Result<Self>` instead of panicking. `Cursive::default()` still unwraps.
- Also added `Cursive::try_new` for failible backends.
- Updated to Rust 2018 (now requires rustc > 1.31)
- Add a logging implementation (`logger::init()`) and a `DebugConsole`
(`cursive::toggle_debug_console()`)

View File

@ -32,6 +32,7 @@ pub struct Backend {
impl Backend {
/// Creates a new BearLibTerminal-based backend.
pub fn init() -> Box<dyn backend::Backend> {
// TODO: Add some error handling?
terminal::open("Cursive", 80, 24);
terminal::set(terminal::config::Window::empty().resizeable(true));
terminal::set(vec![

View File

@ -58,13 +58,16 @@ fn write_to_tty(bytes: &[u8]) -> io::Result<()> {
impl Backend {
/// Creates a new ncurses-based backend.
pub fn init() -> Box<dyn backend::Backend> {
pub fn init() -> io::Result<Box<dyn backend::Backend>> {
// Check the $TERM variable.
if std::env::var("TERM")
.map(|var| var.is_empty())
.unwrap_or(true)
{
panic!("$TERM is unset. Cannot initialize ncurses interface.");
return Err(io::Error::new(
io::ErrorKind::Other,
"$TERM is unset. Cannot initialize ncurses interface.",
));
}
// Change the locale.
@ -111,7 +114,7 @@ impl Backend {
// This asks the terminal to provide us with mouse drag events
// (Mouse move when a button is pressed).
// Replacing 1002 with 1003 would give us ANY mouse move.
write_to_tty(b"\x1B[?1002h").unwrap();
write_to_tty(b"\x1B[?1002h")?;
let c = Backend {
current_style: Cell::new(ColorPair::from_256colors(0, 0)),
@ -121,7 +124,7 @@ impl Backend {
input_buffer: None,
};
Box::new(c)
Ok(Box::new(c))
}
/// Save a new color pair.

View File

@ -34,10 +34,12 @@ fn find_closest_pair(pair: ColorPair) -> (i16, i16) {
impl Backend {
/// Creates a new pancurses-based backend.
pub fn init() -> Box<dyn backend::Backend> {
pub fn init() -> std::io::Result<Box<dyn backend::Backend>> {
::std::env::set_var("ESCDELAY", "25");
// TODO: use pancurses::newterm()
let window = pancurses::initscr();
window.keypad(true);
window.timeout(0);
pancurses::noecho();
@ -55,7 +57,7 @@ impl Backend {
// (Mouse move when a button is pressed).
// Replacing 1002 with 1003 would give us ANY mouse move.
print!("\x1B[?1002h");
stdout().flush().expect("could not flush stdout");
stdout().flush()?;
let c = Backend {
current_style: Cell::new(ColorPair::from_256colors(0, 0)),
@ -66,7 +68,7 @@ impl Backend {
window,
};
Box::new(c)
Ok(Box::new(c))
}
/// Save a new color pair.

View File

@ -43,20 +43,16 @@ pub struct Backend {
impl Backend {
/// Creates a new termion-based backend.
pub fn init() -> Box<dyn backend::Backend> {
pub fn init() -> std::io::Result<Box<dyn backend::Backend>> {
// Use a ~8MB buffer
// Should be enough for a single screen most of the time.
let terminal =
RefCell::new(AlternateScreen::from(MouseTerminal::from(
BufWriter::with_capacity(
8_000_000,
File::create("/dev/tty").unwrap(),
)
.into_raw_mode()
.unwrap(),
BufWriter::with_capacity(8_000_000, File::create("/dev/tty")?)
.into_raw_mode()?,
)));
write!(terminal.borrow_mut(), "{}", termion::cursor::Hide).unwrap();
write!(terminal.borrow_mut(), "{}", termion::cursor::Hide)?;
let (input_sender, input_receiver) = crossbeam_channel::unbounded();
let (resize_sender, resize_receiver) = crossbeam_channel::bounded(0);
@ -96,7 +92,7 @@ impl Backend {
resize_receiver,
};
Box::new(c)
Ok(Box::new(c))
}
fn apply_colors(&self, colors: theme::ColorPair) {

View File

@ -75,14 +75,14 @@ impl<F: FnOnce(&mut Cursive) -> () + Send> CbFunc for F {
#[cfg(feature = "termion-backend")]
impl Default for Cursive {
fn default() -> Self {
Self::termion()
Self::termion().unwrap()
}
}
#[cfg(all(not(feature = "termion-backend"), feature = "pancurses-backend"))]
impl Default for Cursive {
fn default() -> Self {
Self::pancurses()
Self::pancurses().unwrap()
}
}
@ -105,11 +105,23 @@ impl Default for Cursive {
))]
impl Default for Cursive {
fn default() -> Self {
Self::ncurses()
Self::ncurses().unwrap()
}
}
impl Cursive {
/// Shortcut for `Cursive::try_new` with non-failible init function.
///
/// You probably don't want to use this function directly. Instead,
/// `Cursive::default()` or `Cursive::ncurses()` may be what you're
/// looking for.
pub fn new<F>(backend_init: F) -> Self
where
F: FnOnce() -> Box<dyn backend::Backend>,
{
Self::try_new::<_, ()>(|| Ok(backend_init())).unwrap()
}
/// Creates a new Cursive root, and initialize the back-end.
///
/// * If you just want a cursive instance, use `Cursive::default()`.
@ -128,17 +140,15 @@ impl Cursive {
/// # use cursive::{Cursive, backend};
/// let siv = Cursive::new(backend::dummy::Backend::init); // equivalent to Cursive::dummy()
/// ```
pub fn new<F>(backend_init: F) -> Self
pub fn try_new<F, E>(backend_init: F) -> Result<Self, E>
where
F: FnOnce() -> Box<dyn backend::Backend>,
F: FnOnce() -> Result<Box<dyn backend::Backend>, E>,
{
let theme = theme::load_default();
let (cb_sink, cb_source) = crossbeam_channel::unbounded();
let backend = backend_init();
Cursive {
backend_init().map(|backend| Cursive {
autorefresh: false,
theme,
screens: vec![views::StackView::new()],
@ -151,25 +161,25 @@ impl Cursive {
cb_sink,
backend,
user_data: Box::new(()),
}
})
}
/// Creates a new Cursive root using a ncurses backend.
#[cfg(feature = "ncurses-backend")]
pub fn ncurses() -> Self {
Self::new(backend::curses::n::Backend::init)
pub fn ncurses() -> std::io::Result<Self> {
Self::try_new(backend::curses::n::Backend::init)
}
/// Creates a new Cursive root using a pancurses backend.
#[cfg(feature = "pancurses-backend")]
pub fn pancurses() -> Self {
Self::new(backend::curses::pan::Backend::init)
pub fn pancurses() -> std::io::Result<Self> {
Self::try_new(backend::curses::pan::Backend::init)
}
/// Creates a new Cursive root using a termion backend.
#[cfg(feature = "termion-backend")]
pub fn termion() -> Self {
Self::new(backend::termion::Backend::init)
pub fn termion() -> std::io::Result<Self> {
Self::try_new(backend::termion::Backend::init)
}
/// Creates a new Cursive root using a bear-lib-terminal backend.