Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ Simple example for interacting via ftp:
```rust,no_run
use rexpect::spawn;
use rexpect::error::*;
use std::time;

fn do_ftp() -> Result<(), Error> {
let mut p = spawn("ftp speedtest.tele2.net", Some(30_000))?;
let mut p = spawn("ftp speedtest.tele2.net", Some(time::Duration::from_secs(30)))?;
p.exp_regex("Name \\(.*\\):")?;
p.send_line("anonymous")?;
p.exp_string("Password")?;
Expand All @@ -55,9 +56,10 @@ fn main() {
```rust,no_run
use rexpect::spawn_bash;
use rexpect::error::*;
use std::time;

fn do_bash() -> Result<(), Error> {
let mut p = spawn_bash(Some(2000))?;
let mut p = spawn_bash(Some(time::Duration::from_secs(2)))?;

// case 1: wait until program is done
p.send_line("hostname")?;
Expand Down Expand Up @@ -105,9 +107,10 @@ goes into nirvana. There are two functions to ensure that:
```rust,no_run
use rexpect::spawn_bash;
use rexpect::error::*;
use std::time;

fn do_bash_jobcontrol() -> Result<(), Error> {
let mut p = spawn_bash(Some(1000))?;
let mut p = spawn_bash(Some(time::Duration::from_secs(1)))?;
p.execute("ping 8.8.8.8", "bytes of data")?;
p.send_control('z')?;
p.wait_for_prompt()?;
Expand Down
3 changes: 2 additions & 1 deletion examples/bash.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use rexpect::error::Error;
use rexpect::spawn_bash;
use std::time;

fn main() -> Result<(), Error> {
let mut p = spawn_bash(Some(1000))?;
let mut p = spawn_bash(Some(time::Duration::from_secs(1)))?;
p.execute("ping 8.8.8.8", "bytes")?;
p.send_control('z')?;
p.wait_for_prompt()?;
Expand Down
4 changes: 3 additions & 1 deletion examples/bash_read.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::time;

use rexpect::error::Error;
use rexpect::spawn_bash;

fn main() -> Result<(), Error> {
let mut p = spawn_bash(Some(2000))?;
let mut p = spawn_bash(Some(time::Duration::from_secs(2)))?;

// case 1: wait until program is done
p.send_line("hostname")?;
Expand Down
8 changes: 6 additions & 2 deletions examples/exit_code.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
use rexpect::error::Error;
use rexpect::process::wait;
use rexpect::spawn;
use std::time;

/// The following code emits:
/// cat exited with code 0, all good!
/// cat exited with code 1
/// Output (stdout and stderr): cat: /this/does/not/exist: No such file or directory
fn main() -> Result<(), Error> {
let p = spawn("cat /etc/passwd", Some(2000))?;
let p = spawn("cat /etc/passwd", Some(time::Duration::from_secs(2)))?;
match p.process.wait() {
Ok(wait::WaitStatus::Exited(_, 0)) => println!("cat exited with code 0, all good!"),
_ => println!("cat exited with code >0, or it was killed"),
}

let mut p = spawn("cat /this/does/not/exist", Some(2000))?;
let mut p = spawn(
"cat /this/does/not/exist",
Some(time::Duration::from_secs(2)),
)?;
match p.process.wait() {
Ok(wait::WaitStatus::Exited(_, 0)) => println!("cat succeeded"),
Ok(wait::WaitStatus::Exited(_, c)) => {
Expand Down
6 changes: 5 additions & 1 deletion examples/ftp.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use rexpect::error::Error;
use rexpect::spawn;
use std::time;

fn main() -> Result<(), Error> {
let mut p = spawn("ftp speedtest.tele2.net", Some(2000))?;
let mut p = spawn(
"ftp speedtest.tele2.net",
Some(time::Duration::from_secs(2)),
)?;
p.exp_regex("Name \\(.*\\):")?;
p.send_line("anonymous")?;
p.exp_string("Password")?;
Expand Down
3 changes: 2 additions & 1 deletion examples/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use rexpect::error::Error;
use rexpect::session::PtyReplSession;
use rexpect::spawn;
use std::time;

fn ed_session() -> Result<PtyReplSession, Error> {
let mut ed = PtyReplSession {
Expand All @@ -12,7 +13,7 @@ fn ed_session() -> Result<PtyReplSession, Error> {

// used for `wait_for_prompt()`
prompt: "> ".to_owned(),
pty_session: spawn("/bin/ed -p '> '", Some(2000))?,
pty_session: spawn("/bin/ed -p '> '", Some(time::Duration::from_secs(2)))?,
// command which is sent when the instance of this struct is dropped
// in the below example this is not needed, but if you don't explicitly
// exit a REPL then rexpect tries to send a SIGTERM and depending on the repl
Expand Down
3 changes: 2 additions & 1 deletion examples/tcp.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use rexpect::spawn_stream;
use std::error::Error;
use std::net::TcpStream;
use std::time;

fn main() -> Result<(), Box<dyn Error>> {
let tcp = TcpStream::connect("www.google.com:80")?;
let tcp_w = tcp.try_clone()?;
let mut session = spawn_stream(tcp, tcp_w, Some(2000));
let mut session = spawn_stream(tcp, tcp_w, Some(time::Duration::from_secs(2)));
session.send_line("GET / HTTP/1.1")?;
session.send_line("Host: www.google.com")?;
session.send_line("Accept-Language: fr")?;
Expand Down
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
//!
//! use rexpect::spawn;
//! use rexpect::error::Error;
//! use std::time;
//!
//! fn main() -> Result<(), Error> {
//! let mut p = spawn("ftp speedtest.tele2.net", Some(2000))?;
//! let mut p = spawn("ftp speedtest.tele2.net", Some(time::Duration::from_secs(2)))?;
//! p.exp_regex("Name \\(.*\\):")?;
//! p.send_line("anonymous")?;
//! p.exp_string("Password")?;
Expand Down Expand Up @@ -48,9 +49,10 @@
//! ```no_run
//! use rexpect::spawn_bash;
//! use rexpect::error::Error;
//! use std::time;
//!
//! fn main() -> Result<(), Error> {
//! let mut p = spawn_bash(Some(30_000))?;
//! let mut p = spawn_bash(Some(time::Duration::from_secs(30)))?;
//! p.execute("ping 8.8.8.8", "bytes of data")?;
//! p.send_control('z')?;
//! p.wait_for_prompt()?;
Expand All @@ -74,7 +76,8 @@ pub mod reader;
pub mod session;

pub use reader::ReadUntil;
pub use session::{spawn, spawn_bash, spawn_python, spawn_stream, spawn_with_options};
pub use session::Builder;
pub use session::{spawn, spawn_bash, spawn_python, spawn_stream};

// include the README.md here to test its doc
#[doc = include_str!("../README.md")]
Expand Down
4 changes: 2 additions & 2 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ impl PtyProcess {
/// At the drop of `PtyProcess` the running process is killed. This is blocking forever if
/// the process does not react to a normal kill. If `kill_timeout` is set the process is
/// `kill -9`ed after duration
pub fn set_kill_timeout(&mut self, timeout_ms: Option<u64>) {
self.kill_timeout = timeout_ms.map(time::Duration::from_millis);
pub fn set_kill_timeout(&mut self, timeout: Option<time::Duration>) {
self.kill_timeout = timeout;
}

/// Get status of child process, non-blocking.
Expand Down
26 changes: 21 additions & 5 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,12 @@ pub fn find(needle: &ReadUntil, buffer: &str, eof: bool) -> Option<(usize, usize
/// + `None`: `read_until` is blocking forever. This is probably not what you want
/// + `Some(millis)`: after millis milliseconds a timeout error is raised
/// - `strip_ansi_escape_codes`: Whether to filter out escape codes, such as colors.
/// + `Some`: the frequency with which the process will check the output.
/// + `None`: will be 1/1000 of a `timeout` (or `100ms` if `timeout` is None)
#[derive(Default)]
pub struct Options {
pub timeout_ms: Option<u64>,
pub timeout: Option<time::Duration>,
pub poll_frequency: Option<time::Duration>,
pub strip_ansi_escape_codes: bool,
}

Expand All @@ -120,6 +123,7 @@ pub struct NBReader {
buffer: String,
eof: bool,
timeout: Option<time::Duration>,
poll_frequency: time::Duration,
}

impl NBReader {
Expand Down Expand Up @@ -167,13 +171,23 @@ impl NBReader {
// don't do error handling as on an error it was most probably
// the main thread which exited (remote hangup)
});

// Set `poll_frequency` based on the `timeout` (or 100ms in case `timeout` is None) if it is None
let poll_frequency = match options.poll_frequency {
Some(poll_frequency) => poll_frequency,
None => options
.timeout
.map_or(time::Duration::from_millis(100), |t| t / 1000),
};

// allocate string with a initial capacity of 1024, so when appending chars
// we don't need to reallocate memory often
NBReader {
reader: rx,
buffer: String::with_capacity(1024),
eof: false,
timeout: options.timeout_ms.map(time::Duration::from_millis),
timeout: options.timeout,
poll_frequency,
}
}

Expand Down Expand Up @@ -279,7 +293,7 @@ impl NBReader {
}
}
// nothing matched: wait a little
thread::sleep(time::Duration::from_millis(100));
thread::sleep(self.poll_frequency);
}
}

Expand Down Expand Up @@ -406,8 +420,9 @@ mod tests {
let mut r = NBReader::new(
f,
Options {
timeout_ms: None,
timeout: None,
strip_ansi_escape_codes: true,
poll_frequency: None,
},
);
let bytes = r
Expand All @@ -423,8 +438,9 @@ mod tests {
let mut r = NBReader::new(
f,
Options {
timeout_ms: None,
timeout: None,
strip_ansi_escape_codes: true,
poll_frequency: None,
},
);
let bytes = r
Expand Down
Loading