termit 0.7.0

Terminal UI over crossterm
Documentation
use crate::prelude::{point, Point};
use is_terminal::IsTerminal;
use log::trace;
use rustix::fd::{self, AsFd};
use rustix::termios::{self, InputModes, LocalModes, OutputModes, Termios};
use std::{fs, io};

pub fn is_tty<FD>(fd: FD) -> Option<FD>
where
    FD: AsFd,
{
    if fd.is_terminal() {
        Some(fd)
    } else {
        None
    }
}

pub fn get_tty_attributes(control: impl AsFd) -> io::Result<Termios> {
    Ok(termios::tcgetattr(&control)?)
}
pub fn set_tty_attributes(control: impl AsFd, tios: &Termios) -> io::Result<()> {
    Ok(termios::tcsetattr(
        &control,
        termios::OptionalActions::Now,
        tios,
    )?)
}
pub fn is_raw(control: impl AsFd) -> io::Result<bool> {
    let tios = get_tty_attributes(control)?;
    /*
        cfmakeraw(termios) does this:
        t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
        t->c_oflag &= ~OPOST;
        t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
        t->c_cflag &= ~(CSIZE|PARENB);
        t->c_cflag |= CS8;
        t->c_cc[VMIN] = 1;		/* read returns when one char is available.  */
        t->c_cc[VTIME] = 0;
    */
    Ok(false
        == (tios
            .local_modes
            .intersects(LocalModes::ECHO | LocalModes::ICANON))
            | (tios
                .input_modes
                .intersects(InputModes::ICRNL | InputModes::INLCR))
            | (tios.output_modes.intersects(OutputModes::OPOST)))
}

/// https://www.ibm.com/docs/en/zos/2.2.0?topic=functions-tcsetattr-set-attributes-terminal
#[must_use = "Resets on drop"]
pub fn enable_raw(control: impl AsFd) -> io::Result<()> {
    let mut tios = termios::tcgetattr(&control)?;
    trace!("switching to raw mode");
    tios.make_raw();
    termios::tcsetattr(&control, termios::OptionalActions::Now, &tios)?;
    Ok(())
}

pub fn open_tty() -> io::Result<fs::File> {
    fs::File::open("/dev/tty")
}

pub fn size_from_fd(fd: impl fd::AsFd) -> io::Result<Point> {
    let ws = rustix::termios::tcgetwinsize(fd.as_fd())?;
    Ok(point(ws.ws_col, ws.ws_row))
}