interactor 0.1.3

A library for simple (usually command-line) user interaction.
Documentation
use super::termios::*;
use std::fs::{File, OpenOptions};
use std::io::{self, Read};
use std::os::unix::io::AsRawFd;

pub fn read_from_tty_file<F>(
    tty: &mut File,
    byte_callback: F,
    run_before_input: bool,
    run_after_input: bool,
) -> io::Result<Vec<u8>>
where
    F: Fn(&[u8], u8, &mut File),
{
    let fd = tty.as_raw_fd();
    let mut termios = Termios::from_fd(fd)?;
    let orig_lflag = termios.c_lflag;
    termios.c_lflag &= !(ECHO | ICANON);
    tcsetattr(fd, TCSANOW, &termios)?;

    let mut buffer = [0; 1];
    let mut result = Vec::new();
    if run_before_input {
        byte_callback(&result, buffer[0], tty);
    }
    loop {
        tty.read(&mut buffer)?;
        match buffer[0] {
            10 | 13 => break,
            8 | 127 => {
                result.pop();
            }
            0..=31 => {}
            _ => result.push(buffer[0]),
        };
        byte_callback(&result, buffer[0], tty);
    }
    if run_after_input {
        byte_callback(&result, 4, tty);
    }

    termios.c_lflag = orig_lflag;
    tcsetattr(fd, TCSANOW, &termios)?;

    Ok(result)
}

pub fn read_from_tty<F>(
    byte_callback: F,
    run_before_input: bool,
    run_after_input: bool,
) -> io::Result<Vec<u8>>
where
    F: Fn(&[u8], u8, &mut File),
{
    let mut tty = OpenOptions::new().read(true).write(true).open("/dev/tty")?;
    read_from_tty_file(&mut tty, byte_callback, run_before_input, run_after_input)
}