use serde::{Deserialize, Serialize};
macro_rules! mode_flag {
($(#[$m:meta])* $name:ident) => {
$(#[$m])*
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct $name(bool);
impl $name {
#[must_use]
pub const fn new(on: bool) -> Self { Self(on) }
#[must_use]
pub const fn enabled(self) -> bool { self.0 }
}
};
}
mode_flag! {
BracketedPaste
}
mode_flag! {
CursorKeys
}
mode_flag! {
FocusReporting
}
mode_flag! {
SyncOutput
}
mode_flag! {
MouseSgr
}
mode_flag! {
CursorVisible
}
mode_flag! {
AutoWrap
}
mode_flag! {
AltScreen
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MouseTracking {
#[default]
Off,
Click,
Drag,
Motion,
}
impl MouseTracking {
#[must_use]
pub const fn is_on(self) -> bool {
!matches!(self, Self::Off)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ModeSet {
pub bracketed_paste: BracketedPaste,
pub cursor_keys: CursorKeys,
pub focus_reporting: FocusReporting,
pub sync_output: SyncOutput,
pub mouse: MouseTracking,
pub mouse_sgr: MouseSgr,
pub cursor_visible: CursorVisible,
pub autowrap: AutoWrap,
pub alt_screen: AltScreen,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_mode_cannot_be_substituted_for_another() {
fn sanitize(_text: &str, bracketed: BracketedPaste) -> bool {
bracketed.enabled()
}
assert!(sanitize("x", BracketedPaste::new(true)));
assert!(!sanitize("x", BracketedPaste::new(false)));
}
#[test]
fn mouse_levels_are_exclusive_by_construction() {
let m = MouseTracking::Drag;
assert!(m.is_on());
assert_eq!(MouseTracking::default(), MouseTracking::Off);
assert!(!MouseTracking::Off.is_on());
}
#[test]
fn modes_default_to_off_which_is_what_a_fresh_terminal_means() {
let m = ModeSet::default();
assert!(!m.bracketed_paste.enabled());
assert!(!m.cursor_keys.enabled());
assert!(!m.sync_output.enabled());
assert!(!m.mouse.is_on());
}
#[test]
fn a_mode_flag_is_wire_identical_to_the_bool_it_wraps() {
let a = serde_json::to_string(&BracketedPaste::new(true)).unwrap();
let b = serde_json::to_string(&true).unwrap();
assert_eq!(a, b);
}
}