notcurses/rust
Nick Black 2c5d938cbd
Paint sprixels bottom-to-top (#1589)
* Paint sprixels in order, bottom-to-top

We don't want to have to track sprixel order whenever someone
moves an ncplane, so just keep a list growing backwards as we
pass top-to-bottom in notcurses_render_internal(). Each time
we hit a sprixel plane, splice it out of the sprixel list, and
add it to the front of our temporary list. When we hit the
bottom, stick this temporary list on the end of our existing
list (any such planes are to be deleted, which comes before
drawing). Closes #1575.

* reorder collected sprixellist; solves kitty but breaks sixel =/ #1575

* remove debugging cruft

* [rust] fix up mergedown mutability
2021-04-24 13:08:09 -04:00
..
.cargo rust: continue NcMenu PoC example; fixes 2020-12-27 19:00:32 +01:00
build v2.2.8 2021-04-18 13:24:24 -04:00
examples Sixel unit tests #1580 (#1586) 2021-04-24 01:51:26 -04:00
src Paint sprixels bottom-to-top (#1589) 2021-04-24 13:08:09 -04:00
Cargo.toml [rust] re-license with dual MIT OR Apache 2.0 2021-04-21 18:09:44 +02:00
LICENSE-APACHE [rust] re-license with dual MIT OR Apache 2.0 2021-04-21 18:09:44 +02:00
LICENSE-MIT [rust] re-license with dual MIT OR Apache 2.0 2021-04-21 18:09:44 +02:00
README.md [rust] update readme 2021-04-20 21:51:45 +02:00

Crate API MSRV: 1.48.0

libnotcurses-sys is a Rust wrapper for the notcurses C library

This library is built with several layers of zero-overhead abstractions over the C functions and pointers accessed through FFI.

How to use this library

There are basically two ways: The Rust way, and the C way. (Or a mix of both).

1. The Rust way

Where you use the safely wrapped types, with its methods and constructors, and painless error handling, like this:

use libnotcurses_sys::*;

fn main() -> NcResult<()> {
    let mut nc = Nc::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?;
    let plane = nc.stdplane();
    plane.putstr("hello world")?;
    nc.render()?;
    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.

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 (e.g.: NcChannel, NcChannelPair, NcRgb, NcColor…), to leverage type checking, and they implement methods through traits (e.g. NcChannelMethods must be in scope to use the NcChannel methods.

2. The C way

You can always use the C API functions directly if you prefer, in a very similar way as the C library is used.

It requires the use of unsafe, since most functions are wrapped directly by bindgen marked as such.

Error handling is done this way by checking the returned NcIntResult, or in case of receiving a pointer, by comparing it to null_mut().

Example

use core::ptr::{null, null_mut};
use std::process::exit;

use libnotcurses_sys::*;

fn main() {
    let options = ffi::notcurses_options {
        termtype: null(),
        renderfp: null_mut(),
        loglevel: 0,
        margin_t: 0,
        margin_r: 0,
        margin_b: 0,
        margin_l: 0,
        flags: NCOPTION_NO_ALTERNATE_SCREEN,
    };
    unsafe {
        let nc = notcurses_init(&options, null_mut());
        if nc == null_mut() {
            exit(1);
        }
        let plane = notcurses_stdplane(nc);
        let cols = ncplane_putstr(&mut *plane, "hello world");
        if cols < NCRESULT_OK {
            notcurses_stop(nc);
            exit(cols.abs());
        }
        if notcurses_stop(nc) < NCRESULT_OK {
            exit(2);
        }
    }
}

The notcurses C API docs