diff --git a/rust/README.md b/rust/README.md index f932f3462..a6112b053 100644 --- a/rust/README.md +++ b/rust/README.md @@ -15,38 +15,26 @@ and the [**C way**](#2-the-c-way). (Or a mix of both). ## 1. The Rust way -Where you use the safely wrapped types, with its methods and constructors, +Where you use the more safely wrapped types, with its methods and constructors, and painless error handling, like this: ```rust use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?; + let mut nc = Notcurses::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?; let plane = nc.stdplane(); plane.putstr("hello world")?; nc.render()?; + nc.stop()?; Ok(()) } ``` -Specifically `Nc` and `NcD` are safe wrappers over `Notcurses` -and `NcDirect`, respectively. - -`Nc` and `NcD` both implement the Drop, AsRef, AsMut, Deref and DerefMut traits. - -Their destructors are called automatically at the end of their scope. - -Methods are directly implemented for `Notcurses` and `NcDirect`, and are -made automatically available to `Nc` & `NcD`, minus some function overrides, -like their destructors, plus the static methods that have to be recreated. - -The rest of the types that allocate, like `NcPlane`, `NcMenu`, -`NcReader`… have no higher level wrapping struct, they don't -implement Drop, so they have to be `*.destroy()`ed manually. - -But they do implement methods and use `NcResult` as the return type, -for handling errors in the way we are used to in Rust. +Although you still have to manually call the `stop()` method for `Notcurses` +and `NcDirect` objects, and the `destroy()` method for the rest of types that +allocate, (like `NcPlane`, `NcMenu`…) at the end of their scope, since the Drop +trait is not implemented for any wrapping type in libnotcurses-sys. For the types that don't allocate, most are based on primitives like `i32`, `u32`, `u64`… without a name in the C library. In Rust they are type aliased diff --git a/rust/examples/direct-capabilities.rs b/rust/examples/direct-capabilities.rs index c98fd9986..9795c4e9c 100644 --- a/rust/examples/direct-capabilities.rs +++ b/rust/examples/direct-capabilities.rs @@ -1,7 +1,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut dm = NcD::new()?; + let dm = NcDirect::new()?; let (t_rows, t_cols) = dm.dim_yx(); println!("Terminal rows={0}, cols={1}", t_rows, t_cols); diff --git a/rust/examples/direct-cursor.rs b/rust/examples/direct-cursor.rs index ddd837993..c9e37a33e 100644 --- a/rust/examples/direct-cursor.rs +++ b/rust/examples/direct-cursor.rs @@ -10,7 +10,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { let mut rng = thread_rng(); - let mut dm = NcD::new()?; + let mut dm = NcDirect::new()?; let cols = dm.dim_x(); let rows = dm.dim_y(); diff --git a/rust/examples/direct-image-rust.rs b/rust/examples/direct-image-rust.rs index 0dc89662e..8a92f67ef 100644 --- a/rust/examples/direct-image-rust.rs +++ b/rust/examples/direct-image-rust.rs @@ -7,7 +7,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut dm = NcD::new()?; + let mut dm = NcDirect::new()?; render_image(&mut dm, NCBLIT_1x1)?; render_image(&mut dm, NCBLIT_2x1)?; @@ -16,7 +16,7 @@ fn main() -> NcResult<()> { Ok(()) } -fn render_image(dm: &mut NcD, blit: NcBlitter) -> NcResult<()> { +fn render_image(dm: &mut NcDirect, blit: NcBlitter) -> NcResult<()> { if let Err(nc_error) = dm.render_image("image-16x16.png", NCALIGN_CENTER, blit, NCSCALE_NONE) { return Err(NcError::with_msg( nc_error.int, diff --git a/rust/examples/full-capabilities.rs b/rust/examples/full-capabilities.rs index b215fb467..b584acabb 100644 --- a/rust/examples/full-capabilities.rs +++ b/rust/examples/full-capabilities.rs @@ -1,7 +1,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::without_altscreen()?; + let nc = Notcurses::without_altscreen()?; let (t_rows, t_cols) = nc.term_dim_yx(); println!("Terminal rows={0}, cols={1}", t_rows, t_cols); @@ -38,5 +38,6 @@ Palette size: {11:?} println!("{:#?}", pixelgeom); nc.render()?; + nc.stop()?; Ok(()) } diff --git a/rust/examples/full-input.rs b/rust/examples/full-input.rs index 40d7b7bc7..773a188f3 100644 --- a/rust/examples/full-input.rs +++ b/rust/examples/full-input.rs @@ -6,7 +6,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::with_flags( + let mut nc = Notcurses::with_flags( NCOPTION_SUPPRESS_BANNERS | NCOPTION_NO_WINCH_SIGHANDLER | NCOPTION_NO_QUIT_SIGHANDLERS, )?; @@ -32,5 +32,6 @@ fn main() -> NcResult<()> { println!("\nExiting..."); rsleep![&mut nc, 1]; + nc.stop()?; Ok(()) } diff --git a/rust/examples/full-planes.rs b/rust/examples/full-planes.rs index 6f544b189..a62736ba1 100644 --- a/rust/examples/full-planes.rs +++ b/rust/examples/full-planes.rs @@ -1,7 +1,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::new()?; + let mut nc = Notcurses::new()?; // get the terminal size in character rows & columns let (t_rows, t_cols) = nc.term_dim_yx(); @@ -59,5 +59,6 @@ fn main() -> NcResult<()> { rsleep![&mut nc, 3]; + nc.stop()?; Ok(()) } diff --git a/rust/examples/issue-1559.rs b/rust/examples/issue-1559.rs index b9a128829..0e139130e 100644 --- a/rust/examples/issue-1559.rs +++ b/rust/examples/issue-1559.rs @@ -6,7 +6,7 @@ const WIDTH: u32 = 10; const HEIGHT: u32 = 10; fn main() -> NcResult<()> { - let mut nc = Nc::new()?; + let mut nc = Notcurses::new()?; if !nc.check_pixel_support()? { return Err(NcError::new_msg("Current terminal doesn't support pixels.")); @@ -33,5 +33,6 @@ fn main() -> NcResult<()> { rsleep![&mut nc, 2]; vframe.destroy(); + nc.stop()?; Ok(()) } diff --git a/rust/examples/pixel-cell.rs b/rust/examples/pixel-cell.rs index f0e57de30..d71751e9e 100644 --- a/rust/examples/pixel-cell.rs +++ b/rust/examples/pixel-cell.rs @@ -12,7 +12,7 @@ use rand::{distributions::Uniform, Rng}; use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::new()?; + let mut nc = Notcurses::new()?; if !nc.check_pixel_support()? { return Err(NcError::new_msg("Current terminal doesn't support pixels.")); @@ -81,5 +81,6 @@ fn main() -> NcResult<()> { vframe1.destroy(); vframe4.destroy(); + nc.stop()?; Ok(()) } diff --git a/rust/examples/poc-cjkscroll.rs b/rust/examples/poc-cjkscroll.rs index ac0c4059d..16faa33e7 100644 --- a/rust/examples/poc-cjkscroll.rs +++ b/rust/examples/poc-cjkscroll.rs @@ -3,7 +3,8 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::new()?; + let mut nc = Notcurses::new()?; + let plane = nc.stdplane(); plane.set_scrolling(true); @@ -19,4 +20,6 @@ fn main() -> NcResult<()> { } rsleep![&mut nc, 0, 0, 30]; } + + // nc.stop()?; } diff --git a/rust/examples/poc-direct.rs b/rust/examples/poc-direct.rs index 20407f713..ae48f449d 100644 --- a/rust/examples/poc-direct.rs +++ b/rust/examples/poc-direct.rs @@ -3,7 +3,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut dm = NcD::new()?; + let dm = NcDirect::new()?; let dimy = dm.dim_y(); let dimx = dm.dim_x(); diff --git a/rust/examples/poc-kittyzapper.rs b/rust/examples/poc-kittyzapper.rs index 30eaa860d..c899189b3 100644 --- a/rust/examples/poc-kittyzapper.rs +++ b/rust/examples/poc-kittyzapper.rs @@ -3,7 +3,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut dm = NcD::new()?; + let dm = NcDirect::new()?; dm.set_fg_rgb8(100, 100, 100)?; dm.set_bg_rgb8(0xff, 0xff, 0xff)?; diff --git a/rust/examples/poc-menu.rs b/rust/examples/poc-menu.rs index 2b33106e4..435ea2328 100644 --- a/rust/examples/poc-menu.rs +++ b/rust/examples/poc-menu.rs @@ -6,7 +6,7 @@ use libnotcurses_sys::*; fn main() -> NcResult<()> { - let mut nc = Nc::new()?; + let mut nc = Notcurses::new()?; nc.mouse_enable()?; let mut demo_items = [ @@ -72,7 +72,7 @@ fn main() -> NcResult<()> { Ok(()) } -fn run_menu(nc: &mut Nc, menu: &mut NcMenu) -> NcResult<()> { +fn run_menu(nc: &mut Notcurses, menu: &mut NcMenu) -> NcResult<()> { // yellow rectangle let planeopts = NcPlaneOptions::new_aligned(10, NCALIGN_CENTER, 3, 40); let stdplane = nc.stdplane(); @@ -104,6 +104,7 @@ fn run_menu(nc: &mut Nc, menu: &mut NcMenu) -> NcResult<()> { 'q' => { menu.destroy()?; selplane.destroy()?; + nc.stop()?; return Ok(()); } NCKEY_ENTER => { @@ -112,6 +113,7 @@ fn run_menu(nc: &mut Nc, menu: &mut NcMenu) -> NcResult<()> { "Quit" => { menu.destroy()?; selplane.destroy()?; + nc.stop()?; return Ok(()); } _ => (), diff --git a/rust/src/bindings.rs b/rust/src/bindings.rs index 34f7f164d..61c00ac21 100644 --- a/rust/src/bindings.rs +++ b/rust/src/bindings.rs @@ -177,7 +177,7 @@ pub use ffi::{ ncdirect_off_styles, ncdirect_on_styles, ncdirect_palette_size, - ncdirect_printf_aligned, + //W ncdirect_printf_aligned, ncdirect_putstr, ncdirect_raster_frame, ncdirect_readline, diff --git a/rust/src/cells/test/methods.rs b/rust/src/cells/test/methods.rs index 8202083ad..4107ede8b 100644 --- a/rust/src/cells/test/methods.rs +++ b/rust/src/cells/test/methods.rs @@ -1,6 +1,6 @@ //! Test `NcCell` methods and associated functions. -use crate::{Nc, NcCell, NcPlane}; +use crate::{Notcurses, NcCell, NcPlane}; use serial_test::serial; @@ -10,8 +10,9 @@ fn constructors() -> crate::NcResult<()> { let _c1 = NcCell::new(); let _c2 = NcCell::with_char7b('C'); - let mut nc = Nc::new()?; - let plane = NcPlane::new(&mut nc, 0, 0, 10, 10)?; + let nc = Notcurses::new()?; + let plane = NcPlane::new(nc, 0, 0, 10, 10)?; let _c3 = NcCell::with_char('௵', plane); + nc.stop()?; Ok(()) } diff --git a/rust/src/direct/mod.rs b/rust/src/direct/mod.rs index 98bb62263..525096066 100644 --- a/rust/src/direct/mod.rs +++ b/rust/src/direct/mod.rs @@ -1,29 +1,19 @@ //! `NcDirect` -// --- --------------------------------------------------------- -// col 0: -// -------------- -// 4 X: wont do -// ~: WIP +// total: 47 +// --------------------------------------------------- +// (X) 1 : wont do // -// col 1: 43 -// -------------- -// 39 f: ffi function imported by bindgen -// F: ffi function wrapped safely -// 4 r: static function reimplemented in Rust +// (f) 42 : unsafe ffi function exported by bindgen +// (w) 0 : safely wrapped ffi function +// (r) 4 : static function manually reimplemented // -// col 2: 43 -// -------------- -// 41 m: impl as an `NcDirect` method -// 2 M: impl for the `NcD` wrapper struct too -// -// col 3: -// -------------- -// t: tests done for the ffi or reimplemented funtion -// T: tests done also for the m method -// Ŧ: tests done also for the M method wrapper struct -// --- --------------------------------------------------------- +// (m) 45 : method implemented +// (~) 1 : work in progress // +// (t) 0 : unit test done for the function +// (T) 0 : unit test done also for the method +// --------------------------------------------------- // fm ncdirect_bg_default // fm ncdirect_bg_palindex // fm ncdirect_bg_rgb @@ -52,7 +42,7 @@ // fm ncdirect_flush // fm ncdirect_getc // fm ncdirect_hline_interp -// fM ncdirect_init +// fm ncdirect_init // fm ncdirect_inputready_fd // fm ncplane_on_styles // fm ncplane_off_styles @@ -65,10 +55,7 @@ // fm ncdirect_render_image // fm ncdirect_rounded_box // fm ncplane_set_styles -// fM ncdirect_stop -//X ncdirect_styles_off // deprecated -//X ncdirect_styles_on // deprecated -//X ncdirect_styles_set // deprecated +// fm ncdirect_stop // fm ncdirect_vline_interp // rm ncdirect_bg_rgb8 // rm ncdirect_fg_rgb8 @@ -80,10 +67,8 @@ mod test; mod methods; mod reimplemented; -mod wrapper; pub use reimplemented::*; -pub use wrapper::*; /// Minimal notcurses instance for styling text. /// diff --git a/rust/src/direct/wrapper.rs b/rust/src/direct/wrapper.rs deleted file mode 100644 index 29867cbb7..000000000 --- a/rust/src/direct/wrapper.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! `NcD` wrapper struct and traits implementations. - -use std::ops::{Deref, DerefMut}; - -use crate::{raw_wrap, NcDirect, NcResult}; - -/// Safe wrapper around [NcDirect], minimal notcurses instance for styling text. -#[derive(Debug)] -pub struct NcD<'a> { - pub(crate) raw: &'a mut NcDirect, -} - -impl<'a> AsRef for NcD<'a> { - fn as_ref(&self) -> &NcDirect { - self.raw - } -} - -impl<'a> AsMut for NcD<'a> { - fn as_mut(&mut self) -> &mut NcDirect { - self.raw - } -} - -impl<'a> Deref for NcD<'a> { - type Target = NcDirect; - - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl<'a> DerefMut for NcD<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut() - } -} - -impl<'a> Drop for NcD<'a> { - /// Destroys the NcD context. - fn drop(&mut self) { - let _ = self.raw.stop(); - } -} - -/// # Constructors and methods overriden from NcDirect -impl<'a> NcD<'a> { - // wrap constructors - - /// New NcD (without banners). - pub fn new() -> NcResult { - raw_wrap![NcDirect::new()] - } - - /// New NcD, expects `NCOPTION_*` flags. - pub fn with_flags(flags: u64) -> NcResult { - raw_wrap![NcDirect::with_flags(flags)] - } - - // disable destructor - - /// Since NcD already implements [Drop](#impl-Drop), - /// this function is made no-op. - pub fn stop(&mut self) -> NcResult<()> { - Ok(()) - } -} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5168fb3ab..cde914146 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -22,10 +22,11 @@ //! use libnotcurses_sys::*; //! //! fn main() -> NcResult<()> { -//! let mut nc = Nc::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?; +//! let mut nc = Notcurses::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?; //! let plane = nc.stdplane(); //! plane.putstr("hello world")?; //! nc.render()?; +//! nc.stop()?; //! Ok(()) //! } //! ``` diff --git a/rust/src/notcurses/mod.rs b/rust/src/notcurses/mod.rs index 3d4a2f981..c085354a7 100644 --- a/rust/src/notcurses/mod.rs +++ b/rust/src/notcurses/mod.rs @@ -1,29 +1,19 @@ //! `Notcurses` - -// --- ------------------------------------------------------------------------- -// col 0: 3 -// -------------- -// 1 X: wont do -// 2 ~: WIP + +// total: 51 +// --------------------------------------------------- +// (X) 1 : wont do // -// col 1: 50 -// -------------- -// 44 f: ffi function imported by bindgen -// F: ffi function wrapped safely -// 6 r: static function reimplemented in Rust +// (f) 44 : unsafe ffi function exported by bindgen +// (w) 0 : safely wrapped ffi function +// (r) 6 : static function manually reimplemented // -// col 2: 48 -// -------------- -// 38 m: impl as a `Notcurses` method -// 10 M: impl for the `Nc` wrapper struct too -// -// col 3: 13 -// -------------- -// 13 t: tests done for the ffi or reimplemented funtion -// T: tests done also for the m method -// Ŧ: tests done also for the M method wrapper struct -// --- ------------------------------------------------------------------------- +// (m) 38 : method implemented +// (~) 3 : work in progress // +// (t) 13 : unit test done for the function +// (T) 0 : unit test done also for the method +// --------------------------------------------------- // fm notcurses_at_yx // fm notcurses_bottom // fm notcurses_canbraille @@ -35,18 +25,18 @@ // fmt notcurses_cantruecolor // fmt notcurses_canutf8 // fm notcurses_check_pixel_support -// f~ notcurses_core_init +//~f notcurses_core_init // fm notcurses_cursor_disable // fm notcurses_cursor_enable // fmt notcurses_debug // fm notcurses_debug_caps // fmt notcurses_drop_planes // fm notcurses_getc -// fMt notcurses_init +// fmt notcurses_init // fm notcurses_inputready_fd -// fM notcurses_lex_blitter -// fM notcurses_lex_margins -// fM notcurses_lex_scalemode +// fm notcurses_lex_blitter +// fm notcurses_lex_margins +// fm notcurses_lex_scalemode // fm notcurses_linesigs_disable // fm notcurses_linesigs_enable // fm notcurses_mouse_disable @@ -61,16 +51,15 @@ // fm notcurses_stats_reset // fm notcurses_stdplane // fm notcurses_stdplane_const -// fMt notcurses_stop -// fM notcurses_str_blitter -// fM notcurses_str_scalemode +// fmt notcurses_stop +// fm notcurses_str_blitter +// fm notcurses_str_scalemode // fm notcurses_supported_styles // fm notcurses_top //X notcurses_ucs32_to_utf8 (not needed in rust) -// fMt notcurses_version -// fM notcurses_version_components -// -// rMt notcurses_align +// fmt notcurses_version +// fm notcurses_version_components +// rmt notcurses_align // rm notcurses_getc_blocking // rm notcurses_getc_nblock //~r notcurses_stddim_yx // multiple mutable references errors @@ -83,12 +72,10 @@ mod test; mod helpers; mod methods; mod reimplemented; -mod wrapper; #[allow(unused_imports)] pub(crate) use helpers::*; pub use reimplemented::*; -pub use wrapper::*; /// Notcurses builds atop the terminfo abstraction layer to /// provide reasonably portable vivid character displays. diff --git a/rust/src/notcurses/wrapper.rs b/rust/src/notcurses/wrapper.rs deleted file mode 100644 index f9c50089e..000000000 --- a/rust/src/notcurses/wrapper.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! `Nc` wrapper struct and traits implementations. - -use std::ops::{Deref, DerefMut}; - -use crate::{ - raw_wrap, NcAlign, NcBlitter, NcDim, NcLogLevel, NcResult, NcScale, Notcurses, NotcursesOptions, -}; - -/// Safe wrapper around [Notcurses], the main struct of the TUI library. -#[derive(Debug)] -pub struct Nc<'a> { - pub(crate) raw: &'a mut Notcurses, -} - -impl<'a> AsRef for Nc<'a> { - fn as_ref(&self) -> &Notcurses { - self.raw - } -} - -impl<'a> AsMut for Nc<'a> { - fn as_mut(&mut self) -> &mut Notcurses { - self.raw - } -} - -impl<'a> Deref for Nc<'a> { - type Target = Notcurses; - - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl<'a> DerefMut for Nc<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_mut() - } -} - -impl<'a> Drop for Nc<'a> { - /// Destroys the Nc context. - fn drop(&mut self) { - let _ = self.raw.stop(); - } -} - -/// # Constructors and methods overriden from Notcurses -impl<'a> Nc<'a> { - // wrap constructors - - /// New Nc (without banners). - pub fn new() -> NcResult { - raw_wrap![Notcurses::new()] - } - - /// New Nc, with banners. - pub fn with_banners() -> NcResult { - raw_wrap![Notcurses::with_banners()] - } - - /// New Nc, without an alternate screen (nor banners). - pub fn without_altscreen() -> NcResult { - raw_wrap![Notcurses::without_altscreen()] - } - - /// New Nc, expects `NCOPTION_*` flags. - pub fn with_flags(flags: u64) -> NcResult { - raw_wrap![Notcurses::with_flags(flags)] - } - - /// New Nc, expects [NotcursesOptions]. - pub fn with_options(options: NotcursesOptions) -> NcResult { - raw_wrap![Notcurses::with_options(options)] - } - - /// New Nc, expects [NcLogLevel] and flags. - pub fn with_debug(loglevel: NcLogLevel, flags: u64) -> NcResult { - raw_wrap![Notcurses::with_debug(loglevel, flags)] - } - - // disable destructor - - /// Since Nc already implements [Drop](#impl-Drop), - /// this function is made no-op. - pub fn stop(&mut self) -> NcResult<()> { - Ok(()) - } - - // wrap associated functions - - /// Returns the offset into `availcols` at which `cols` ought be output given - /// the requirements of `align`. - pub fn align(availcols: NcDim, align: NcAlign, cols: NcDim) -> NcResult<()> { - Notcurses::align(availcols, align, cols) - } - - /// Gets the name of an [NcBlitter] blitter. - pub fn str_blitter(blitter: NcBlitter) -> String { - Notcurses::str_blitter(blitter) - } - - /// Gets the name of an [NcScale] scaling mode. - pub fn str_scalemode(scalemode: NcScale) -> String { - Notcurses::str_scalemode(scalemode) - } - - /// Returns an [NcBlitter] from a string representation. - pub fn lex_blitter(op: &str) -> NcResult { - Notcurses::lex_blitter(op) - } - - /// Lexes a margin argument according to the standard Notcurses definition. - /// - /// There can be either a single number, which will define all margins equally, - /// or there can be four numbers separated by commas. - /// - pub fn lex_margins(op: &str, options: &mut NotcursesOptions) -> NcResult<()> { - Notcurses::lex_margins(op, options) - } - - /// Returns an [NcScale] from a string representation. - pub fn lex_scalemode(op: &str) -> NcResult { - Notcurses::lex_scalemode(op) - } - - /// Returns a human-readable string describing the running Nc version. - pub fn version() -> String { - Notcurses::version() - } - - /// Returns the running Notcurses version components - /// (major, minor, patch, tweak). - pub fn version_components() -> (u32, u32, u32, u32) { - Notcurses::version_components() - } -}