notcurses/rust/README.md
2021-04-20 21:51:45 +02:00

115 lines
3.8 KiB
Markdown

[![Crate](https://img.shields.io/crates/v/libnotcurses-sys.svg)](https://crates.io/crates/libnotcurses-sys)
[![API](https://docs.rs/libnotcurses-sys/badge.svg)](https://dankamongmen.github.io/notcurses/rustdoc/libnotcurses_sys/)
[![MSRV: 1.48.0](https://flat.badgen.net/badge/MSRV/1.48.0/purple)](https://blog.rust-lang.org/2020/11/19/Rust-1.48.html)
`libnotcurses-sys` is a Rust wrapper for the
[notcurses C library](https://www.github.com/dankamongmen/notcurses/)
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**](#1-the-rust-way),
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,
and painless error handling, like this:
```rust
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
```rust
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
- [API reference (man pages)](https://notcurses.com/)
- [Wiki Page](https://nick-black.com/dankwiki/index.php/Notcurses)
- [The Book Guide (pdf)](https://nick-black.com/htp-notcurses.pdf)
- [USAGE.md](https://github.com/dankamongmen/notcurses/blob/master/USAGE.md)
- [HACKING.md](https://github.com/dankamongmen/notcurses/blob/master/doc/HACKING.md)
- [Doxygen Documentation](https://nick-black.com/notcurses/html/index.html)