use std::collections::HashMap;
use std::sync::OnceLock;
use crate::ast::Mode;
use crate::lexer::is_combining_diacritical_mark;
use crate::symbol_registry::lookup_symbol;
fn unicode_symbol_decompositions() -> &'static HashMap<String, String> {
static TABLE: OnceLock<HashMap<String, String>> = OnceLock::new();
TABLE.get_or_init(|| {
let entries: HashMap<&str, &str> = HashMap::from([
("\u{E1}", "a\u{301}"),
("\u{E0}", "a\u{300}"),
("\u{E4}", "a\u{308}"),
("\u{1DF}", "a\u{308}\u{304}"),
("\u{E3}", "a\u{303}"),
("\u{101}", "a\u{304}"),
("\u{103}", "a\u{306}"),
("\u{1EAF}", "a\u{306}\u{301}"),
("\u{1EB1}", "a\u{306}\u{300}"),
("\u{1EB5}", "a\u{306}\u{303}"),
("\u{1CE}", "a\u{30C}"),
("\u{E2}", "a\u{302}"),
("\u{1EA5}", "a\u{302}\u{301}"),
("\u{1EA7}", "a\u{302}\u{300}"),
("\u{1EAB}", "a\u{302}\u{303}"),
("\u{227}", "a\u{307}"),
("\u{1E1}", "a\u{307}\u{304}"),
("\u{E5}", "a\u{30A}"),
("\u{1FB}", "a\u{30A}\u{301}"),
("\u{1E03}", "b\u{307}"),
("\u{107}", "c\u{301}"),
("\u{1E09}", "c\u{327}\u{301}"),
("\u{10D}", "c\u{30C}"),
("\u{109}", "c\u{302}"),
("\u{10B}", "c\u{307}"),
("\u{E7}", "c\u{327}"),
("\u{10F}", "d\u{30C}"),
("\u{1E0B}", "d\u{307}"),
("\u{1E11}", "d\u{327}"),
("\u{E9}", "e\u{301}"),
("\u{E8}", "e\u{300}"),
("\u{EB}", "e\u{308}"),
("\u{1EBD}", "e\u{303}"),
("\u{113}", "e\u{304}"),
("\u{1E17}", "e\u{304}\u{301}"),
("\u{1E15}", "e\u{304}\u{300}"),
("\u{115}", "e\u{306}"),
("\u{1E1D}", "e\u{327}\u{306}"),
("\u{11B}", "e\u{30C}"),
("\u{EA}", "e\u{302}"),
("\u{1EBF}", "e\u{302}\u{301}"),
("\u{1EC1}", "e\u{302}\u{300}"),
("\u{1EC5}", "e\u{302}\u{303}"),
("\u{117}", "e\u{307}"),
("\u{229}", "e\u{327}"),
("\u{1E1F}", "f\u{307}"),
("\u{1F5}", "g\u{301}"),
("\u{1E21}", "g\u{304}"),
("\u{11F}", "g\u{306}"),
("\u{1E7}", "g\u{30C}"),
("\u{11D}", "g\u{302}"),
("\u{121}", "g\u{307}"),
("\u{123}", "g\u{327}"),
("\u{1E27}", "h\u{308}"),
("\u{21F}", "h\u{30C}"),
("\u{125}", "h\u{302}"),
("\u{1E23}", "h\u{307}"),
("\u{1E29}", "h\u{327}"),
("\u{ED}", "i\u{301}"),
("\u{EC}", "i\u{300}"),
("\u{EF}", "i\u{308}"),
("\u{1E2F}", "i\u{308}\u{301}"),
("\u{129}", "i\u{303}"),
("\u{12B}", "i\u{304}"),
("\u{12D}", "i\u{306}"),
("\u{1D0}", "i\u{30C}"),
("\u{EE}", "i\u{302}"),
("\u{1F0}", "j\u{30C}"),
("\u{135}", "j\u{302}"),
("\u{1E31}", "k\u{301}"),
("\u{1E9}", "k\u{30C}"),
("\u{137}", "k\u{327}"),
("\u{13A}", "l\u{301}"),
("\u{13E}", "l\u{30C}"),
("\u{13C}", "l\u{327}"),
("\u{1E3F}", "m\u{301}"),
("\u{1E41}", "m\u{307}"),
("\u{144}", "n\u{301}"),
("\u{1F9}", "n\u{300}"),
("\u{F1}", "n\u{303}"),
("\u{148}", "n\u{30C}"),
("\u{1E45}", "n\u{307}"),
("\u{146}", "n\u{327}"),
("\u{F3}", "o\u{301}"),
("\u{F2}", "o\u{300}"),
("\u{F6}", "o\u{308}"),
("\u{22B}", "o\u{308}\u{304}"),
("\u{F5}", "o\u{303}"),
("\u{1E4D}", "o\u{303}\u{301}"),
("\u{1E4F}", "o\u{303}\u{308}"),
("\u{22D}", "o\u{303}\u{304}"),
("\u{14D}", "o\u{304}"),
("\u{1E53}", "o\u{304}\u{301}"),
("\u{1E51}", "o\u{304}\u{300}"),
("\u{14F}", "o\u{306}"),
("\u{1D2}", "o\u{30C}"),
("\u{F4}", "o\u{302}"),
("\u{1ED1}", "o\u{302}\u{301}"),
("\u{1ED3}", "o\u{302}\u{300}"),
("\u{1ED7}", "o\u{302}\u{303}"),
("\u{22F}", "o\u{307}"),
("\u{231}", "o\u{307}\u{304}"),
("\u{151}", "o\u{30B}"),
("\u{1E55}", "p\u{301}"),
("\u{1E57}", "p\u{307}"),
("\u{155}", "r\u{301}"),
("\u{159}", "r\u{30C}"),
("\u{1E59}", "r\u{307}"),
("\u{157}", "r\u{327}"),
("\u{15B}", "s\u{301}"),
("\u{1E65}", "s\u{301}\u{307}"),
("\u{161}", "s\u{30C}"),
("\u{1E67}", "s\u{30C}\u{307}"),
("\u{15D}", "s\u{302}"),
("\u{1E61}", "s\u{307}"),
("\u{15F}", "s\u{327}"),
("\u{1E97}", "t\u{308}"),
("\u{165}", "t\u{30C}"),
("\u{1E6B}", "t\u{307}"),
("\u{163}", "t\u{327}"),
("\u{FA}", "u\u{301}"),
("\u{F9}", "u\u{300}"),
("\u{FC}", "u\u{308}"),
("\u{1D8}", "u\u{308}\u{301}"),
("\u{1DC}", "u\u{308}\u{300}"),
("\u{1D6}", "u\u{308}\u{304}"),
("\u{1DA}", "u\u{308}\u{30C}"),
("\u{169}", "u\u{303}"),
("\u{1E79}", "u\u{303}\u{301}"),
("\u{16B}", "u\u{304}"),
("\u{1E7B}", "u\u{304}\u{308}"),
("\u{16D}", "u\u{306}"),
("\u{1D4}", "u\u{30C}"),
("\u{FB}", "u\u{302}"),
("\u{16F}", "u\u{30A}"),
("\u{171}", "u\u{30B}"),
("\u{1E7D}", "v\u{303}"),
("\u{1E83}", "w\u{301}"),
("\u{1E81}", "w\u{300}"),
("\u{1E85}", "w\u{308}"),
("\u{175}", "w\u{302}"),
("\u{1E87}", "w\u{307}"),
("\u{1E98}", "w\u{30A}"),
("\u{1E8D}", "x\u{308}"),
("\u{1E8B}", "x\u{307}"),
("\u{FD}", "y\u{301}"),
("\u{1EF3}", "y\u{300}"),
("\u{FF}", "y\u{308}"),
("\u{1EF9}", "y\u{303}"),
("\u{233}", "y\u{304}"),
("\u{177}", "y\u{302}"),
("\u{1E8F}", "y\u{307}"),
("\u{1E99}", "y\u{30A}"),
("\u{17A}", "z\u{301}"),
("\u{17E}", "z\u{30C}"),
("\u{1E91}", "z\u{302}"),
("\u{17C}", "z\u{307}"),
("\u{C1}", "A\u{301}"),
("\u{C0}", "A\u{300}"),
("\u{C4}", "A\u{308}"),
("\u{1DE}", "A\u{308}\u{304}"),
("\u{C3}", "A\u{303}"),
("\u{100}", "A\u{304}"),
("\u{102}", "A\u{306}"),
("\u{1EAE}", "A\u{306}\u{301}"),
("\u{1EB0}", "A\u{306}\u{300}"),
("\u{1EB4}", "A\u{306}\u{303}"),
("\u{1CD}", "A\u{30C}"),
("\u{C2}", "A\u{302}"),
("\u{1EA4}", "A\u{302}\u{301}"),
("\u{1EA6}", "A\u{302}\u{300}"),
("\u{1EAA}", "A\u{302}\u{303}"),
("\u{226}", "A\u{307}"),
("\u{1E0}", "A\u{307}\u{304}"),
("\u{C5}", "A\u{30A}"),
("\u{1FA}", "A\u{30A}\u{301}"),
("\u{1E02}", "B\u{307}"),
("\u{106}", "C\u{301}"),
("\u{1E08}", "C\u{327}\u{301}"),
("\u{10C}", "C\u{30C}"),
("\u{108}", "C\u{302}"),
("\u{10A}", "C\u{307}"),
("\u{C7}", "C\u{327}"),
("\u{10E}", "D\u{30C}"),
("\u{1E0A}", "D\u{307}"),
("\u{1E10}", "D\u{327}"),
("\u{C9}", "E\u{301}"),
("\u{C8}", "E\u{300}"),
("\u{CB}", "E\u{308}"),
("\u{1EBC}", "E\u{303}"),
("\u{112}", "E\u{304}"),
("\u{1E16}", "E\u{304}\u{301}"),
("\u{1E14}", "E\u{304}\u{300}"),
("\u{114}", "E\u{306}"),
("\u{1E1C}", "E\u{327}\u{306}"),
("\u{11A}", "E\u{30C}"),
("\u{CA}", "E\u{302}"),
("\u{1EBE}", "E\u{302}\u{301}"),
("\u{1EC0}", "E\u{302}\u{300}"),
("\u{1EC4}", "E\u{302}\u{303}"),
("\u{116}", "E\u{307}"),
("\u{228}", "E\u{327}"),
("\u{1E1E}", "F\u{307}"),
("\u{1F4}", "G\u{301}"),
("\u{1E20}", "G\u{304}"),
("\u{11E}", "G\u{306}"),
("\u{1E6}", "G\u{30C}"),
("\u{11C}", "G\u{302}"),
("\u{120}", "G\u{307}"),
("\u{122}", "G\u{327}"),
("\u{1E26}", "H\u{308}"),
("\u{21E}", "H\u{30C}"),
("\u{124}", "H\u{302}"),
("\u{1E22}", "H\u{307}"),
("\u{1E28}", "H\u{327}"),
("\u{CD}", "I\u{301}"),
("\u{CC}", "I\u{300}"),
("\u{CF}", "I\u{308}"),
("\u{1E2E}", "I\u{308}\u{301}"),
("\u{128}", "I\u{303}"),
("\u{12A}", "I\u{304}"),
("\u{12C}", "I\u{306}"),
("\u{1CF}", "I\u{30C}"),
("\u{CE}", "I\u{302}"),
("\u{130}", "I\u{307}"),
("\u{134}", "J\u{302}"),
("\u{1E30}", "K\u{301}"),
("\u{1E8}", "K\u{30C}"),
("\u{136}", "K\u{327}"),
("\u{139}", "L\u{301}"),
("\u{13D}", "L\u{30C}"),
("\u{13B}", "L\u{327}"),
("\u{1E3E}", "M\u{301}"),
("\u{1E40}", "M\u{307}"),
("\u{143}", "N\u{301}"),
("\u{1F8}", "N\u{300}"),
("\u{D1}", "N\u{303}"),
("\u{147}", "N\u{30C}"),
("\u{1E44}", "N\u{307}"),
("\u{145}", "N\u{327}"),
("\u{D3}", "O\u{301}"),
("\u{D2}", "O\u{300}"),
("\u{D6}", "O\u{308}"),
("\u{22A}", "O\u{308}\u{304}"),
("\u{D5}", "O\u{303}"),
("\u{1E4C}", "O\u{303}\u{301}"),
("\u{1E4E}", "O\u{303}\u{308}"),
("\u{22C}", "O\u{303}\u{304}"),
("\u{14C}", "O\u{304}"),
("\u{1E52}", "O\u{304}\u{301}"),
("\u{1E50}", "O\u{304}\u{300}"),
("\u{14E}", "O\u{306}"),
("\u{1D1}", "O\u{30C}"),
("\u{D4}", "O\u{302}"),
("\u{1ED0}", "O\u{302}\u{301}"),
("\u{1ED2}", "O\u{302}\u{300}"),
("\u{1ED6}", "O\u{302}\u{303}"),
("\u{22E}", "O\u{307}"),
("\u{230}", "O\u{307}\u{304}"),
("\u{150}", "O\u{30B}"),
("\u{1E54}", "P\u{301}"),
("\u{1E56}", "P\u{307}"),
("\u{154}", "R\u{301}"),
("\u{158}", "R\u{30C}"),
("\u{1E58}", "R\u{307}"),
("\u{156}", "R\u{327}"),
("\u{15A}", "S\u{301}"),
("\u{1E64}", "S\u{301}\u{307}"),
("\u{160}", "S\u{30C}"),
("\u{1E66}", "S\u{30C}\u{307}"),
("\u{15C}", "S\u{302}"),
("\u{1E60}", "S\u{307}"),
("\u{15E}", "S\u{327}"),
("\u{164}", "T\u{30C}"),
("\u{1E6A}", "T\u{307}"),
("\u{162}", "T\u{327}"),
("\u{DA}", "U\u{301}"),
("\u{D9}", "U\u{300}"),
("\u{DC}", "U\u{308}"),
("\u{1D7}", "U\u{308}\u{301}"),
("\u{1DB}", "U\u{308}\u{300}"),
("\u{1D5}", "U\u{308}\u{304}"),
("\u{1D9}", "U\u{308}\u{30C}"),
("\u{168}", "U\u{303}"),
("\u{1E78}", "U\u{303}\u{301}"),
("\u{16A}", "U\u{304}"),
("\u{1E7A}", "U\u{304}\u{308}"),
("\u{16C}", "U\u{306}"),
("\u{1D3}", "U\u{30C}"),
("\u{DB}", "U\u{302}"),
("\u{16E}", "U\u{30A}"),
("\u{170}", "U\u{30B}"),
("\u{1E7C}", "V\u{303}"),
("\u{1E82}", "W\u{301}"),
("\u{1E80}", "W\u{300}"),
("\u{1E84}", "W\u{308}"),
("\u{174}", "W\u{302}"),
("\u{1E86}", "W\u{307}"),
("\u{1E8C}", "X\u{308}"),
("\u{1E8A}", "X\u{307}"),
("\u{DD}", "Y\u{301}"),
("\u{1EF2}", "Y\u{300}"),
("\u{178}", "Y\u{308}"),
("\u{1EF8}", "Y\u{303}"),
("\u{232}", "Y\u{304}"),
("\u{176}", "Y\u{302}"),
("\u{1E8E}", "Y\u{307}"),
("\u{179}", "Z\u{301}"),
("\u{17D}", "Z\u{30C}"),
("\u{1E90}", "Z\u{302}"),
("\u{17B}", "Z\u{307}"),
("\u{3AC}", "\u{3B1}\u{301}"),
("\u{1F70}", "\u{3B1}\u{300}"),
("\u{1FB1}", "\u{3B1}\u{304}"),
("\u{1FB0}", "\u{3B1}\u{306}"),
("\u{3AD}", "\u{3B5}\u{301}"),
("\u{1F72}", "\u{3B5}\u{300}"),
("\u{3AE}", "\u{3B7}\u{301}"),
("\u{1F74}", "\u{3B7}\u{300}"),
("\u{3AF}", "\u{3B9}\u{301}"),
("\u{1F76}", "\u{3B9}\u{300}"),
("\u{3CA}", "\u{3B9}\u{308}"),
("\u{390}", "\u{3B9}\u{308}\u{301}"),
("\u{1FD2}", "\u{3B9}\u{308}\u{300}"),
("\u{1FD1}", "\u{3B9}\u{304}"),
("\u{1FD0}", "\u{3B9}\u{306}"),
("\u{3CC}", "\u{3BF}\u{301}"),
("\u{1F78}", "\u{3BF}\u{300}"),
("\u{3CD}", "\u{3C5}\u{301}"),
("\u{1F7A}", "\u{3C5}\u{300}"),
("\u{3CB}", "\u{3C5}\u{308}"),
("\u{3B0}", "\u{3C5}\u{308}\u{301}"),
("\u{1FE2}", "\u{3C5}\u{308}\u{300}"),
("\u{1FE1}", "\u{3C5}\u{304}"),
("\u{1FE0}", "\u{3C5}\u{306}"),
("\u{3CE}", "\u{3C9}\u{301}"),
("\u{1F7C}", "\u{3C9}\u{300}"),
("\u{38E}", "\u{3A5}\u{301}"),
("\u{1FEA}", "\u{3A5}\u{300}"),
("\u{3AB}", "\u{3A5}\u{308}"),
("\u{1FE9}", "\u{3A5}\u{304}"),
("\u{1FE8}", "\u{3A5}\u{306}"),
("\u{38F}", "\u{3A9}\u{301}"),
("\u{1FFA}", "\u{3A9}\u{300}"),
]);
entries.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect()
})
}
pub(crate) fn normalize_unicode_symbol(mode: Mode, text: &str) -> String {
if text.is_empty() {
return text.to_string();
}
let first = &text[..text
.char_indices()
.nth(1)
.map(|(i, _)| i)
.unwrap_or(text.len())];
if let Some(decomposition) = unicode_symbol_decompositions().get(first)
&& lookup_symbol(mode, first).is_none() {
return format!("{decomposition}{}", &text[first.len()..]);
}
text.to_string()
}
pub(crate) fn trailing_combining_mark_start(text: &str) -> Option<usize> {
let chars: Vec<char> = text.chars().collect();
let mut start = chars.len();
while start > 0 && is_combining_diacritical_mark(chars[start - 1]) {
start -= 1;
}
if start != chars.len() {
Some(start)
} else {
None
}
}
pub(crate) fn unicode_accent_command(mode: Mode, accent: &str) -> Option<String> {
let result = match accent {
"\u{301}" => Some(if mode == Mode::Math { "\\acute" } else { "\\'" }),
"\u{300}" => Some(if mode == Mode::Math { "\\grave" } else { "\\`" }),
"\u{308}" => Some(if mode == Mode::Math { "\\ddot" } else { "\\\"" }),
"\u{303}" => Some(if mode == Mode::Math { "\\tilde" } else { "\\~" }),
"\u{304}" => Some(if mode == Mode::Math { "\\bar" } else { "\\=" }),
"\u{306}" => Some(if mode == Mode::Math { "\\breve" } else { "\\u" }),
"\u{30C}" => Some(if mode == Mode::Math { "\\check" } else { "\\v" }),
"\u{302}" => Some(if mode == Mode::Math { "\\hat" } else { "\\^" }),
"\u{307}" => Some(if mode == Mode::Math { "\\dot" } else { "\\." }),
"\u{30A}" => Some(if mode == Mode::Math { "\\mathring" } else { "\\r" }),
"\u{30B}" => Some("\\H"),
"\u{327}" => Some("\\c"),
_ => None,
};
result.map(|s| s.to_string())
}