expectrl/
lib.rs

1#![warn(
2    missing_docs,
3    future_incompatible,
4    single_use_lifetimes,
5    trivial_casts,
6    trivial_numeric_casts,
7    unreachable_pub,
8    unused_extern_crates,
9    unused_import_braces,
10    unused_qualifications,
11    unused_results,
12    unused_variables,
13    variant_size_differences,
14    missing_debug_implementations,
15    rust_2018_idioms
16)]
17#![allow(clippy::uninlined_format_args)]
18
19//! # A tool for automating terminal applications on alike original expect.
20//!
21//! Using the library you can:
22//!
23//! - Spawn process
24//! - Control process
25//! - Interact with process's IO(input/output).
26//!
27//! `expectrl` like original `expect` may shine when you're working with interactive applications.
28//! If your application is not interactive you may not find the library the best choise.
29//!
30//! ## Feature flags
31//!
32//! - `async`: Enables a async/await public API.
33//! - `polling`: Enables polling backend in interact session. Be cautious to use it on windows.
34//!
35//! ## Examples
36//!
37//! ### An example for interacting via ftp.
38//!
39//! ```no_run,ignore
40//! use expectrl::{spawn, Regex, Eof, WaitStatus};
41//!
42//! let mut p = spawn("ftp speedtest.tele2.net").unwrap();
43//! p.expect(Regex("Name \\(.*\\):")).unwrap();
44//! p.send_line("anonymous").unwrap();
45//! p.expect("Password").unwrap();
46//! p.send_line("test").unwrap();
47//! p.expect("ftp>").unwrap();
48//! p.send_line("cd upload").unwrap();
49//! p.expect("successfully changed.\r\nftp>").unwrap();
50//! p.send_line("pwd").unwrap();
51//! p.expect(Regex("[0-9]+ \"/upload\"")).unwrap();
52//! p.send_line("exit").unwrap();
53//! p.expect(Eof).unwrap();
54//! assert_eq!(p.wait().unwrap(), WaitStatus::Exited(p.pid(), 0));
55//! ```
56//!
57//! *The example inspired by the one in [philippkeller/rexpect].*
58//!
59//! ### An example when `Command` is used.
60//!
61//! ```no_run,ignore
62//! use std::{process::Command, io::prelude::*};
63//! use expectrl::Session;
64//!
65//! let mut echo_hello = Command::new("sh");
66//! echo_hello.arg("-c").arg("echo hello");
67//!
68//! let mut p = Session::spawn(echo_hello).unwrap();
69//! p.expect("hello").unwrap();
70//! ```
71//!
72//! ### An example of logging.
73//!
74//! ```no_run,ignore
75//! use std::io::{stdout, prelude::*};
76//! use expectrl::{spawn, session::log};
77//!
78//! let mut sh = log(spawn("sh").unwrap(), stdout()).unwrap();
79//!
80//! writeln!(sh, "Hello World").unwrap();
81//! ```
82//!
83//! ### An example of `async` feature.
84//!
85//! You need to provide a `features=["async"]` flag to use it.
86//!
87//! ```no_run,ignore
88//! use expectrl::spawn;
89//!
90//! let mut p = spawn("cat").await.unwrap();
91//! p.expect("hello").await.unwrap();
92//! ```
93//!
94//! ### An example of interact session with `STDIN` and `STDOUT`
95//!
96//! ```no_run,ignore
97//! use expectrl::{spawn, stream::stdin::Stdin};
98//! use std::io::stdout;
99//!
100//! let mut sh = spawn("cat").expect("Failed to spawn a 'cat' process");
101//!
102//! let mut stdin = Stdin::open().expect("Failed to create stdin");
103//!
104//! sh.interact(&mut stdin, stdout())
105//!     .spawn()
106//!     .expect("Failed to start interact session");
107//!
108//! stdin.close().expect("Failed to close a stdin");
109//! ```
110//!
111//! [For more examples, check the examples directory.](https://github.com/zhiburt/expectrl/tree/main/examples)
112
113mod captures;
114mod check_macros;
115mod control_code;
116mod error;
117mod expect;
118mod needle;
119
120#[cfg(all(windows, feature = "polling"))]
121mod waiter;
122
123pub mod interact;
124pub mod process;
125pub mod repl;
126pub mod session;
127pub mod stream;
128
129pub use captures::Captures;
130pub use control_code::ControlCode;
131pub use error::Error;
132pub use needle::{Any, Eof, NBytes, Needle, Regex};
133
134pub use expect::Expect;
135pub use session::Session;
136
137#[cfg(feature = "async")]
138pub use expect::AsyncExpect;
139
140use session::OsSession;
141
142/// Spawn spawnes a new session.
143///
144/// It accepts a command and possibly arguments just as string.
145/// It doesn't parses ENV variables. For complex constrictions use [`Session::spawn`].
146///
147/// # Example
148///
149/// ```no_run,ignore
150/// use std::{thread, time::Duration, io::{Read, Write}};
151/// use expectrl::{spawn, ControlCode};
152///
153/// let mut p = spawn("cat").unwrap();
154/// p.send_line("Hello World").unwrap();
155///
156/// thread::sleep(Duration::from_millis(300)); // give 'cat' some time to set up
157/// p.send(ControlCode::EndOfText).unwrap(); // abort: SIGINT
158///
159/// let mut buf = String::new();
160/// p.read_to_string(&mut buf).unwrap();
161///
162/// assert_eq!(buf, "Hello World\r\n");
163/// ```
164///
165/// [`Session::spawn`]: ./struct.Session.html?#spawn
166pub fn spawn<S>(cmd: S) -> Result<OsSession, Error>
167where
168    S: AsRef<str>,
169{
170    Session::spawn_cmd(cmd.as_ref())
171}