use portable_pty::PtySize;
use std::ops::{Add, AddAssign};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PtyConfigOption {
Osc,
Output,
Size(PtySize),
NoCaptureOutput,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PtyConfig {
pub capture_osc: bool,
pub capture_output: bool,
pub pty_size: PtySize,
}
impl Default for PtyConfig {
fn default() -> Self {
Self {
capture_osc: false,
capture_output: true,
pty_size: PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
},
}
}
}
impl PtyConfig {
#[must_use]
pub fn is_osc_capture_enabled(&self) -> bool { self.capture_osc }
#[must_use]
pub fn is_output_capture_enabled(&self) -> bool { self.capture_output }
#[must_use]
pub fn get_pty_size(&self) -> PtySize { self.pty_size }
fn apply(&mut self, option: PtyConfigOption) {
match option {
PtyConfigOption::Osc => self.capture_osc = true,
PtyConfigOption::Output => self.capture_output = true,
PtyConfigOption::Size(size) => self.pty_size = size,
PtyConfigOption::NoCaptureOutput => {
self.capture_osc = false;
self.capture_output = false;
}
}
}
}
impl From<PtyConfigOption> for PtyConfig {
fn from(option: PtyConfigOption) -> Self {
let mut config = PtyConfig::default();
config.apply(option);
config
}
}
impl Add for PtyConfigOption {
type Output = PtyConfig;
fn add(self, rhs: Self) -> PtyConfig {
let mut config = PtyConfig::from(self);
config.apply(rhs);
config
}
}
impl Add<PtyConfigOption> for PtyConfig {
type Output = PtyConfig;
fn add(mut self, rhs: PtyConfigOption) -> PtyConfig {
self.apply(rhs);
self
}
}
impl Add<PtyConfig> for PtyConfigOption {
type Output = PtyConfig;
fn add(self, rhs: PtyConfig) -> PtyConfig { rhs + self }
}
impl AddAssign<PtyConfigOption> for PtyConfig {
fn add_assign(&mut self, rhs: PtyConfigOption) { self.apply(rhs); }
}
impl From<PtySize> for PtyConfigOption {
fn from(size: PtySize) -> Self { PtyConfigOption::Size(size) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pty_config_default() {
let config = PtyConfig::default();
assert!(!config.capture_osc);
assert!(config.capture_output);
assert_eq!(config.pty_size.rows, 24);
assert_eq!(config.pty_size.cols, 80);
}
#[test]
fn test_pty_config_accessors() {
let config = PtyConfig::default();
assert!(!config.is_osc_capture_enabled());
assert!(config.is_output_capture_enabled());
let size = config.get_pty_size();
assert_eq!(size.rows, 24);
assert_eq!(size.cols, 80);
}
#[test]
fn test_pty_config_option_osc() {
let config: PtyConfig = PtyConfigOption::Osc.into();
assert!(config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_pty_config_option_output() {
let config: PtyConfig = PtyConfigOption::Output.into();
assert!(!config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_pty_config_option_size() {
let custom_size = PtySize {
rows: 30,
cols: 120,
pixel_width: 0,
pixel_height: 0,
};
let config: PtyConfig = PtyConfigOption::Size(custom_size).into();
assert_eq!(config.pty_size, custom_size);
assert!(!config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_pty_config_option_no_capture_output() {
let config: PtyConfig = PtyConfigOption::NoCaptureOutput.into();
assert!(!config.capture_osc);
assert!(!config.capture_output);
}
#[test]
fn test_pty_config_option_add() {
let config = PtyConfigOption::Osc + PtyConfigOption::Output;
assert!(config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_pty_config_option_add_with_config() {
let config = PtyConfig::default() + PtyConfigOption::Osc;
assert!(config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_config_plus_option() {
let config = PtyConfigOption::Osc + PtyConfig::default();
assert!(config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_config_add_assign() {
let mut config = PtyConfig::default();
config += PtyConfigOption::Osc;
assert!(config.capture_osc);
assert!(config.capture_output);
}
#[test]
fn test_last_write_wins_capture_flags() {
let config = PtyConfigOption::Osc
+ PtyConfigOption::Output
+ PtyConfigOption::NoCaptureOutput;
assert!(!config.capture_osc);
assert!(!config.capture_output);
}
#[test]
fn test_last_write_wins_size() {
let size1 = PtySize {
rows: 30,
cols: 120,
pixel_width: 0,
pixel_height: 0,
};
let size2 = PtySize {
rows: 40,
cols: 100,
pixel_width: 0,
pixel_height: 0,
};
let config = PtyConfigOption::Size(size1) + PtyConfigOption::Size(size2);
assert_eq!(config.pty_size, size2);
}
#[test]
fn test_complex_combination() {
let custom_size = PtySize {
rows: 50,
cols: 150,
pixel_width: 0,
pixel_height: 0,
};
let config = PtyConfigOption::Osc
+ PtyConfigOption::Output
+ PtyConfigOption::Size(custom_size)
+ PtyConfigOption::NoCaptureOutput
+ PtyConfigOption::Osc;
assert!(config.capture_osc); assert!(!config.capture_output); assert_eq!(config.pty_size, custom_size);
}
#[test]
fn test_pty_size_conversion() {
let size = PtySize {
rows: 25,
cols: 90,
pixel_width: 0,
pixel_height: 0,
};
let option: PtyConfigOption = size.into();
match option {
PtyConfigOption::Size(converted_size) => assert_eq!(converted_size, size),
_ => panic!("Expected Size option"),
}
}
#[test]
fn test_pty_config_equality() {
let config1 = PtyConfigOption::Osc + PtyConfigOption::Output;
let config2 = PtyConfigOption::Output + PtyConfigOption::Osc;
assert_eq!(config1, config2);
}
#[test]
fn test_pty_config_option_equality() {
assert_eq!(PtyConfigOption::Osc, PtyConfigOption::Osc);
assert_eq!(PtyConfigOption::Output, PtyConfigOption::Output);
assert_eq!(
PtyConfigOption::NoCaptureOutput,
PtyConfigOption::NoCaptureOutput
);
let size = PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
};
assert_eq!(PtyConfigOption::Size(size), PtyConfigOption::Size(size));
}
}