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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use futures::stream::Stream as _;
mod input;
#[allow(clippy::type_complexity)]
struct Expect {
process: tokio_pty_process_stream::Process<input::buf::Stdin>,
expectations: Vec<(
regex::Regex,
Box<
dyn Fn(&mut tokio_pty_process_stream::Process<input::buf::Stdin>)
+ Send,
>,
)>,
}
impl Expect {
fn new(cmd: &str, args: &[String]) -> Self {
Self {
process: tokio_pty_process_stream::Process::new(
cmd,
args,
input::buf::Stdin::new(),
),
expectations: vec![],
}
}
fn expect<
F: Fn(&mut tokio_pty_process_stream::Process<input::buf::Stdin>)
+ Send
+ 'static,
>(
&mut self,
rx: &str,
cb: F,
) {
self.expectations
.push((regex::Regex::new(rx).unwrap(), Box::new(cb)));
}
}
impl futures::future::Future for Expect {
type Item = ();
type Error = ();
fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
loop {
let event = futures::try_ready!(self
.process
.poll()
.map_err(|e| panic!(e)));
match event {
Some(tokio_pty_process_stream::Event::Output { data }) => {
let s = std::string::String::from_utf8_lossy(&data);
let mut found = None;
for (rx, cb) in &self.expectations {
if rx.is_match(&s) {
found = Some(cb);
break;
}
}
if let Some(cb) = found {
cb(&mut self.process);
}
}
Some(tokio_pty_process_stream::Event::CommandExit {
..
}) => break,
None => break,
_ => {}
}
}
Ok(futures::Async::Ready(()))
}
}
fn main() {
tokio::run(futures::future::lazy(|| {
let mut expect = Expect::new("nethack", &[]);
expect.expect(r"Shall I pick.*[ynaq]", |process| {
println!("shall i pick");
process.input().send(b"n");
});
expect.expect(r"Pick a role", |process| {
println!("pick a role");
process.input().send(b"w");
});
expect.expect(r"Pick a race", |process| {
println!("pick a race");
process.input().send(b"e");
});
expect.expect(r"Pick a gender", |process| {
println!("pick a gender");
process.input().send(b"f");
});
expect.expect(r"start game", |process| {
println!("start game");
process.input().send(b"y");
});
expect.expect(r"welcome to NetHack", |process| {
println!("welcome");
process.input().send(b"#quit\n");
});
expect.expect(r"Really quit", |process| {
println!("really quit");
process.input().send(b"y");
});
expect.expect(
r"Do you want your possessions identified",
|process| {
println!("dywypi");
process.input().send(b"n");
},
);
expect.expect(r"--More--", |process| {
println!("more");
process.input().send(b" ");
});
expect.expect(
r"Do you want to see the dungeon overview",
|process| {
println!("dungeon overview");
process.input().send(b"n");
},
);
expect
}));
}
|