use std::io::Write;
use crossterm::{
event::{
DisableBracketedPaste, EnableBracketedPaste, KeyboardEnhancementFlags,
PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
},
execute,
};
const ENABLE_MODIFY_OTHER_KEYS: &[u8] = b"\x1b[>4;2m";
const DISABLE_MODIFY_OTHER_KEYS: &[u8] = b"\x1b[>4;0m";
pub(super) struct Enabled {
bracketed_paste: bool,
modified_keys: bool,
keyboard_enhancements: bool,
}
impl Enabled {
pub(super) fn acquire() -> Self {
let extended = should_request_extended_keyboard_protocols();
Self {
bracketed_paste: enable_bracketed_paste().is_ok(),
modified_keys: extended && enable_modified_keys().is_ok(),
keyboard_enhancements: extended && enable_keyboard_enhancements().is_ok(),
}
}
pub(super) fn release(self) {
if self.keyboard_enhancements {
let _ = disable_keyboard_enhancements();
}
if self.modified_keys {
let _ = disable_modified_keys();
}
if self.bracketed_paste {
let _ = disable_bracketed_paste();
}
}
}
fn enable_bracketed_paste() -> std::io::Result<()> {
execute!(std::io::stdout(), EnableBracketedPaste)
}
fn disable_bracketed_paste() -> std::io::Result<()> {
execute!(std::io::stdout(), DisableBracketedPaste)
}
fn enable_keyboard_enhancements() -> std::io::Result<()> {
execute!(
std::io::stdout(),
PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES)
)
}
fn disable_keyboard_enhancements() -> std::io::Result<()> {
execute!(std::io::stdout(), PopKeyboardEnhancementFlags)
}
fn enable_modified_keys() -> std::io::Result<()> {
let mut stdout = std::io::stdout();
stdout.write_all(ENABLE_MODIFY_OTHER_KEYS)?;
stdout.flush()
}
fn disable_modified_keys() -> std::io::Result<()> {
let mut stdout = std::io::stdout();
stdout.write_all(DISABLE_MODIFY_OTHER_KEYS)?;
stdout.flush()
}
pub(super) fn should_request_extended_keyboard_protocols() -> bool {
!cfg!(windows)
}
#[cfg(test)]
#[path = "keyboard_modes_tests.rs"]
mod tests;