#![cfg(unix)]
#[allow(dead_code)]
#[macro_use]
mod common;
use common::tmux::Keys::*;
use rand::{RngExt as _, distr::Alphabetic};
use std::{
io::{Result, Write as _},
process::{Child, Command, Stdio},
};
use common::tmux::TmuxController;
use crate::common::SK;
fn connect(name: &str) -> Result<Child> {
Command::new("/bin/sh")
.arg("-c")
.arg(format!("{SK} --remote {name}"))
.stdin(Stdio::piped())
.spawn()
}
fn send(child: &mut Child, msg: &str) -> Result<()> {
let mut b = msg.bytes().collect::<Vec<_>>();
b.push(b'\n');
child.stdin.as_mut().map(|s| s.write_all(&b));
Ok(())
}
fn setup(name: &str, extra_args: &[&str]) -> Result<(TmuxController, Child)> {
let mut tmux = TmuxController::new_named(name)?;
let socket_name = format!(
"sk-test-{name}{}",
rand::rng()
.sample_iter(&Alphabetic)
.take(4)
.map(char::from)
.collect::<String>()
);
tmux.start_sk(
Some(&format!("echo -n -e '{}'", "a\\nb\\nc\\nd")),
&[&["--listen", &socket_name], extra_args].concat(),
)?;
tmux.until(|l| !l.is_empty() && l[0].starts_with(">"))?;
let stream = connect(&socket_name)?;
Ok((tmux, stream))
}
#[test]
fn listen_up() -> std::io::Result<()> {
let (tmux, mut stream) = setup("up", &[])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
send(&mut stream,"up(2)")? ;
@capture[2]trim().starts_with("a");
@capture[4]starts_with("> c");
);
Ok(())
}
#[test]
fn listen_down() -> std::io::Result<()> {
let (tmux, mut stream) = setup("down", &[])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
@keys Up, Up;
@capture[2]trim().starts_with("a");
@capture[4]starts_with("> c");
send(&mut stream, "down(2)")?;
@capture[2]starts_with("> a");
);
Ok(())
}
#[test]
fn listen_abort() -> std::io::Result<()> {
let (tmux, mut stream) = setup("abort", &[])?;
sk_test!(@expand tmux;
send(&mut stream, "abort")?;
@capture[0]trim().contains("$");
);
Ok(())
}
#[test]
fn listen_accept() -> std::io::Result<()> {
let (tmux, mut stream) = setup("accept", &[])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
send(&mut stream, "accept")?;
@output[0]eq("a");
);
Ok(())
}
#[test]
fn listen_accept_key() -> std::io::Result<()> {
let (tmux, mut stream) = setup("accept_key", &[])?;
sk_test!(@expand tmux;
send(&mut stream, "accept(ctrl-a)")?;
@output[0]eq("ctrl-a");
@output[1]eq("a");
);
Ok(())
}
#[test]
fn listen_add_char() -> std::io::Result<()> {
let (tmux, mut stream) = setup("add_char", &[])?;
sk_test!(@expand tmux;
send(&mut stream, "add-char(a)")?;
@capture[0]trim().eq("> a");
);
Ok(())
}
#[test]
fn listen_backward_char() -> std::io::Result<()> {
let (tmux, mut stream) = setup("backward_char", &[])?;
sk_test!(@expand tmux;
@keys Str("hello");
@capture[0]starts_with("> hello");
send(&mut stream, "backward-char")?;
@keys Key('|');
@capture[0]trim().eq("> hell|o");
);
Ok(())
}
#[test]
fn listen_backward_delete_char() -> std::io::Result<()> {
let (tmux, mut stream) = setup("backward_delete_char", &[])?;
sk_test!(@expand tmux;
@keys Str("test");
@capture[0]trim().eq("> test");
send(&mut stream, "backward-delete-char")?;
@capture[0]trim().eq("> tes");
);
Ok(())
}
#[test]
fn listen_backward_delete_char_eof() -> std::io::Result<()> {
let (tmux, mut stream) = setup("backward_delete_char_eof", &[])?;
sk_test!(@expand tmux;
@keys Str("x");
@capture[0]trim().eq("> x");
send(&mut stream, "backward-delete-char/eof")?;
@capture[0]trim().eq(">");
);
Ok(())
}
#[test]
fn listen_backward_kill_word() -> std::io::Result<()> {
let (tmux, mut stream) = setup("backward_kill_word", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "backward-kill-word")?;
@capture[0]trim().eq("> hello");
);
Ok(())
}
#[test]
fn listen_backward_word() -> std::io::Result<()> {
let (tmux, mut stream) = setup("backward_word", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]starts_with("> hello world");
send(&mut stream, "backward-word")?;
@keys Key('|');
@capture[0]trim().eq("> hello |world");
);
Ok(())
}
#[test]
fn listen_end_of_line() -> std::io::Result<()> {
let (tmux, mut stream) = setup("end_of_line", &[])?;
sk_test!(@expand tmux;
@keys Str("hello");
@capture[0]trim().eq("> hello");
send(&mut stream, "beginning-of-line")?;
send(&mut stream, "end-of-line")?;
@keys Key('X');
@capture[0]trim().eq("> helloX");
);
Ok(())
}
#[test]
fn listen_first() -> std::io::Result<()> {
let (tmux, mut stream) = setup("first", &[])?;
sk_test!(@expand tmux;
@keys Up, Up;
@capture[4]starts_with("> c");
send(&mut stream, "first")?;
@capture[2]starts_with("> a");
);
Ok(())
}
#[test]
fn listen_forward_char() -> std::io::Result<()> {
let (tmux, mut stream) = setup("forward_char", &[])?;
sk_test!(@expand tmux;
@keys Str("hello");
@capture[0]trim().eq("> hello");
send(&mut stream, "beginning-of-line")?;
send(&mut stream, "forward-char")?;
@keys Key('X');
@capture[0]trim().eq("> hXello");
);
Ok(())
}
#[test]
fn listen_forward_word() -> std::io::Result<()> {
let (tmux, mut stream) = setup("forward_word", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "beginning-of-line")?;
send(&mut stream, "forward-word")?;
@keys Key('X');
@capture[0]trim().eq("> helloX world");
);
Ok(())
}
#[test]
fn listen_kill_line() -> std::io::Result<()> {
let (tmux, mut stream) = setup("kill_line", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "backward-word")?;
send(&mut stream, "kill-line")?;
@capture[0]trim().eq("> hello");
);
Ok(())
}
#[test]
fn listen_kill_word() -> std::io::Result<()> {
let (tmux, mut stream) = setup("kill_word", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "beginning-of-line")?;
send(&mut stream, "kill-word")?;
@capture[0]trim().eq("> world");
);
Ok(())
}
#[test]
fn listen_last() -> std::io::Result<()> {
let (tmux, mut stream) = setup("last", &[])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
@capture[5]trim().eq("d");
send(&mut stream, "last")?;
@capture[5]starts_with("> d");
);
Ok(())
}
#[test]
fn listen_reload_cmd() -> std::io::Result<()> {
let (tmux, mut stream) = setup("reload_cmd", &[])?;
sk_test!(@expand tmux;
@capture[1]trim().contains("4/4");
send(&mut stream, "reload(printf 'x\\ny\\nz'))")?;
@capture[2]starts_with("> x");
);
Ok(())
}
#[test]
fn listen_select_all() -> std::io::Result<()> {
let (tmux, mut stream) = setup("select_all", &["-m"])?;
sk_test!(@expand tmux;
send(&mut stream, "select-all")?;
@capture[2]trim().eq(">>a");
@capture[3]trim().eq(">b");
@capture[4]trim().eq(">c");
);
Ok(())
}
#[test]
fn listen_select_row() -> std::io::Result<()> {
let (tmux, mut stream) = setup("select_row", &["-m"])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
send(&mut stream, "select-row(2)")?;
@capture[2]trim().eq("> a");
@capture[4]trim().eq(">c");
);
Ok(())
}
#[test]
fn listen_select() -> std::io::Result<()> {
let (tmux, mut stream) = setup("select", &["-m"])?;
sk_test!(@expand tmux;
send(&mut stream, "select")?;
@capture[2]starts_with(">>");
);
Ok(())
}
#[test]
fn listen_toggle() -> std::io::Result<()> {
let (tmux, mut stream) = setup("toggle", &["-m"])?;
sk_test!(@expand tmux;
send(&mut stream, "toggle")?;
@capture[2]starts_with(">>a");
send(&mut stream, "toggle")?;
@capture[2]starts_with("> a");
);
Ok(())
}
#[test]
fn listen_toggle_all() -> std::io::Result<()> {
let (tmux, mut stream) = setup("toggle_all", &["-m"])?;
sk_test!(@expand tmux;
send(&mut stream, "toggle-all")?;
@capture[2]starts_with(">>a");
@capture[3]trim().eq(">b");
@capture[4]trim().eq(">c");
);
Ok(())
}
#[test]
fn listen_toggle_in() -> std::io::Result<()> {
let (tmux, mut stream) = setup("toggle_in", &["-m"])?;
sk_test!(@expand tmux;
@keys Up;
@capture[2]trim().starts_with("a");
@capture[3]starts_with("> b");
send(&mut stream, "toggle-in")?;
@capture[2]starts_with("> a");
@capture[3]trim().starts_with(">b");
);
Ok(())
}
#[test]
fn listen_toggle_out() -> std::io::Result<()> {
let (tmux, mut stream) = setup("toggle_out", &["-m"])?;
sk_test!(@expand tmux;
@capture[2]starts_with("> a");
@capture[3]trim().starts_with("b");
send(&mut stream, "toggle-out")?;
@capture[2]trim().starts_with(">a");
@capture[3]starts_with("> b");
);
Ok(())
}
#[test]
fn listen_top() -> std::io::Result<()> {
let (tmux, mut stream) = setup("top", &[])?;
sk_test!(@expand tmux;
@keys Up, Up;
@capture[4]starts_with("> c");
send(&mut stream, "top")?;
@capture[2]starts_with("> a");
);
Ok(())
}
#[test]
fn listen_unix_line_discard() -> std::io::Result<()> {
let (tmux, mut stream) = setup("unix_line_discard", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "unix-line-discard")?;
@capture[0]trim().eq(">");
);
Ok(())
}
#[test]
fn listen_unix_word_rubout() -> std::io::Result<()> {
let (tmux, mut stream) = setup("unix_word_rubout", &[])?;
sk_test!(@expand tmux;
@keys Str("hello world");
@capture[0]trim().eq("> hello world");
send(&mut stream, "unix-word-rubout")?;
@capture[0]trim().eq("> hello");
);
Ok(())
}
#[test]
fn listen_yank() -> std::io::Result<()> {
let (tmux, mut stream) = setup("yank", &[])?;
sk_test!(@expand tmux;
@keys Str("hello");
@capture[0]trim().eq("> hello");
send(&mut stream, "backward-kill-word")?;
@capture[0]trim().eq(">");
send(&mut stream, "yank")?;
@capture[0]trim().eq("> hello");
);
Ok(())
}