use super::detect::MultiplexerKind;
pub trait EscapeWrapper {
fn wrap(&self, seq: &str) -> String;
}
#[derive(Debug, Clone, Copy)]
pub struct TmuxWrapper;
impl EscapeWrapper for TmuxWrapper {
fn wrap(&self, seq: &str) -> String {
let escaped = seq.replace('\x1b', "\x1b\x1b");
format!("\x1bPtmux;\x1b{}\x1b\\", escaped)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ScreenWrapper;
impl EscapeWrapper for ScreenWrapper {
fn wrap(&self, seq: &str) -> String {
format!("\x1bP{}\x1b\\", seq)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ZellijWrapper;
impl EscapeWrapper for ZellijWrapper {
fn wrap(&self, seq: &str) -> String {
seq.to_string()
}
}
#[derive(Debug, Clone, Copy)]
pub struct NoopWrapper;
impl EscapeWrapper for NoopWrapper {
fn wrap(&self, seq: &str) -> String {
seq.to_string()
}
}
pub fn wrapper_for(kind: MultiplexerKind) -> Box<dyn EscapeWrapper> {
match kind {
MultiplexerKind::Tmux => Box::new(TmuxWrapper),
MultiplexerKind::Screen => Box::new(ScreenWrapper),
MultiplexerKind::Zellij => Box::new(ZellijWrapper),
MultiplexerKind::None => Box::new(NoopWrapper),
}
}
pub fn wrap_sequence(seq: &str, kind: MultiplexerKind) -> String {
let wrapper = wrapper_for(kind);
wrapper.wrap(seq)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tmux_wrapper_basic() {
let wrapper = TmuxWrapper;
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bPtmux;\x1b\x1b\x1b[?2026h\x1b\\");
}
#[test]
fn test_tmux_wrapper_multiple_escapes() {
let wrapper = TmuxWrapper;
let seq = "\x1b[?2026h\x1b[?2027h";
let wrapped = wrapper.wrap(seq);
assert_eq!(
wrapped,
"\x1bPtmux;\x1b\x1b\x1b[?2026h\x1b\x1b[?2027h\x1b\\"
);
}
#[test]
fn test_tmux_wrapper_no_escapes() {
let wrapper = TmuxWrapper;
let seq = "plain text";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bPtmux;\x1bplain text\x1b\\");
}
#[test]
fn test_screen_wrapper_basic() {
let wrapper = ScreenWrapper;
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bP\x1b[?2026h\x1b\\");
}
#[test]
fn test_screen_wrapper_multiple_escapes() {
let wrapper = ScreenWrapper;
let seq = "\x1b[?2026h\x1b[?2027h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bP\x1b[?2026h\x1b[?2027h\x1b\\");
}
#[test]
fn test_zellij_wrapper_passthrough() {
let wrapper = ZellijWrapper;
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, seq);
}
#[test]
fn test_noop_wrapper_passthrough() {
let wrapper = NoopWrapper;
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, seq);
}
#[test]
fn test_wrapper_for_tmux() {
let wrapper = wrapper_for(MultiplexerKind::Tmux);
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bPtmux;\x1b\x1b\x1b[?2026h\x1b\\");
}
#[test]
fn test_wrapper_for_screen() {
let wrapper = wrapper_for(MultiplexerKind::Screen);
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, "\x1bP\x1b[?2026h\x1b\\");
}
#[test]
fn test_wrapper_for_zellij() {
let wrapper = wrapper_for(MultiplexerKind::Zellij);
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, seq);
}
#[test]
fn test_wrapper_for_none() {
let wrapper = wrapper_for(MultiplexerKind::None);
let seq = "\x1b[?2026h";
let wrapped = wrapper.wrap(seq);
assert_eq!(wrapped, seq);
}
#[test]
fn test_wrap_sequence_tmux() {
let seq = "\x1b[?2026h";
let wrapped = wrap_sequence(seq, MultiplexerKind::Tmux);
assert_eq!(wrapped, "\x1bPtmux;\x1b\x1b\x1b[?2026h\x1b\\");
}
#[test]
fn test_wrap_sequence_screen() {
let seq = "\x1b[?2026h";
let wrapped = wrap_sequence(seq, MultiplexerKind::Screen);
assert_eq!(wrapped, "\x1bP\x1b[?2026h\x1b\\");
}
#[test]
fn test_wrap_sequence_zellij() {
let seq = "\x1b[?2026h";
let wrapped = wrap_sequence(seq, MultiplexerKind::Zellij);
assert_eq!(wrapped, seq);
}
#[test]
fn test_wrap_sequence_none() {
let seq = "\x1b[?2026h";
let wrapped = wrap_sequence(seq, MultiplexerKind::None);
assert_eq!(wrapped, seq);
}
#[test]
fn test_synchronized_output_sequence() {
let begin = "\x1b[?2026h";
let end = "\x1b[?2026l";
let begin_wrapped = wrap_sequence(begin, MultiplexerKind::Tmux);
let end_wrapped = wrap_sequence(end, MultiplexerKind::Tmux);
assert_eq!(begin_wrapped, "\x1bPtmux;\x1b\x1b\x1b[?2026h\x1b\\");
assert_eq!(end_wrapped, "\x1bPtmux;\x1b\x1b\x1b[?2026l\x1b\\");
}
#[test]
fn test_empty_sequence() {
let seq = "";
let wrapped = wrap_sequence(seq, MultiplexerKind::Tmux);
assert_eq!(wrapped, "\x1bPtmux;\x1b\x1b\\");
}
}