1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use std::io::BufReader;
use std::io::prelude::*;
use std::process::Child;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
#[derive(Debug)]
pub enum Line {
StdOut(String),
StdErr(String)
}
pub struct Lines {
rx: Receiver<Option<Line>>,
}
pub struct Iter<'a> {
lines: &'a Lines
}
impl Lines {
pub fn iter(&self) -> Iter {
Iter { lines: self }
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Line;
fn next(&mut self) -> Option<Line> {
match self.lines.rx.recv() {
Ok(line) => line,
_ => None,
}
}
}
pub fn lines(child: &mut Child) -> Lines {
let (tx, rx) = channel();
fn read<R, F>(
readable: Option<R>,
tx: Sender<Option<Line>>,
wrap: F
) where
R: Send + 'static + Read,
F: Send + 'static + Fn(String) -> Line {
if let Some(r) = readable {
thread::spawn(move || {
let mut buf = BufReader::new(r);
loop {
let mut line = String::new();
match buf.read_line(&mut line) {
Ok(0) | Err(_) => break,
Ok(_) => {
let _ = tx.send(Some(wrap(line)));
}
}
}
});
} else {
let _ = tx.send(None);
}
};
read(child.stdout.take(), tx.clone(), |l| Line::StdOut(l));
read(child.stderr.take(), tx.clone(), |l| Line::StdErr(l));
Lines { rx: rx }
}
#[test]
fn it_works() {
}