pub(crate) const ESCAPE_PLACEHOLDER_BASE: u32 = 0xE000;
pub(crate) const ESCAPE_PLACEHOLDER_FILLER: char = '\u{E100}';
pub(crate) const PERIOD_ESCAPE_PLACEHOLDER: char = '\u{E02E}';
pub(crate) const fn placeholder_pair_width(placeholder: char) -> usize {
if matches!(placeholder, PERIOD_ESCAPE_PLACEHOLDER) { 1 } else { 2 }
}
pub(crate) fn is_escape_placeholder(scalar: char) -> bool {
('\u{E000}'..='\u{E0FF}').contains(&scalar)
}
pub(crate) fn rendered_width(text: &str) -> usize {
if !text.contains(ESCAPE_PLACEHOLDER_FILLER) {
return text.chars().count();
}
let mut width = 0;
let mut chars = text.chars().peekable();
while let Some(scalar) = chars.next() {
if is_escape_placeholder(scalar) && chars.peek() == Some(&ESCAPE_PLACEHOLDER_FILLER) {
chars.next();
width += placeholder_pair_width(scalar);
} else {
width += 1;
}
}
width
}
pub(crate) fn retains_leading_period_escape(text: &str) -> bool {
let mut chars = text.chars();
let mut digits = 0usize;
loop {
match chars.next() {
Some(scalar) if scalar.is_ascii_digit() => digits += 1,
Some(PERIOD_ESCAPE_PLACEHOLDER) => {
return digits > 0 && chars.next() == Some(ESCAPE_PLACEHOLDER_FILLER);
}
_ => return false,
}
}
}
pub(crate) fn rendered_width_at_line_start(text: &str) -> usize {
rendered_width(text) + usize::from(retains_leading_period_escape(text))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn plain_text_measures_by_scalar_count() {
assert_eq!(rendered_width("hello"), 5);
assert_eq!(rendered_width(""), 0);
}
#[test]
fn period_pair_measures_as_the_bare_period() {
let protected = format!("5{PERIOD_ESCAPE_PLACEHOLDER}{ESCAPE_PLACEHOLDER_FILLER}");
assert_eq!(protected.chars().count(), 3);
assert_eq!(rendered_width(&protected), 2);
}
#[test]
fn other_escape_pairs_keep_their_backslash_width() {
let star = char::from_u32(ESCAPE_PLACEHOLDER_BASE + u32::from(b'*')).expect("valid PUA");
let protected = format!("a{star}{ESCAPE_PLACEHOLDER_FILLER}");
assert_eq!(rendered_width(&protected), 3);
}
#[test]
fn placeholder_without_filler_is_left_alone() {
let protected = format!("a{PERIOD_ESCAPE_PLACEHOLDER}b");
assert_eq!(rendered_width(&protected), 3);
}
#[test]
fn period_placeholder_matches_the_documented_encoding() {
assert_eq!(
char::from_u32(ESCAPE_PLACEHOLDER_BASE + u32::from(b'.')),
Some(PERIOD_ESCAPE_PLACEHOLDER)
);
}
#[test]
fn digits_then_period_pair_keeps_its_backslash_at_a_line_start() {
let protected = format!("5{PERIOD_ESCAPE_PLACEHOLDER}{ESCAPE_PLACEHOLDER_FILLER}");
assert!(retains_leading_period_escape(&protected));
assert_eq!(rendered_width(&protected), 2);
assert_eq!(rendered_width_at_line_start(&protected), 3);
}
#[test]
fn a_period_pair_not_preceded_by_digits_is_dropped_everywhere() {
let protected = format!("a{PERIOD_ESCAPE_PLACEHOLDER}{ESCAPE_PLACEHOLDER_FILLER}");
assert!(!retains_leading_period_escape(&protected));
assert_eq!(rendered_width_at_line_start(&protected), rendered_width(&protected));
}
#[test]
fn a_leading_period_pair_with_no_digits_is_dropped() {
let protected = format!("{PERIOD_ESCAPE_PLACEHOLDER}{ESCAPE_PLACEHOLDER_FILLER}x");
assert!(!retains_leading_period_escape(&protected));
}
#[test]
fn other_leading_escapes_do_not_trigger_the_line_start_adjustment() {
let star = char::from_u32(ESCAPE_PLACEHOLDER_BASE + u32::from(b'*')).expect("valid PUA");
let protected = format!("5{star}{ESCAPE_PLACEHOLDER_FILLER}");
assert!(!retains_leading_period_escape(&protected));
}
}