logss/
tstdin.rs

1use std::{
2    io::{stdin, BufRead, BufReader, Error},
3    process::{Command, Stdio},
4    sync::{mpsc, mpsc::Sender},
5    thread,
6};
7
8use anyhow::Result;
9
10#[derive(Debug)]
11pub struct StdinHandler {
12    receiver: mpsc::Receiver<String>,
13    pub sender: mpsc::Sender<String>,
14}
15
16impl Default for StdinHandler {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl StdinHandler {
23    pub fn new() -> Self {
24        let (sender, receiver) = mpsc::channel();
25        Self { receiver, sender }
26    }
27
28    pub fn init(&self, cmd: Option<Vec<String>>) -> Result<()> {
29        let sender = self.sender.clone();
30        match cmd {
31            Some(inner_cmd) => {
32                let child = Command::new(&inner_cmd[0])
33                    .args(&inner_cmd[1..])
34                    .stderr(Stdio::null())
35                    .stdout(Stdio::piped())
36                    .spawn()?;
37
38                let stdout = child
39                    .stdout
40                    .ok_or_else(|| Error::other("Failed to run command"))?;
41                let reader = BufReader::new(stdout);
42                read_lines_and_send(reader, sender);
43            }
44            // If no command set then we are being pipped
45            None => {
46                let stdin = stdin();
47                let reader = BufReader::new(stdin);
48
49                read_lines_and_send(reader, sender);
50            }
51        }
52
53        Ok(())
54    }
55
56    pub fn recv(&self) -> Result<String, mpsc::RecvError> {
57        self.receiver.recv()
58    }
59
60    pub fn try_recv(&self) -> Result<String, mpsc::TryRecvError> {
61        self.receiver.try_recv()
62    }
63}
64
65fn read_lines_and_send<R>(mut reader: R, sender: Sender<String>)
66where
67    R: BufRead + Send + 'static,
68{
69    let mut line = String::new();
70    thread::spawn(move || loop {
71        match reader.read_line(&mut line) {
72            Ok(len) => {
73                if len == 0 {
74                    break;
75                } else {
76                    sender.send(line.clone()).ok();
77                }
78            }
79            Err(e) => {
80                sender.send(e.to_string()).ok();
81                break;
82            }
83        }
84        line.clear();
85    });
86}