cag 0.0.3

Context aware pager
Documentation
use crate::error::Error;
use std::io::{stdin, BufRead};
use std::sync::mpsc::{channel, Receiver};
use std::thread::{self, JoinHandle};
use tracing::{trace, warn};

pub fn stream_input(num_lines: usize) -> (Receiver<Result<Vec<String>, Error>>, JoinHandle<()>) {
    trace!("Opening channel for input reader");
    let (tx, rx) = channel::<Result<Vec<String>, Error>>();
    let thread_handle = thread::spawn(move || {
        trace!("Reading input");
        let input = stdin().lock();
        trace!("Splitting input");
        let mut input_lines = input.split(b'\n');

        loop {
            trace!("Reading lines");
            let mut maybe_err = None;
            let mut lines = Vec::with_capacity(num_lines);
            for _ in 0..num_lines {
                match input_lines.next() {
                    Some(Ok(buf)) => {
                        trace!("Got lines");
                        let line = String::from_utf8_lossy(&buf).to_string();
                        lines.push(line);
                    }
                    Some(Err(err)) => {
                        warn!("Error reading input lines: {err}");
                        maybe_err = Some(err);
                        break;
                    }
                    None => {
                        trace!("No new lines");
                        return;
                    }
                }
            }
            if let Err(err) = tx.send(Ok(lines)) {
                warn!("Error sending input streaming result: {err}");
                return;
            }
            if let Some(read_err) = maybe_err {
                warn!("Got read error streaming input: {read_err}");
                if let Err(_send_err) = tx.send(Err(Error::StreamingSend)) {
                    return;
                }
            }
        }
    });
    (rx, thread_handle)
}