use std::time::Duration;
use rust_expect::interact::{
HookBuilder, HookManager, InputFilter, InteractionMode, OutputFilter, Terminal, TerminalMode,
TerminalSize, TerminalState,
};
use rust_expect::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
println!("rust-expect Interactive Session Example");
println!("=======================================\n");
println!("1. Terminal state...");
let state = TerminalState::default();
println!(" Default terminal state created");
println!(" Mode: {:?}", state.mode);
println!(" Echo: {}", state.echo);
println!(" Canonical: {}", state.canonical);
println!("\n2. Terminal modes...");
let terminal_modes = [
TerminalMode::Raw,
TerminalMode::Cooked,
TerminalMode::Cbreak,
];
for mode in terminal_modes {
println!(" Mode: {mode:?}");
}
println!("\n3. Terminal size...");
let size = TerminalSize::default();
println!(" Default size: {}x{}", size.cols, size.rows);
let custom_size = TerminalSize::new(120, 40);
println!(" Custom size: {}x{}", custom_size.cols, custom_size.rows);
println!("\n4. Terminal handle...");
let terminal = Terminal::new();
println!(" Terminal created");
println!(" Is running: {}", terminal.is_running());
println!(" Current mode: {:?}", terminal.mode());
terminal.set_running(true);
println!(" Set running: {}", terminal.is_running());
println!("\n5. Interaction modes...");
let mode = InteractionMode::new()
.with_local_echo(true)
.with_crlf(true)
.with_exit_char(Some(0x1d));
println!(" Local echo: {}", mode.local_echo);
println!(" CRLF: {}", mode.crlf);
println!(" Exit char: {:?}", mode.exit_char);
println!("\n6. Setting up interaction hooks...");
let mut hook_manager = HookManager::new();
hook_manager.add_input_hook(|data| {
data.iter().map(u8::to_ascii_uppercase).collect()
});
hook_manager.add_output_hook(|data| {
data.iter()
.copied()
.filter(|&b| b >= 0x20 || b == b'\n')
.collect()
});
println!(" Input hook added (uppercase conversion)");
println!(" Output hook added (control char filter)");
let result = hook_manager.process_input(b"hello".to_vec());
println!(" Test: 'hello' -> '{}'", String::from_utf8_lossy(&result));
println!("\n7. Hook builder pattern...");
let _manager = HookBuilder::new()
.with_crlf() .with_echo() .with_logging() .build();
println!(" Built hook manager with CRLF, echo, and logging");
println!("\n8. Input/Output filters...");
let input_filter = InputFilter::new()
.filter(b"xyz") .with_control(false);
let filtered = input_filter.apply(b"abcxyz123");
println!(
" Input filter applied: 'abcxyz123' -> '{}'",
String::from_utf8_lossy(&filtered)
);
let output_filter = OutputFilter::new()
.with_strip_ansi(true)
.with_normalize_newlines(true);
let normalized = output_filter.apply(b"line1\r\nline2\r\n");
println!(
" Output filter (normalize CRLF): {:?}",
String::from_utf8_lossy(&normalized)
);
println!("\n9. Semi-interactive automation...");
let mut session = Session::spawn("/bin/sh", &[]).await?;
session
.expect_timeout(Pattern::shell_prompt(), Duration::from_secs(2))
.await?;
let commands = [
("pwd", "Print working directory"),
("whoami", "Show current user"),
("date", "Display current date"),
];
for (cmd, description) in commands {
println!(" {cmd} -> {description}");
session.send_line(cmd).await?;
session
.expect_timeout(Pattern::shell_prompt(), Duration::from_secs(2))
.await?;
}
session.send_line("exit").await?;
session.wait().await?;
println!("\nInteractive session examples completed successfully!");
Ok(())
}