rust: continue refactoring the error system.

- made const NotcursesOptions constructors.
- refactor Notcurses constructors to return NcResult.
- pass NotcursesOptions by value, since it's Copy.
- update tests.
- add helper modules for Notcurses & NcPlane.
  - new initialization functions to be used in tests.
- BONUS:
  - refactor NcDirect
  - update examples.
This commit is contained in:
joseLuís 2020-12-25 19:35:21 +01:00
parent b8c33a6caf
commit 6049e07d27
15 changed files with 143 additions and 122 deletions

View File

@ -22,9 +22,8 @@ fn main() -> NcResult<()> {
sleep![50];
}
if let Some((cy, cx)) = ncd.cursor_yx() {
ncd.putstr(0, &format!(" ({},{})\n", cy, cx))?;
}
let (cy, cx) = ncd.cursor_yx()?;
ncd.putstr(0, &format!(" ({},{})\n", cy, cx))?;
sleep![1000];
let sentence = vec!["And", "now", "I", "will", "clear", "the", "screen", ".", ".", "."];

View File

@ -1,8 +1,8 @@
use libnotcurses_sys::*;
fn main() {
fn main() -> NcResult<()> {
unsafe {
let nc = Notcurses::new();
let nc = Notcurses::new()?;
let stdplane = notcurses_stdplane(nc);
for ch in "Initializing cells...".chars() {
@ -15,4 +15,5 @@ fn main() {
notcurses_stop(nc);
}
Ok(())
}

View File

@ -5,12 +5,12 @@
use libnotcurses_sys::*;
fn main() {
fn main() -> NcResult<()> {
let nc = Notcurses::with_flags(
NCOPTION_SUPPRESS_BANNERS
| NCOPTION_NO_WINCH_SIGHANDLER
| NCOPTION_NO_QUIT_SIGHANDLERS
);
)?;
// doesn't seem to be necessary:
// let ready = unsafe { notcurses_inputready_fd(nc) };
@ -38,5 +38,6 @@ fn main() {
println!("\nExiting...");
rsleep![nc, 1000];
nc.stop();
nc.stop()?;
Ok(())
}

View File

@ -2,9 +2,9 @@
use libnotcurses_sys::*;
fn main() {
fn main() -> NcResult<()> {
let nc = Notcurses::new();
let nc = Notcurses::new()?;
let plane = nc.stdplane();
plane.set_scrolling(true);
@ -27,5 +27,6 @@ fn main() {
break;
}
}
nc.stop();
nc.stop()?;
Ok(())
}

View File

@ -29,7 +29,7 @@ fn main() -> NcResult<()> {
let (mut y, x);
if let Some((_y, _x)) = ncd.cursor_yx() {
if let Ok((_y, _x)) = ncd.cursor_yx() {
y = _y;
x = _x;
printf!("\n\tRead cursor position: y: %d x: %d\n", y, x);
@ -42,7 +42,7 @@ fn main() -> NcResult<()> {
y -= up;
let newy;
if let Some((_y, _)) = ncd.cursor_yx() {
if let Ok((_y, _)) = ncd.cursor_yx() {
newy = _y;
} else {
break;

View File

@ -6,12 +6,13 @@ use serial_test::serial;
#[test]
#[serial]
fn constructors() {
fn constructors() -> crate::NcResult<()> {
let _c1 = NcCell::new();
let _c2 = NcCell::with_char7b('C');
let _n0 = Notcurses::new();
let _p0 = NcPlane::new(_n0, 0, 0, 10, 10);
let _c3 = NcCell::with_char('௵', _p0);
_n0.stop();
let nc = Notcurses::new()?;
let plane = NcPlane::new(nc, 0, 0, 10, 10);
let _c3 = NcCell::with_char('௵', plane);
nc.stop()?;
Ok(())
}

View File

@ -6,7 +6,7 @@ use crate::ffi::sigset_t;
use crate::{
cstring, error, NcAlign, NcBlitter, NcChannelPair, NcColor, NcDimension, NcDirect,
NcDirectFlags, NcEgc, NcError, NcInput, NcPaletteIndex, NcResult, NcRgb, NcScale, NcStyleMask,
NcTime, NCRESULT_ERR, NCRESULT_OK,
NcTime, NCRESULT_ERR,
};
/// # `NcDirect` constructors and destructors
@ -35,7 +35,7 @@ impl NcDirect {
pub fn with_flags<'a>(flags: NcDirectFlags) -> NcResult<&'a mut NcDirect> {
let res = unsafe { crate::ncdirect_init(null(), null_mut(), flags) };
if res == null_mut() {
return Err(NcError::new(NCRESULT_ERR));
return Err(NcError::with_msg(NCRESULT_ERR, "Initializing NcDirect"));
}
Ok(unsafe { &mut *res })
}
@ -272,16 +272,15 @@ impl NcDirect {
///
/// This requires writing to the terminal, and then reading from it.
/// If the terminal doesn't reply, or doesn't reply in a way we understand,
/// the results might be deleterious.
/// the results might be detrimental.
///
/// *C style function: [ncdirect_cursor_yx()][crate::ncdirect_cursor_yx].*
pub fn cursor_yx(&mut self) -> Option<(NcDimension, NcDimension)> {
pub fn cursor_yx(&mut self) -> NcResult<(NcDimension, NcDimension)> {
let (mut y, mut x) = (0, 0);
let res = unsafe { crate::ncdirect_cursor_yx(self, &mut y, &mut x) };
if res == NCRESULT_OK {
return Some((y as NcDimension, x as NcDimension));
}
None
error![
unsafe { crate::ncdirect_cursor_yx(self, &mut y, &mut x) },
(y as NcDimension, x as NcDimension)
]
}
/// Pushes the cursor location to the terminal's stack.

View File

@ -13,12 +13,13 @@
//! ```rust
//! use libnotcurses_sys::*;
//!
//! fn main() {
//! let nc = Notcurses::without_altscreen();
//! fn main() -> NcResult<()> {
//! let nc = Notcurses::without_altscreen()?;
//! let plane = nc.stdplane();
//! plane.putstr("hello world");
//! nc.render();
//! nc.stop();
//! nc.stop()?;
//! Ok(())
//! }
//! ```
//!
@ -37,8 +38,8 @@
//!
//! fn main() {
//! let options = NotcursesOptions::with_flags(NCOPTION_NO_ALTERNATE_SCREEN);
//! let nc = Notcurses::with_options(&options);
//! unsafe {
//! let nc = notcurses_init(&options, core::ptr::null_mut());
//! let plane = notcurses_stdplane(nc);
//! ncplane_putstr(&mut *plane, "hello world");
//! notcurses_render(nc);

View File

@ -0,0 +1,10 @@
use crate::{notcurses_init, Notcurses, NotcursesOptions, NCOPTION_SUPPRESS_BANNERS};
/// Helper function for initializing Notcurses on C style tests.
#[allow(dead_code)]
pub(crate) unsafe fn notcurses_init_test<'a>() -> &'a mut Notcurses {
&mut *notcurses_init(
&NotcursesOptions::with_flags(NCOPTION_SUPPRESS_BANNERS),
core::ptr::null_mut(),
)
}

View File

@ -4,26 +4,31 @@ use core::ptr::{null, null_mut};
use std::ffi::CStr;
use crate::{
cstring, notcurses_init, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc, NcFile,
NcInput, NcIntResult, NcLogLevel, NcPlane, NcScale, NcSignalSet, NcStats, NcStyleMask, NcTime,
Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS,
NCRESULT_ERR, NCRESULT_OK,
cstring, error, notcurses_init, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc, NcError,
NcFile, NcInput, NcIntResult, NcLogLevel, NcPlane, NcResult, NcScale, NcSignalSet, NcStats,
NcStyleMask, NcTime, Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN,
NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, NCRESULT_OK,
};
/// # `NotcursesOptions` Constructors
impl NotcursesOptions {
/// New NotcursesOptions.
pub fn new() -> Self {
pub const fn new() -> Self {
Self::with_all_options(0, 0, 0, 0, 0, 0)
}
/// New NotcursesOptions, with margins.
pub fn with_margins(top: i32, right: i32, bottom: i32, left: i32) -> Self {
pub const fn with_margins(
top: NcDimension,
right: NcDimension,
bottom: NcDimension,
left: NcDimension,
) -> Self {
Self::with_all_options(0, top, right, bottom, left, 0)
}
/// New NotcursesOptions, with flags.
pub fn with_flags(flags: u64) -> Self {
pub const fn with_flags(flags: u64) -> Self {
Self::with_all_options(0, 0, 0, 0, 0, flags)
}
@ -58,22 +63,22 @@ impl NotcursesOptions {
/// - [`NCOPTION_NO_WINCH_SIGHANDLER`][crate::NCOPTION_NO_WINCH_SIGHANDLER]
/// - [`NCOPTION_SUPPRESS_BANNERS`]
///
pub fn with_all_options(
pub const fn with_all_options(
loglevel: NcLogLevel,
margin_t: i32,
margin_r: i32,
margin_b: i32,
margin_l: i32,
margin_t: NcDimension,
margin_r: NcDimension,
margin_b: NcDimension,
margin_l: NcDimension,
flags: u64,
) -> Self {
Self {
termtype: null(),
renderfp: null_mut(),
loglevel,
margin_t,
margin_r,
margin_b,
margin_l,
margin_t: margin_t as i32,
margin_r: margin_r as i32,
margin_b: margin_b as i32,
margin_l: margin_l as i32,
flags,
}
}
@ -82,38 +87,37 @@ impl NotcursesOptions {
/// # `Notcurses` Constructors
impl Notcurses {
/// Returns a Notcurses context (without banners).
pub fn new<'a>() -> &'a mut Notcurses {
let options = NotcursesOptions::with_flags(NCOPTION_SUPPRESS_BANNERS);
unsafe { &mut *notcurses_init(&options, null_mut()) }
pub fn new<'a>() -> NcResult<&'a mut Notcurses> {
Self::with_flags(NCOPTION_SUPPRESS_BANNERS)
}
/// Returns a Notcurses context, with banners. The default in the C library.
pub fn with_banners<'a>() -> &'a mut Notcurses {
unsafe { &mut *notcurses_init(&NotcursesOptions::new(), null_mut()) }
pub fn with_banners<'a>() -> NcResult<&'a mut Notcurses> {
Self::with_flags(0)
}
/// Returns a Notcurses context, without an alternate screen (nor banners).
pub fn without_altscreen<'a>() -> &'a mut Notcurses {
let options =
NotcursesOptions::with_flags(NCOPTION_NO_ALTERNATE_SCREEN | NCOPTION_SUPPRESS_BANNERS);
unsafe { &mut *notcurses_init(&options, null_mut()) }
pub fn without_altscreen<'a>() -> NcResult<&'a mut Notcurses> {
Self::with_flags(NCOPTION_NO_ALTERNATE_SCREEN | NCOPTION_SUPPRESS_BANNERS)
}
/// Returns a Notcurses context, without an alternate screen, with banners.
pub fn without_altscreen_nor_banners<'a>() -> &'a mut Notcurses {
let options = NotcursesOptions::with_flags(NCOPTION_NO_ALTERNATE_SCREEN);
unsafe { &mut *notcurses_init(&options, null_mut()) }
pub fn without_altscreen_nor_banners<'a>() -> NcResult<&'a mut Notcurses> {
Self::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)
}
/// Returns a Notcurses context, expects [NotcursesOptions].
pub fn with_flags<'a>(flags: u64) -> &'a mut Notcurses {
let options = NotcursesOptions::with_flags(flags);
unsafe { &mut *notcurses_init(&options, null_mut()) }
pub fn with_flags<'a>(flags: u64) -> NcResult<&'a mut Notcurses> {
Self::with_options(NotcursesOptions::with_flags(flags))
}
/// Returns a Notcurses context, expects [NotcursesOptions].
pub fn with_options<'a>(options: &NotcursesOptions) -> &'a mut Notcurses {
unsafe { &mut *notcurses_init(options, null_mut()) }
pub fn with_options<'a>(options: NotcursesOptions) -> NcResult<&'a mut Notcurses> {
let res = unsafe { notcurses_init(&options, null_mut()) };
if res == null_mut() {
return Err(NcError::with_msg(NCRESULT_ERR, "Initializing Notcurses"));
}
Ok(unsafe { &mut *res })
}
}
@ -542,8 +546,8 @@ impl Notcurses {
/// Destroys the Notcurses context.
///
/// *C style function: [notcurses_stop()][crate::notcurses_stop].*
pub fn stop(&mut self) -> NcIntResult {
unsafe { crate::notcurses_stop(self) }
pub fn stop(&mut self) -> NcResult<()> {
error![unsafe { crate::notcurses_stop(self) }]
}
/// Gets the name of an [NcBlitter] blitter.

View File

@ -63,8 +63,12 @@
#[cfg(test)]
mod test;
mod helpers;
mod methods;
mod reimplemented;
#[allow(unused_imports)]
pub(crate) use helpers::*;
pub use reimplemented::*;
/// The main struct of the TUI library (full mode)

View File

@ -3,13 +3,13 @@
use serial_test::serial;
use std::io::Read;
use crate::{notcurses_stop, NcFile, Notcurses, NCRESULT_MAX};
use crate::{notcurses_init_test, notcurses_stop, NcFile, NCRESULT_MAX};
#[test]
#[serial]
fn notcurses_align() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
assert_eq![0, crate::notcurses_align(30, crate::NCALIGN_LEFT, 20)];
assert_eq![5, crate::notcurses_align(30, crate::NCALIGN_CENTER, 20)];
assert_eq![10, crate::notcurses_align(30, crate::NCALIGN_RIGHT, 20)];
@ -25,7 +25,7 @@ fn notcurses_align() {
#[serial]
fn notcurses_canchangecolor() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_canchangecolor(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -36,7 +36,7 @@ fn notcurses_canchangecolor() {
#[serial]
fn notcurses_canfade() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_canfade(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -47,7 +47,7 @@ fn notcurses_canfade() {
#[serial]
fn notcurses_canopen_images() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_canopen_images(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -58,7 +58,7 @@ fn notcurses_canopen_images() {
#[serial]
fn notcurses_canopen_videos() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_canopen_videos(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -69,7 +69,7 @@ fn notcurses_canopen_videos() {
#[serial]
fn notcurses_cansixel() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_cansixel(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -80,7 +80,7 @@ fn notcurses_cansixel() {
#[serial]
fn notcurses_cantruecolor() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_cantruecolor(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -91,7 +91,7 @@ fn notcurses_cantruecolor() {
#[serial]
fn notcurses_canutf8() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let res = crate::notcurses_canutf8(nc);
notcurses_stop(nc);
print!("[{}] ", res);
@ -102,7 +102,7 @@ fn notcurses_canutf8() {
#[serial]
fn notcurses_drop_planes() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let stdplane = crate::notcurses_stdplane(nc);
let plane1 = crate::NcPlane::new_bound(&mut *stdplane, 0, 0, 10, 10);
let _plane2 = crate::NcPlane::new_bound(&mut *plane1, 0, 0, 10, 10);
@ -116,9 +116,9 @@ fn notcurses_drop_planes() {
#[test]
#[serial]
fn notcurses_init() {
fn notcurses_initialization() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
assert![nc as *mut _ != core::ptr::null_mut()];
notcurses_stop(nc);
}
@ -130,7 +130,7 @@ fn notcurses_init() {
// FIXME: always return null
fn notcurses_at_yx() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let mut sm = 0;
let mut ch = 0;
let res = crate::notcurses_at_yx(nc, 0, 0, &mut sm, &mut ch);
@ -145,7 +145,7 @@ fn notcurses_at_yx() {
#[serial]
fn notcurses_debug() {
unsafe {
let nc = Notcurses::new();
let nc = notcurses_init_test();
let mut _p: *mut i8 = &mut 0;
let mut _size: *mut usize = &mut 0;
let mut file = NcFile::from_libc(libc::open_memstream(&mut _p, _size));

13
rust/src/plane/helpers.rs Normal file
View File

@ -0,0 +1,13 @@
use crate::{ncpile_create, NcDimension, NcOffset, NcPlane, NcPlaneOptions, Notcurses};
/// Helper function for a new NcPlane on C style tests.
#[allow(dead_code)]
pub(crate) unsafe fn ncplane_new_test<'a>(
nc: &mut Notcurses,
y: NcOffset,
x: NcOffset,
rows: NcDimension,
cols: NcDimension,
) -> &'a mut NcPlane {
&mut *ncpile_create(nc, &NcPlaneOptions::new(y, x, rows, cols))
}

View File

@ -163,8 +163,12 @@
#[cfg(test)]
mod test;
mod helpers;
mod methods;
mod reimplemented;
#[allow(unused_imports)]
pub(crate) use helpers::*;
pub use reimplemented::*;
// NcPlane

View File

@ -1,31 +1,14 @@
//! Test `ncplane_*` reimplemented functions.
use crate::{notcurses_stop, NcPlane, NcPlaneOptions, Notcurses, NCRESULT_OK};
use crate::{ncplane_new_test, notcurses_init_test, notcurses_stop, NCRESULT_OK};
use serial_test::serial;
#[test]
#[serial]
fn ncplane_options() {
let _po = NcPlaneOptions::new(0, 0, 20, 20);
}
#[test]
#[serial]
fn ncpile_create() {
let po = NcPlaneOptions::new(0, 0, 20, 20);
unsafe {
let nc = Notcurses::new();
let _p = NcPlane::with_options(nc, &po);
notcurses_stop(nc);
}
}
#[test]
#[serial]
fn ncplane_notcurses() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
let nc2 = crate::ncplane_notcurses(plane);
assert_eq![nc as *mut _, nc2];
@ -41,8 +24,8 @@ fn ncplane_notcurses() {
#[serial]
fn ncplane_cursor() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
let (mut y, mut x) = (0, 0);
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
@ -74,8 +57,8 @@ fn ncplane_cursor() {
#[serial]
fn ncplane_channels() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
let channels = crate::ncplane_channels(plane);
assert_eq![channels, 0];
@ -91,8 +74,8 @@ fn ncplane_channels() {
#[serial]
fn ncplane_fchannel() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
crate::ncplane_set_channels(plane, 0x1122334455667788);
let channels = crate::ncplane_channels(plane);
@ -110,8 +93,8 @@ fn ncplane_fchannel() {
#[serial]
fn ncplane_bchannel() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
crate::ncplane_set_channels(plane, 0x1122334455667788);
let channels = crate::ncplane_channels(plane);
@ -132,8 +115,8 @@ fn ncplane_bchannel() {
#[serial]
fn ncplane_rgb() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
crate::ncplane_set_fg_rgb(plane, 0x112233);
assert_eq![0x112233, crate::ncplane_fg_rgb(plane)];
@ -146,8 +129,8 @@ fn ncplane_rgb() {
#[serial]
fn ncplane_default() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
assert_eq![true, crate::ncplane_bg_default_p(plane)];
assert_eq![true, crate::ncplane_fg_default_p(plane)];
@ -169,8 +152,8 @@ fn ncplane_default() {
#[serial]
fn ncplane_dimensions() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 10, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 10, 20);
let (mut y, mut x) = (0, 0);
crate::ncplane_dim_yx(plane, &mut y, &mut x);
@ -187,8 +170,8 @@ fn ncplane_dimensions() {
#[serial]
fn ncplane_resize() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
let res = crate::ncplane_resize_simple(plane, 40, 40);
assert_eq![NCRESULT_OK, res];
@ -216,8 +199,8 @@ fn ncplane_resize() {
// The base cell is preserved.
fn ncplane_erase() {
unsafe {
let nc = Notcurses::new();
let plane = NcPlane::new(nc, 0, 0, 20, 20);
let nc = notcurses_init_test();
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
crate::ncplane_set_bg_rgb(plane, 0x112233);
crate::ncplane_set_fg_rgb(plane, 0x445566);
@ -238,8 +221,8 @@ fn ncplane_erase() {
// #[serial]
// fn ncplane_at_cursor() {
// unsafe {
// let nc = Notcurses::new();
// let plane = NcPlane::new(nc, 0, 0, 20, 20);
// let nc = notcurses_init_test();
// let plane = ncplane_new_test(nc, 0, 0, 20, 20);
//
// notcurses_stop(nc);
// }
@ -249,8 +232,8 @@ fn ncplane_erase() {
// #[serial]
// fn ncplane_at_cursor_cell() {
// unsafe {
// let nc = Notcurses::new();
// let plane = NcPlane::new(nc, 0, 0, 20, 20);
// let nc = notcurses_init_test();
// let plane = ncplane_new_test(nc, 0, 0, 20, 20);
//
// notcurses_stop(nc);
// }