1use crate::Sink;
5use katui_proto::{clipboard, kitty};
6use std::io;
7
8pub fn enter<W: Sink>(out: &mut W) -> io::Result<()> {
11 out.write_all(b"\x1b[?1049h\x1b[?25l")
12}
13
14pub fn leave<W: Sink>(out: &mut W) -> io::Result<()> {
16 out.write_all(b"\x1b[?25h\x1b[?1049l")
17}
18
19pub fn enable_input<W: Sink>(out: &mut W) -> io::Result<()> {
23 out.write_all(b"\x1b[?1003h\x1b[?1006h\x1b[?1016h\x1b[?1004h\x1b[?2004h\x1b[>1u\x1b[?1016$p")
24}
25
26pub fn disable_input<W: Sink>(out: &mut W) -> io::Result<()> {
28 out.write_all(b"\x1b[=0;1u\x1b[<u\x1b[?2004l\x1b[?1004l\x1b[?1016l\x1b[?1006l\x1b[?1003l")
29}
30
31pub fn report_key_releases<W: Sink>(out: &mut W) -> io::Result<()> {
35 out.write_all(b"\x1b[=11;1u")
36}
37
38pub fn terminal_query<W: Sink>(out: &mut W, id: u32) -> io::Result<()> {
41 out.write_all(&kitty::barrier(kitty::ImageId(id)))
42}
43
44pub fn copy_to_clipboard<W: Sink>(out: &mut W, text: &str, multiplexed: bool) -> io::Result<()> {
47 out.write_all(&clipboard::copy(text, multiplexed))
48}
49
50#[cfg(test)]
51mod tests {
52 use super::{disable_input, enable_input, enter, leave, report_key_releases};
53
54 #[test]
55 fn disabling_input_undoes_the_key_release_flags() {
56 let (mut flags, mut off) = (Vec::new(), Vec::new());
57 report_key_releases(&mut flags).expect("writing to a Vec cannot fail");
58 disable_input(&mut off).expect("writing to a Vec cannot fail");
59 assert_eq!(flags, b"\x1b[=11;1u");
60 assert!(
61 off.starts_with(b"\x1b[=0;1u\x1b[<u"),
62 "clearing the flags before popping covers terminals that keep them"
63 );
64 }
65
66 #[test]
67 fn disabling_input_turns_off_every_mode_enabling_set() {
68 let (mut on, mut off) = (Vec::new(), Vec::new());
69 enable_input(&mut on).expect("writing to a Vec cannot fail");
70 disable_input(&mut off).expect("writing to a Vec cannot fail");
71 let (on, off) = (
72 String::from_utf8_lossy(&on).into_owned(),
73 String::from_utf8_lossy(&off).into_owned(),
74 );
75 for mode in ["1003", "1006", "1016", "1004", "2004"] {
76 assert!(on.contains(&format!("?{mode}h")), "{mode} goes on");
77 assert!(off.contains(&format!("?{mode}l")), "{mode} goes off");
78 }
79 }
80
81 #[test]
82 fn enter_and_leave_write_their_exact_sequences() {
83 let mut out = Vec::new();
84 enter(&mut out).expect("writing to a Vec cannot fail");
85 leave(&mut out).expect("writing to a Vec cannot fail");
86 assert_eq!(
87 String::from_utf8_lossy(&out),
88 "\x1b[?1049h\x1b[?25l\x1b[?25h\x1b[?1049l"
89 );
90 }
91}