pub mod accents;
pub mod alphabets;
pub mod arrows;
pub mod atoms;
pub mod delims;
pub mod funcs;
pub mod grids;
pub mod radicals;
pub mod scripts;
pub use accents::*;
pub use alphabets::*;
pub use arrows::*;
pub use atoms::*;
pub use delims::*;
pub use funcs::*;
pub use grids::*;
pub use radicals::*;
pub use scripts::*;
pub fn symbol_by_name(name: &str) -> Option<char> {
if let Some(c) = named_char(name).or_else(|| alphabets::alphabet_char(name)) {
return Some(c);
}
let base = name.strip_prefix('!').or_else(|| name.strip_suffix('!'))?;
let base_char = named_char(base).or_else(|| {
let mut cs = base.chars();
match (cs.next(), cs.next()) {
(Some(c), None) => Some(c),
_ => None,
}
});
atoms::negated(base_char?)
}
pub fn is_bigop(c: char) -> bool {
atom_of(c).is_some_and(|a| a.kind == AtomKind::BigOp)
}
pub fn latex_name(c: char) -> Option<&'static str> {
atom_of(c).map(|a| a.latex)
}
pub fn latex_of(c: char) -> Option<String> {
latex_name(c)
.map(|n| format!("\\{} ", n))
.or_else(|| alphabets::styled_latex(c))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn latex_spelling_covers_the_styled_families() {
for (style, fam) in alphabets::ALPHABETS.entries() {
for l in ('A'..='Z').chain('a'..='z') {
let c = alphabets::alphabet_char(&format!("{}{}", style, l)).unwrap();
let want = format!("\\{}{{{}}}", fam.latex, l);
let got = latex_of(c).unwrap_or_default();
assert!(
got == want || latex_name(c).is_some(),
"{}{}: {:?}",
style,
l,
got
);
}
}
let gap: Vec<char> = (1..=0x2FFFFu32)
.filter_map(char::from_u32)
.filter(|&c| is_atom(c) && !c.is_ascii() && latex_of(c).is_none())
.collect();
assert!(gap.is_empty(), "atoms with no LaTeX spelling: {:?}", gap);
}
}