#![allow(missing_docs, clippy::pedantic)]
#![cfg(unix)]
#[allow(dead_code)]
mod common;
use std::fs::{self, File, Permissions};
use std::io::{Read, Result, Write};
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use common::tmux::Keys::*;
use common::tmux::{TmuxController, wait};
fn read_file(path: &Path) -> Result<String> {
let mut s = String::new();
File::open(path)?.read_to_string(&mut s)?;
Ok(s)
}
fn run_interactive_execute(name: &str, extra_opts: &[&str]) -> Result<()> {
let mut tmux = TmuxController::new_named(name)?;
let dir = tmux.tempdir.path().to_path_buf();
let script = dir.join("interactive.sh");
let ready = dir.join("ready");
let result = dir.join("keys.txt");
let script_body = r#"#!/usr/bin/env bash
out="$1"
ready="$2"
: > "$ready"
s=""
for _ in 1 2 3 4; do
IFS= read -rsn1 c || break
s="$s$c"
done
printf '%s' "$s" > "$out"
"#;
File::create(&script)?.write_all(script_body.as_bytes())?;
fs::set_permissions(&script, Permissions::from_mode(0o755))?;
let bind = format!(
"--bind='enter:execute(bash {} {} {})'",
script.display(),
result.display(),
ready.display()
);
let mut opts: Vec<&str> = extra_opts.to_vec();
opts.push(bind.as_str());
tmux.start_sk(Some("printf 'aaa\\nbbb\\nccc'"), &opts)?;
tmux.until(|l| l.iter().any(|s| s.trim_start().starts_with(">")))?;
tmux.send_keys(&[Enter])?;
wait(|| {
if ready.exists() {
Ok(())
} else {
Err(std::io::Error::other("child not ready yet"))
}
})?;
tmux.send_keys(&[Key('w'), Key('x'), Key('y'), Key('z')])?;
wait(|| match read_file(&result) {
Ok(s) if s == "wxyz" => Ok(()),
_ => Err(std::io::Error::other("keys not complete yet")),
})
.map_err(|_| {
std::io::Error::other(format!(
"child did not receive all keystrokes; result file = {:?}",
read_file(&result).ok()
))
})?;
tmux.send_keys(&[Str("aaa")])?;
tmux.until(|l| l.iter().any(|s| s.contains("1/3")))?;
Ok(())
}
#[test]
fn execute_interactive_child_keeps_receiving_keys_fullscreen() -> Result<()> {
run_interactive_execute("execute_interactive_fs", &[])
}
#[test]
fn execute_interactive_child_keeps_receiving_keys_inline() -> Result<()> {
run_interactive_execute("execute_interactive_inline", &["--height=40%"])
}