• Stars
    star
    139
  • Rank 262,954 (Top 6 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A rust library for controlling interactive programs in a pseudo-terminal

Build coverage status crate docs.rs

expectrl

Expectrl is a tool for automating terminal applications.

Expectrl is a rust module for spawning child applications and controlling them and responding to expected patterns in process's output. Expectrl works like Don Libes' Expect. Expectrl allows your script to spawn a child application and control it as if a human were typing commands.

Using the library you can:

  • Spawn process
  • Control process
  • Interact with process's IO(input/output).

expectrl like original expect may shine when you're working with interactive applications. If your application is not interactive you may not find the library the best choise.

Usage

Add expectrl to your Cargo.toml.

# Cargo.toml
[dependencies]
expectrl = "0.7"

An example where the program simulates a used interacting with ftp.

use expectrl::{Regex, Eof, Error, Expect};

fn main() -> Result<(), Error> {
    let mut p = expectrl::spawn("ftp speedtest.tele2.net")?;
    p.expect(Regex("Name \\(.*\\):"))?;
    p.send_line("anonymous")?;
    p.expect("Password")?;
    p.send_line("test")?;
    p.expect("ftp>")?;
    p.send_line("cd upload")?;
    p.expect("successfully changed.\r\nftp>")?;
    p.send_line("pwd")?;
    p.expect(Regex("[0-9]+ \"/upload\""))?;
    p.send_line("exit")?;
    p.expect(Eof)?;

    Ok(())
}

The same example but the password will be read from stdin.

use std::io::stdout;

use expectrl::{
    interact::{actions::lookup::Lookup, InteractSession},
    stream::stdin::Stdin,
    ControlCode, Error, Expect, Regex,
};

fn main() -> Result<(), Error> {
    let mut p = expectrl::spawn("ftp bks4-speedtest-1.tele2.net")?;

    let mut auth = false;
    let mut login_lookup = Lookup::new();
    let mut stdin = Stdin::open()?;

    InteractSession::new(&mut p, &mut stdin, stdout(), &mut auth)
        .set_output_action(move |ctx| {
            if login_lookup
                .on(ctx.buf, ctx.eof, "Login successful")?
                .is_some()
            {
                **ctx.state = true;
                return Ok(true);
            }

            Ok(false)
        })
        .spawn()?;

    stdin.close()?;

    if !auth {
        println!("An authefication was not passed");
        return Ok(());
    }

    p.expect("ftp>")?;
    p.send_line("cd upload")?;
    p.expect("successfully changed.")?;
    p.send_line("pwd")?;
    p.expect(Regex("[0-9]+ \"/upload\""))?;
    p.send(ControlCode::EndOfTransmission)?;
    p.expect("Goodbye.")?;

    Ok(())
}

Features

  • It has an async support (To enable them you must turn on an async feature).
  • It supports logging.
  • It supports interact function.
  • It works on windows.

Notes

It was originally inspired by philippkeller/rexpect and pexpect.

Licensed under MIT License