infoterm 0.1.1

ncurses-compatible terminfo parsing library
Documentation
//! Compiled ncurses terminfo file parser.
//!
//! ## Format Support
//!
//! This crate handles the *binary terminfo* format used by modern versions of ncurses.
//! It may work with other implementations of curses (e.g. NetBSD), but there are no guarantees.
//! File an issue if you find a widely used alternative implementation.
//!
//! This crate currently supports the following formats:
//!
//! - ncurses pre-5.0 legacy format (SVr4 compatible)
//! - ncurses 5.0 user-defined capabilities format
//! - ncurses 6.1 32-bit integer format
//!
//! While ncurses restricts the size of compiled entries to 4096 and 32768 bytes for the legacy
//! and 32-bit integer formats respectively and further restricts the length of the name field to
//! 512 bytes, this crate imposes no such restrictions. As there is no support for writing
//! entries, this should pose no issues.
//!
//! ## Portability
//!
//! While the binary terminfo format is de-facto standard between Unix versions, and the
//! capability names are part of the X/Open standard, implementations do differ in the order the
//! capabilities are stored in the compiled files. This is why capability indices (see the
//! [`index` feature](#index)) are provided for **ncurses specifically**.
//!
//! *If you're using this crate for terminfo files compiled for a different implementation of
//! curses, you will likely need different names and indices.*
//!
//! For more information, see [term(5)][man-term], [section PORTABILITY][man-term-portability].
//!
//! ## Crate Features
//!
//! #### `index`
//!
//! Enabled by default.
//!
//! The [`index`] module provides efficient translation from capability names to indices and back.
//! The indices are based on ncurses. See [portability](#portability) for potential caveats.
//!
//! The module uses large tables of strings, so you may get longer compile times or binary sizes.
//!
//! ---
//!
//! #### `expand`
//!
//! Enabled by default.
//!
//! The [`mod@expand`] module implements the [`tiparm()`][man-tparm] function, enabling the
//! expansion of parameterized capability strings. Part of the X/Open curses standard. See the
//! [`expand!`] macro for more information.
//!
//! ---
//!
//! #### `search`
//!
//! Enabled by default.
//!
//! The [`search`] module provides customizable searching for terminfo entries on the system.
//! It matches the search behaviour of ncurses by default. The hashed database storage introduced
//! in ncurses 5.6 is not supported.
//!
//! [man-term]: https://man.archlinux.org/man/term.5
//! [man-term-portability]: https://man.archlinux.org/man/terminfo.5#PORTABILITY
//! [man-terminfo]: https://man.archlinux.org/man/terminfo.5
//! [man-tparm]: https://man.archlinux.org/man/terminfo.5#Parameterized_Strings

pub mod entry;
pub mod escape;
#[cfg(feature = "expand")]
pub mod expand;
#[cfg(feature = "index")]
pub mod index;
#[cfg(feature = "search")]
pub mod search;

#[doc(inline)]
pub use entry::Entry;
#[doc(inline)]
pub use escape::escape_terminfo;
#[cfg(feature = "search")]
#[doc(inline)]
pub use search::Search;

/// Returns the name of the current terminal.
///
/// This function queries the value of the environment variable `TERM`.
///
/// Returns `None` if `TERM`:
/// - is not set
/// - is empty
/// - contains non-ASCII characters
/// - contains path separator characters
pub fn current_terminal() -> Option<String> {
    let term = std::env::var_os("TERM")?;

    valid_terminal(&term)?;

    // SAFETY: `valid_terminal` checks that the string cannot contain invalid UTF-8.
    let term = unsafe { term.into_string().unwrap_unchecked() };

    Some(term)
}

/// Check if `term` is a valid terminal name.
/// See [`current_terminal`] for what constitutes valid.
fn valid_terminal(term: &std::ffi::OsStr) -> Option<&str> {
    if term.is_empty() || !term.is_ascii() {
        return None;
    }

    // SAFETY: `term` is ASCII and cannot contain invalid UTF-8
    let term = unsafe { term.to_str().unwrap_unchecked() };

    if term.contains(std::path::is_separator) {
        return None;
    }

    Some(term)
}