use std::env;
use std::fmt::Write;
use std::sync::OnceLock;
use crate::utils::terminal::{terminal_type, TerminalType};
static TEXT_SIZING_SUPPORTED: OnceLock<bool> = OnceLock::new();
pub fn is_supported() -> bool {
*TEXT_SIZING_SUPPORTED.get_or_init(|| {
if terminal_type() == TerminalType::Kitty {
return true;
}
if env::var("GHOSTTY_RESOURCES_DIR").is_ok() {
return false;
}
false
})
}
pub struct TextSizing;
impl TextSizing {
#[inline]
pub fn size_ratio(tier: u8) -> (u8, u8) {
match tier {
1 => (7, 7), 2 => (5, 6), 3 => (3, 4), 4 => (2, 3), 5 => (3, 5), _ => (1, 3), }
}
pub fn scaled_width(width: u16, tier: u8) -> u16 {
let (n, d) = Self::size_ratio(tier);
let half_width = width / 2;
half_width.saturating_mul(u16::from(d)) / u16::from(n)
}
pub fn escape_sequence(text: &str, tier: u8, width: u16) -> String {
let (n, d) = Self::size_ratio(tier);
let chars: Vec<char> = text.chars().collect();
let chunk_count = chars.len().div_ceil(d as usize);
let width_digits = width.checked_ilog10().unwrap_or(0) as usize + 1;
let capacity = 19 + 2 * width_digits + text.len() + chunk_count * 24;
let mut result = String::with_capacity(capacity);
let _ = write!(result, "\x1b[{}X\x1b[?7l", width);
let _ = write!(result, "\x1b[1B");
let _ = write!(result, "\x1b[{}X\x1b[?7l", width);
let _ = write!(result, "\x1b[1A");
for chunk in chars.chunks(d as usize) {
let _ = write!(result, "\x1b]66;s=2:n={n}:d={d}:w={n};");
result.extend(chunk);
let _ = write!(result, "\x1b\\");
}
result
}
#[inline]
pub const fn height() -> u16 {
2
}
}