mxsh 0.2.0

Embeddable POSIX-style shell parser and runtime
Documentation
#![cfg(all(feature = "embed", feature = "frontend", feature = "test-support"))]

use mxsh::ShellBuilder;
use mxsh::embed::StdioConfig;
use mxsh::policy::{ShellOptionSchema, ShellOptionSpec, ShellOptions};
use mxsh::runtime::testing::{InMemoryRuntime, StringStdioOut};

fn strict_option_schema() -> ShellOptionSchema {
    ShellOptionSchema::empty().with_option(
        ShellOptionSpec::new(ShellOptions::ERREXIT)
            .with_short_name('E')
            .with_long_name("strict"),
    )
}

#[test]
fn set_builtin_uses_config_option_schema() {
    let stdout = StringStdioOut::new();
    let stderr = StringStdioOut::new();
    let mut shell = ShellBuilder::new()
        .option_schema(strict_option_schema())
        .stdio(StdioConfig {
            stdout: stdout.fd(),
            stderr: stderr.fd(),
            ..StdioConfig::default()
        })
        .new_session()
        .expect("session should build");
    let mut runtime = InMemoryRuntime::new();

    let result = shell.run(&mut runtime, "set -E; echo $-; set +o");

    assert_eq!(result.status, 0);
    assert!(shell.has_option(ShellOptions::ERREXIT));
    assert_eq!(stderr.collect(), "");
    let output = stdout.collect();
    assert!(
        output.lines().any(|line| line == "E"),
        "unexpected output: {output:?}"
    );
    assert!(
        output.lines().any(|line| line == "set -o strict"),
        "unexpected output: {output:?}"
    );
}

#[test]
fn cli_uses_config_option_schema() {
    let stdout = StringStdioOut::new();
    let stderr = StringStdioOut::new();
    let argv = vec![
        "toysh".to_string(),
        "-E".to_string(),
        "-c".to_string(),
        "false; echo after".to_string(),
    ];
    let mut shell = ShellBuilder::new()
        .option_schema(strict_option_schema())
        .stdio(StdioConfig {
            stdout: stdout.fd(),
            stderr: stderr.fd(),
            ..StdioConfig::default()
        })
        .build(InMemoryRuntime::new())
        .expect("shell should build");
    let outcome = shell.run_cli(&argv);

    assert_eq!(outcome.status, 1);
    assert_eq!(outcome.exit_code, Some(1));
    assert_eq!(stdout.collect(), "");
    assert_eq!(stderr.collect(), "");
}