asciimath_unicode/
lib.rs

1//! A module for converting asciimath to unicode
2//!
3//! To convert asciimath quickly, you can use the [`write_unicode`] or [`convert_unicode`] methods.
4//! If you want more control, see the options exposed through [`InlineRenderer`] which can be
5//! [rendered][InlineRenderer::render] into [`RenderedUnicode`].
6//!
7//! # Usage
8//!
9//! ## Binary
10//!
11//! This crate provides a simple cli for converting asciimath to unicode:
12//!
13//! ```bash
14//! cargo install asciimath-unicode --features binary
15//! ```
16//!
17//! ```bash
18//! asciimath-unicode -h
19//! ```
20//!
21//! ## Library
22//!
23//! ```bash
24//! cargo add asciimath-parser
25//! ```
26//!
27//! ```
28//! let res = asciimath_unicode::convert_unicode("1/2");
29//! assert_eq!(res, "½");
30//! ```
31//!
32//! ```
33//! use asciimath_unicode::InlineRenderer;
34//! let renderer = InlineRenderer {
35//!     vulgar_fracs: false,
36//!     ..Default::default()
37//! };
38//! let res: String = renderer.render("1/2").collect();
39//! assert_eq!(res, "¹⁄₂");
40//! ```
41#![forbid(unsafe_code)]
42#![warn(clippy::pedantic, missing_docs)]
43
44mod iter;
45mod render_chars;
46mod tokens;
47
48use asciimath_parser::tree::{
49    Expression, Frac, Func, Group, Intermediate, Matrix, Script, ScriptFunc, Simple, SimpleBinary,
50    SimpleFunc, SimpleScript, SimpleUnary,
51};
52use asciimath_parser::Tokenizer;
53pub use emojis::SkinTone;
54use iter::{Interleave, Modified};
55use render_chars::{enum_iter, struct_iter, RenderChars};
56use std::array;
57use std::fmt;
58use std::io;
59use std::io::Write;
60use std::iter::{Chain, Flatten, FusedIterator, Map};
61use std::str::Chars;
62use std::vec;
63use tokens::{
64    bold_map, cal_map, double_map, frak_map, italic_map, left_bracket_str, mono_map,
65    right_bracket_str, sans_map, subscript_char, superscript_char, symbol_str, TOKEN_MAP,
66};
67
68type CharIter = array::IntoIter<char, 1>;
69
70type GenericBinaryIter<'a> = Chain<
71    Chain<Chain<Chain<Chars<'a>, CharIter>, Box<SimpleIter<'a>>>, CharIter>,
72    Box<SimpleIter<'a>>,
73>;
74
75type CharMap<I> = Map<I, fn(char) -> char>;
76
77type Delim<'a, I> = Chain<Chain<Chars<'a>, I>, Chars<'a>>;
78
79type SimpleFuncIter<'a> = Chain<Chain<Chars<'a>, CharIter>, Box<SimpleIter<'a>>>;
80
81type GroupIter<'a> = Delim<'a, Box<ExpressionIter<'a>>>;
82
83type SimpleScriptIter<'a> = Chain<SimpleIter<'a>, ScriptIter<'a>>;
84
85type FuncIter<'a> =
86    Chain<Chain<Chain<Chars<'a>, ScriptIter<'a>>, CharIter>, Box<ScriptFuncIter<'a>>>;
87
88type ExpressionIter<'a> = Flatten<vec::IntoIter<IntermediateIter<'a>>>;
89
90type MatIter<'a> = Delim<'a, Box<Interleave<Delim<'a, Interleave<ExpressionIter<'a>>>>>>;
91
92struct_iter! { SimpMappedIter : CharMap<SimpleIter<'a>> }
93
94struct_iter! { FuncMappedIter : CharMap<ScriptFuncIter<'a>> }
95
96struct_iter! { ExprMappedIter : CharMap<ExpressionIter<'a>> }
97
98enum_iter! { SimpleUnaryIter :
99    Simple => Chain<CharIter, Box<SimpleIter<'a>>>,
100    Font => Box<CharMap<SimpleIter<'a>>>,
101    StrippedFont => Box<CharMap<ExpressionIter<'a>>>,
102    Wrapped => Delim<'a, Box<SimpleIter<'a>>>,
103    StrippedWrapped => Delim<'a, Box<ExpressionIter<'a>>>,
104    Single => Chain<Box<SimpleIter<'a>>, CharIter>,
105    StrippedSingle => Chain<Box<ExpressionIter<'a>>, CharIter>,
106    Moded => Box<Modified<SimpleIter<'a>>>,
107    StrippedModed => Box<Modified<ExpressionIter<'a>>>,
108    Generic => Chain<Chain<Chars<'a>, CharIter>, Box<SimpleIter<'a>>>,
109}
110
111enum_iter! { SimpleFracIter :
112    Vulgar => CharIter,
113    VulgOne => Chain<CharIter, SimpMappedIter<'a>>,
114    StrippedVulgOne => Chain<CharIter, Box<ExprMappedIter<'a>>>,
115    StrippedScript => Box<Chain<Chain<ExprMappedIter<'a>, CharIter>, ExprMappedIter<'a>>>,
116    DenomStrippedScript => Chain<Chain<SimpMappedIter<'a>, CharIter>, Box<ExprMappedIter<'a>>>,
117    NumerStrippedScript => Chain<Chain<Box<ExprMappedIter<'a>>, CharIter>, SimpMappedIter<'a>>,
118    Script => Chain<Chain<SimpMappedIter<'a>, CharIter>, SimpMappedIter<'a>>,
119    Simple => Chain<Chain<SimpleIter<'a>, CharIter>, SimpleIter<'a>>,
120}
121
122enum_iter! { SimpleBinaryIter :
123    Simple => Chain<CharIter, Box<SimpleIter<'a>>>,
124    ExprComb => Chain<Box<ExpressionIter<'a>>, CharIter>,
125    Comb => Chain<Box<SimpleIter<'a>>, CharIter>,
126    Char => CharIter,
127    Frac => Box<SimpleFracIter<'a>>,
128    Generic => GenericBinaryIter<'a>,
129}
130
131enum_iter! { SimpleIter :
132    Chars => Chars<'a>,
133    Func => SimpleFuncIter<'a>,
134    Unary => SimpleUnaryIter<'a>,
135    Binary => SimpleBinaryIter<'a>,
136    Group => GroupIter<'a>,
137    Matrix => MatIter<'a>,
138}
139
140enum_iter! { ScriptIter :
141    Empty => Chars<'static>,
142    Untouched => Chain<CharIter, SimpleIter<'a>>,
143    Mapped => CharMap<SimpleIter<'a>>,
144    SubsupUntouched => Chain<Chain<Chain<CharIter, SimpleIter<'a>>, CharIter>, SimpleIter<'a>>,
145    SubsupMapped => Chain<SimpMappedIter<'a>, SimpMappedIter<'a>>,
146}
147
148enum_iter! { ScriptFuncIter :
149    Simple => SimpleScriptIter<'a>,
150    Func => FuncIter<'a>,
151}
152
153enum_iter! { FracIter :
154    Simple => SimpleFracIter<'a>,
155    NumerStrippedScript => Chain<Chain<Box<ExprMappedIter<'a>>, CharIter>, FuncMappedIter<'a>>,
156    DenomStrippedScript => Chain<Chain<FuncMappedIter<'a>, CharIter>, Box<ExprMappedIter<'a>>>,
157    Script => Chain<Chain<FuncMappedIter<'a>, CharIter>, FuncMappedIter<'a>>,
158    VulgOne => Chain<CharIter, FuncMappedIter<'a>>,
159    One => Chain<Chars<'static>, ScriptFuncIter<'a>>,
160    Func => Chain<Chain<ScriptFuncIter<'a>, CharIter>, ScriptFuncIter<'a>>,
161}
162
163enum_iter! { IntermediateIter :
164    ScriptFunc => ScriptFuncIter<'a>,
165    Frac => FracIter<'a>,
166}
167
168macro_rules! num {
169    ($num:pat) => {
170        Simple::Number($num)
171    };
172}
173
174macro_rules! iden {
175    ($idn:pat) => {
176        Simple::Ident($idn)
177    };
178}
179
180macro_rules! symb {
181    ($sym:pat) => {
182        Simple::Symbol($sym)
183    };
184}
185
186macro_rules! script_func {
187    ($simp:pat) => {
188        ScriptFunc::Simple(SimpleScript {
189            simple: $simp,
190            script: Script::None,
191        })
192    };
193}
194
195macro_rules! sgroup {
196    ($expr:pat) => {
197        Simple::Group(Group { expr: $expr, .. })
198    };
199}
200
201macro_rules! xnum {
202    ($expr:expr, $num:pat) => {
203        matches!(
204            **$expr,
205            [Intermediate::ScriptFunc(script_func!(num!($num)))]
206        )
207    };
208}
209
210macro_rules! xiden {
211    ($expr:expr, $num:pat) => {
212        matches!(
213            **$expr,
214            [Intermediate::ScriptFunc(script_func!(iden!($num)))]
215        )
216    };
217}
218
219#[inline]
220fn vulg<'a>(vulgar: char) -> RenderChars<SimpleFracIter<'a>> {
221    RenderChars::from(vulgar).map(SimpleFracIter::Vulgar)
222}
223
224#[inline]
225fn gsfrac<'a>(
226    num: RenderChars<SimpleIter<'a>>,
227    den: RenderChars<SimpleIter<'a>>,
228) -> RenderChars<SimpleFracIter<'a>> {
229    num.chain(RenderChars::from('/'))
230        .chain(den)
231        .map(SimpleFracIter::Simple)
232}
233
234#[inline]
235fn gfrac<'a>(
236    num: RenderChars<ScriptFuncIter<'a>>,
237    den: RenderChars<ScriptFuncIter<'a>>,
238) -> RenderChars<FracIter<'a>> {
239    num.chain(RenderChars::from('/'))
240        .chain(den)
241        .map(FracIter::Func)
242}
243
244/// An inline unicode renderer for asciimath
245#[derive(Debug, Clone, PartialEq, Eq)]
246pub struct InlineRenderer {
247    /// If true, this will strip unnecessary parenthesis in some contexts
248    pub strip_brackets: bool,
249    /// If true, this will try to render fractions as vulgar fractions
250    pub vulgar_fracs: bool,
251    /// If true, this will try to render fractions using super- and sub-scripts
252    pub script_fracs: bool,
253    /// Default skin tone for emojis
254    pub skin_tone: SkinTone,
255}
256
257impl Default for InlineRenderer {
258    fn default() -> Self {
259        InlineRenderer {
260            strip_brackets: true,
261            vulgar_fracs: true,
262            script_fracs: true,
263            skin_tone: SkinTone::Default,
264        }
265    }
266}
267
268impl InlineRenderer {
269    fn render_simplefunc<'a>(&self, simple: &SimpleFunc<'a>) -> RenderChars<SimpleFuncIter<'a>> {
270        RenderChars::from(simple.func)
271            .chain(RenderChars::from(' '))
272            .chain(self.render_simple(simple.arg()).map(Box::new))
273    }
274
275    #[inline]
276    fn render_root<'a>(
277        &self,
278        root_char: char,
279        arg: &Simple<'a>,
280    ) -> RenderChars<SimpleBinaryIter<'a>> {
281        RenderChars::from(root_char)
282            .chain(self.render_simple(arg).map(Box::new))
283            .map(SimpleBinaryIter::Simple)
284    }
285
286    #[inline]
287    fn cover<'a>(
288        &self,
289        op: &'a str,
290        first: &Simple<'a>,
291        arg: &Simple<'a>,
292        chr: char,
293    ) -> RenderChars<SimpleBinaryIter<'a>> {
294        match arg {
295            sgroup!(expr) if self.strip_brackets => {
296                let rendered = self.render_expression(expr);
297                if rendered.len == 1 {
298                    rendered
299                        .map(Box::new)
300                        .chain(RenderChars::from(chr))
301                        .map(SimpleBinaryIter::ExprComb)
302                } else {
303                    self.render_bgeneric(op, first, arg)
304                }
305            }
306            arg => {
307                let rendered = self.render_simple(arg);
308                if rendered.len == 1 {
309                    rendered
310                        .map(Box::new)
311                        .chain(RenderChars::from(chr))
312                        .map(SimpleBinaryIter::Comb)
313                } else {
314                    self.render_bgeneric(op, first, arg)
315                }
316            }
317        }
318    }
319
320    #[inline]
321    fn render_equals<'a>(
322        &self,
323        iter: impl Iterator<Item = char> + Clone,
324        op: &'a str,
325        first: &Simple<'a>,
326        second: &Simple<'a>,
327    ) -> RenderChars<SimpleBinaryIter<'a>> {
328        if iter.clone().eq("∘".chars()) {
329            RenderChars::from('\u{2257}').map(SimpleBinaryIter::Char)
330        } else if iter.clone().eq("⋆".chars()) {
331            RenderChars::from('\u{225b}').map(SimpleBinaryIter::Char)
332        } else if iter.clone().eq("△".chars()) {
333            RenderChars::from('\u{225c}').map(SimpleBinaryIter::Char)
334        } else if iter.clone().eq("def".chars()) {
335            RenderChars::from('\u{225d}').map(SimpleBinaryIter::Char)
336        } else if iter.clone().eq("m".chars()) {
337            RenderChars::from('\u{225e}').map(SimpleBinaryIter::Char)
338        } else if iter.eq("?".chars()) {
339            RenderChars::from('\u{225f}').map(SimpleBinaryIter::Char)
340        } else {
341            self.render_bgeneric(op, first, second)
342        }
343    }
344
345    #[inline]
346    fn render_bgeneric<'a>(
347        &self,
348        op: &'a str,
349        first: &Simple<'a>,
350        second: &Simple<'a>,
351    ) -> RenderChars<SimpleBinaryIter<'a>> {
352        RenderChars::from(op)
353            .chain(RenderChars::from(' '))
354            .chain(self.render_simple(first).map(Box::new))
355            .chain(RenderChars::from(' '))
356            .chain(self.render_simple(second).map(Box::new))
357            .map(SimpleBinaryIter::Generic)
358    }
359
360    fn render_simplebinary<'a>(
361        &self,
362        simple: &SimpleBinary<'a>,
363    ) -> RenderChars<SimpleBinaryIter<'a>> {
364        let sb = self.strip_brackets;
365        match (simple.op, simple.first(), simple.second()) {
366            // roots
367            ("root", num!("2"), arg) => self.render_root('√', arg),
368            ("root", num!("3"), arg) => self.render_root('∛', arg),
369            ("root", num!("4"), arg) => self.render_root('∜', arg),
370            ("root", sgroup!(expr), arg) if xnum!(expr, "2") => self.render_root('√', arg),
371            ("root", sgroup!(expr), arg) if xnum!(expr, "3") => self.render_root('∛', arg),
372            ("root", sgroup!(expr), arg) if xnum!(expr, "4") => self.render_root('∜', arg),
373            // frac
374            ("frac", numer, denom) => self
375                .render_simplefrac(numer, denom)
376                .map(|iter| SimpleBinaryIter::Frac(Box::new(iter))),
377            // stackrel / overset combining
378            (o @ ("stackrel" | "overset"), f @ iden!("a"), a) => self.cover(o, f, a, '\u{0363}'),
379            (o @ ("stackrel" | "overset"), f @ iden!("e"), a) => self.cover(o, f, a, '\u{0364}'),
380            (o @ ("stackrel" | "overset"), f @ iden!("i"), a) => self.cover(o, f, a, '\u{0365}'),
381            (o @ ("stackrel" | "overset"), f @ iden!("o"), a) => self.cover(o, f, a, '\u{0366}'),
382            (o @ ("stackrel" | "overset"), f @ iden!("u"), a) => self.cover(o, f, a, '\u{0367}'),
383            (o @ ("stackrel" | "overset"), f @ iden!("c"), a) => self.cover(o, f, a, '\u{0368}'),
384            (o @ ("stackrel" | "overset"), f @ iden!("d"), a) => self.cover(o, f, a, '\u{0369}'),
385            (o @ ("stackrel" | "overset"), f @ iden!("h"), a) => self.cover(o, f, a, '\u{036a}'),
386            (o @ ("stackrel" | "overset"), f @ iden!("m"), a) => self.cover(o, f, a, '\u{036b}'),
387            (o @ ("stackrel" | "overset"), f @ iden!("r"), a) => self.cover(o, f, a, '\u{036c}'),
388            (o @ ("stackrel" | "overset"), f @ iden!("t"), a) => self.cover(o, f, a, '\u{036d}'),
389            (o @ ("stackrel" | "overset"), f @ iden!("v"), a) => self.cover(o, f, a, '\u{036e}'),
390            (o @ ("stackrel" | "overset"), f @ iden!("x"), a) => self.cover(o, f, a, '\u{036f}'),
391            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "a") => {
392                self.cover(simple.op, simple.first(), arg, '\u{0363}')
393            }
394            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "e") => {
395                self.cover(simple.op, simple.first(), arg, '\u{0364}')
396            }
397            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "i") => {
398                self.cover(simple.op, simple.first(), arg, '\u{0365}')
399            }
400            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "o") => {
401                self.cover(simple.op, simple.first(), arg, '\u{0366}')
402            }
403            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "u") => {
404                self.cover(simple.op, simple.first(), arg, '\u{0367}')
405            }
406            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "c") => {
407                self.cover(simple.op, simple.first(), arg, '\u{0368}')
408            }
409            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "d") => {
410                self.cover(simple.op, simple.first(), arg, '\u{0369}')
411            }
412            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "h") => {
413                self.cover(simple.op, simple.first(), arg, '\u{036a}')
414            }
415            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "m") => {
416                self.cover(simple.op, simple.first(), arg, '\u{036b}')
417            }
418            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "r") => {
419                self.cover(simple.op, simple.first(), arg, '\u{036c}')
420            }
421            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "t") => {
422                self.cover(simple.op, simple.first(), arg, '\u{036d}')
423            }
424            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "v") => {
425                self.cover(simple.op, simple.first(), arg, '\u{036e}')
426            }
427            ("stackrel" | "overset", sgroup!(exp), arg) if sb && xiden!(exp, "x") => {
428                self.cover(simple.op, simple.first(), arg, '\u{036f}')
429            }
430            // stackrel / overset equals
431            ("stackrel" | "overset", arg, symb!("=")) => match arg {
432                sgroup!(expr) if self.strip_brackets => {
433                    let rendered = self.render_expression(expr);
434                    self.render_equals(rendered.iter, simple.op, arg, simple.second())
435                }
436                arg => {
437                    let rendered = self.render_simple(arg);
438                    self.render_equals(rendered.iter, simple.op, arg, simple.second())
439                }
440            },
441            // generic
442            (op, first, second) => self.render_bgeneric(op, first, second),
443        }
444    }
445
446    #[inline]
447    fn render_font<'a>(
448        &self,
449        font: fn(char) -> char,
450        arg: &Simple<'a>,
451    ) -> RenderChars<SimpleUnaryIter<'a>> {
452        match arg {
453            sgroup!(expr) if self.strip_brackets => self
454                .render_expression(expr)
455                .map(|iter| SimpleUnaryIter::StrippedFont(Box::new(iter.map(font)))),
456            arg => self
457                .render_simple(arg)
458                .map(|iter| SimpleUnaryIter::Font(Box::new(iter.map(font)))),
459        }
460    }
461
462    #[inline]
463    fn render_sfunc<'a>(
464        &self,
465        open: &'a str,
466        arg: &Simple<'a>,
467        close: &'a str,
468    ) -> RenderChars<SimpleUnaryIter<'a>> {
469        match arg {
470            sgroup!(expr) if self.strip_brackets => RenderChars::from(open)
471                .chain(self.render_expression(expr).map(Box::new))
472                .chain(RenderChars::from(close))
473                .map(SimpleUnaryIter::StrippedWrapped),
474            arg => RenderChars::from(open)
475                .chain(self.render_simple(arg).map(Box::new))
476                .chain(RenderChars::from(close))
477                .map(SimpleUnaryIter::Wrapped),
478        }
479    }
480
481    #[inline]
482    fn render_mod<'a>(&self, chr: char, arg: &Simple<'a>) -> RenderChars<SimpleUnaryIter<'a>> {
483        match arg {
484            sgroup!(expr) if self.strip_brackets => self
485                .render_expression(expr)
486                .map(|iter| SimpleUnaryIter::StrippedModed(Box::new(Modified::new(iter, chr)))),
487            arg => self
488                .render_simple(arg)
489                .map(|iter| SimpleUnaryIter::Moded(Box::new(Modified::new(iter, chr)))),
490        }
491    }
492
493    #[inline]
494    fn render_char_mod<'a>(
495        &self,
496        op: &'a str,
497        chr: char,
498        arg: &Simple<'a>,
499    ) -> RenderChars<SimpleUnaryIter<'a>> {
500        match arg {
501            sgroup!(expr) if self.strip_brackets => {
502                let rendered = self.render_expression(expr);
503                if rendered.len == 1 {
504                    rendered
505                        .map(Box::new)
506                        .chain(RenderChars::from(chr))
507                        .map(SimpleUnaryIter::StrippedSingle)
508                } else {
509                    self.render_ugeneric(op, arg)
510                }
511            }
512            arg => {
513                let rendered = self.render_simple(arg);
514                if rendered.len == 1 {
515                    rendered
516                        .map(Box::new)
517                        .chain(RenderChars::from(chr))
518                        .map(SimpleUnaryIter::Single)
519                } else {
520                    self.render_ugeneric(op, arg)
521                }
522            }
523        }
524    }
525
526    #[inline]
527    fn render_ugeneric<'a>(
528        &self,
529        op: &'a str,
530        arg: &Simple<'a>,
531    ) -> RenderChars<SimpleUnaryIter<'a>> {
532        RenderChars::from(op)
533            .chain(RenderChars::from(' '))
534            .chain(self.render_simple(arg).map(Box::new))
535            .map(SimpleUnaryIter::Generic)
536    }
537
538    #[allow(clippy::too_many_lines)]
539    fn render_simpleunary<'a>(&self, simple: &SimpleUnary<'a>) -> RenderChars<SimpleUnaryIter<'a>> {
540        match (simple.op, simple.arg()) {
541            // sqrt
542            ("sqrt", arg) => RenderChars::from('√')
543                .chain(self.render_simple(arg).map(Box::new))
544                .map(SimpleUnaryIter::Simple),
545            // fonts
546            ("bb" | "mathbf", arg) => self.render_font(bold_map, arg),
547            ("bbb" | "mathbb", arg) => self.render_font(double_map, arg),
548            ("cc" | "mathcal", arg) => self.render_font(cal_map, arg),
549            ("tt" | "mathtt", arg) => self.render_font(mono_map, arg),
550            ("fr" | "mathfrak", arg) => self.render_font(frak_map, arg),
551            ("sf" | "mathsf", arg) => self.render_font(sans_map, arg),
552            ("it" | "mathit", arg) => self.render_font(italic_map, arg),
553            // functions
554            ("abs" | "Abs", arg) => self.render_sfunc("|", arg, "|"),
555            ("ceil", arg) => self.render_sfunc("⌈", arg, "⌉"),
556            ("floor", arg) => self.render_sfunc("⌊", arg, "⌋"),
557            ("norm", arg) => self.render_sfunc("||", arg, "||"),
558            ("text", arg) => self.render_sfunc("", arg, ""),
559            // modifiers
560            ("overline", arg) => self.render_mod('\u{0305}', arg),
561            ("underline" | "ul", arg) => self.render_mod('\u{0332}', arg),
562            // single character modifiers
563            (o @ "hat", arg) => self.render_char_mod(o, '\u{0302}', arg),
564            (o @ "tilde", arg) => self.render_char_mod(o, '\u{0303}', arg),
565            (o @ "bar", arg) => self.render_char_mod(o, '\u{0304}', arg),
566            (o @ "dot", arg) => self.render_char_mod(o, '\u{0307}', arg),
567            (o @ "ddot", arg) => self.render_char_mod(o, '\u{0308}', arg),
568            (o @ ("overarc" | "overparen"), arg) => self.render_char_mod(o, '\u{0311}', arg),
569            // generic
570            (op, arg) => self.render_ugeneric(op, arg),
571        }
572    }
573
574    fn render_matrix<'a>(&self, matrix: &Matrix<'a>) -> RenderChars<MatIter<'a>> {
575        let num_cols = matrix.num_cols();
576        let num_rows = matrix.num_rows();
577        let left_rend = RenderChars::from(left_bracket_str(matrix.left_bracket));
578        let right_rend = RenderChars::from(right_bracket_str(matrix.right_bracket));
579
580        let mut rendered = Vec::with_capacity(matrix.num_rows());
581        let mut len =
582            (num_rows + 1) * (left_rend.len + right_rend.len) + (num_rows - 1) * (num_cols - 1);
583        for row in matrix.rows() {
584            let mut rends = Vec::with_capacity(row.len());
585            for expr in row {
586                let rend = self.render_expression(expr);
587                len += rend.len;
588                rends.push(rend.iter);
589            }
590            rendered.push(
591                left_rend
592                    .iter
593                    .clone()
594                    .chain(Interleave::new(rends, ','))
595                    .chain(right_rend.iter.clone()),
596            );
597        }
598        RenderChars {
599            iter: left_rend
600                .iter
601                .chain(Box::new(Interleave::new(rendered, ',')))
602                .chain(right_rend.iter),
603            len,
604            sub: false,
605            sup: false,
606        }
607    }
608
609    fn render_group<'a>(&self, group: &Group<'a>) -> RenderChars<GroupIter<'a>> {
610        RenderChars::from(left_bracket_str(group.left_bracket))
611            .chain(self.render_expression(&group.expr).map(Box::new))
612            .chain(RenderChars::from(right_bracket_str(group.right_bracket)))
613    }
614
615    fn render_simple<'a>(&self, simple: &Simple<'a>) -> RenderChars<SimpleIter<'a>> {
616        match simple {
617            Simple::Missing => RenderChars::from("").map(SimpleIter::Chars),
618            &Simple::Number(num) => RenderChars::from(num).map(SimpleIter::Chars),
619            &Simple::Text(text) => RenderChars::from(text).map(SimpleIter::Chars),
620            &Simple::Ident(ident) => RenderChars::from(ident).map(SimpleIter::Chars),
621            &Simple::Symbol(symbol) => {
622                RenderChars::from(symbol_str(symbol, self.skin_tone)).map(SimpleIter::Chars)
623            }
624            Simple::Func(func) => self.render_simplefunc(func).map(SimpleIter::Func),
625            Simple::Unary(unary) => self.render_simpleunary(unary).map(SimpleIter::Unary),
626            Simple::Binary(binary) => self.render_simplebinary(binary).map(SimpleIter::Binary),
627            Simple::Group(group) => self.render_group(group).map(SimpleIter::Group),
628            Simple::Matrix(matrix) => self.render_matrix(matrix).map(SimpleIter::Matrix),
629        }
630    }
631
632    fn render_script<'a>(&self, script: &Script<'a>) -> RenderChars<ScriptIter<'a>> {
633        match script {
634            Script::None => RenderChars::from("").map(ScriptIter::Empty),
635            Script::Sub(sub) => {
636                let rendered = self.render_simple(sub);
637                if rendered.sub {
638                    rendered
639                        .map(|iter| ScriptIter::Mapped(iter.map(|c| subscript_char(c).unwrap())))
640                } else {
641                    RenderChars::from('_')
642                        .chain(rendered)
643                        .map(ScriptIter::Untouched)
644                }
645            }
646            Script::Super(sup) => {
647                let rendered = self.render_simple(sup);
648                if rendered.sup {
649                    rendered
650                        .map(|iter| ScriptIter::Mapped(iter.map(|c| superscript_char(c).unwrap())))
651                } else {
652                    RenderChars::from('^')
653                        .chain(rendered)
654                        .map(ScriptIter::Untouched)
655                }
656            }
657            Script::Subsuper(sub, supersc) => {
658                let rend_sub = self.render_simple(sub);
659                let rend_super = self.render_simple(supersc);
660                if rend_sub.sub && rend_super.sup {
661                    rend_sub
662                        .map(|iter| SimpMappedIter(iter.map(|c| subscript_char(c).unwrap())))
663                        .chain(
664                            rend_super.map(|iter| {
665                                SimpMappedIter(iter.map(|c| superscript_char(c).unwrap()))
666                            }),
667                        )
668                        .map(ScriptIter::SubsupMapped)
669                } else {
670                    RenderChars::from('_')
671                        .chain(rend_sub)
672                        .chain(RenderChars::from('^'))
673                        .chain(rend_super)
674                        .map(ScriptIter::SubsupUntouched)
675                }
676            }
677        }
678    }
679
680    fn render_simplescript<'a>(
681        &self,
682        simple: &SimpleScript<'a>,
683    ) -> RenderChars<SimpleScriptIter<'a>> {
684        self.render_simple(&simple.simple)
685            .chain(self.render_script(&simple.script))
686    }
687
688    fn render_func<'a>(&self, func: &Func<'a>) -> RenderChars<FuncIter<'a>> {
689        RenderChars::from(func.func)
690            .chain(self.render_script(&func.script))
691            .chain(RenderChars::from(' '))
692            .chain(self.render_scriptfunc(func.arg()).map(Box::new))
693    }
694
695    fn render_scriptfunc<'a>(&self, func: &ScriptFunc<'a>) -> RenderChars<ScriptFuncIter<'a>> {
696        match func {
697            ScriptFunc::Simple(simple) => {
698                self.render_simplescript(simple).map(ScriptFuncIter::Simple)
699            }
700            ScriptFunc::Func(func) => self.render_func(func).map(ScriptFuncIter::Func),
701        }
702    }
703
704    #[inline]
705    fn render_sone<'a>(
706        &self,
707        num: &Simple<'a>,
708        den: &Simple<'a>,
709    ) -> RenderChars<SimpleFracIter<'a>> {
710        match den {
711            sgroup!(expr) if self.strip_brackets => {
712                let rend_den = self.render_expression(expr);
713                if rend_den.sub {
714                    RenderChars::from('⅟')
715                        .chain(rend_den.map(|iter| {
716                            Box::new(ExprMappedIter(iter.map(|c| subscript_char(c).unwrap())))
717                        }))
718                        .map(SimpleFracIter::StrippedVulgOne)
719                } else {
720                    gsfrac(self.render_simple(num), self.render_simple(den))
721                }
722            }
723            den => {
724                let rend_den = self.render_simple(den);
725                if rend_den.sub {
726                    RenderChars::from('⅟')
727                        .chain(
728                            rend_den.map(|iter| {
729                                SimpMappedIter(iter.map(|c| subscript_char(c).unwrap()))
730                            }),
731                        )
732                        .map(SimpleFracIter::VulgOne)
733                } else {
734                    gsfrac(self.render_simple(num), rend_den)
735                }
736            }
737        }
738    }
739
740    #[allow(clippy::too_many_lines)]
741    fn render_simplefrac<'a>(
742        &self,
743        numer: &Simple<'a>,
744        denom: &Simple<'a>,
745    ) -> RenderChars<SimpleFracIter<'a>> {
746        let vsf = self.vulgar_fracs && self.script_fracs;
747        let vs = self.vulgar_fracs && self.strip_brackets;
748        match (numer, denom) {
749            // fracs
750            (num!("0"), num!("3")) if self.vulgar_fracs => vulg('↉'),
751            (num!("1"), num!("10")) if self.vulgar_fracs => vulg('⅒'),
752            (num!("1"), num!("9")) if self.vulgar_fracs => vulg('⅑'),
753            (num!("1"), num!("8")) if self.vulgar_fracs => vulg('⅛'),
754            (num!("1"), num!("7")) if self.vulgar_fracs => vulg('⅐'),
755            (num!("1"), num!("6")) if self.vulgar_fracs => vulg('⅙'),
756            (num!("1"), num!("5")) if self.vulgar_fracs => vulg('⅕'),
757            (num!("1"), num!("4")) if self.vulgar_fracs => vulg('¼'),
758            (num!("1"), num!("3")) if self.vulgar_fracs => vulg('⅓'),
759            (num!("1"), num!("2")) if self.vulgar_fracs => vulg('½'),
760            (num!("2"), num!("5")) if self.vulgar_fracs => vulg('⅖'),
761            (num!("2"), num!("3")) if self.vulgar_fracs => vulg('⅔'),
762            (num!("3"), num!("8")) if self.vulgar_fracs => vulg('⅜'),
763            (num!("3"), num!("5")) if self.vulgar_fracs => vulg('⅗'),
764            (num!("3"), num!("4")) if self.vulgar_fracs => vulg('¾'),
765            (num!("4"), num!("5")) if self.vulgar_fracs => vulg('⅘'),
766            (num!("5"), num!("8")) if self.vulgar_fracs => vulg('⅝'),
767            (num!("5"), num!("6")) if self.vulgar_fracs => vulg('⅚'),
768            (num!("7"), num!("8")) if self.vulgar_fracs => vulg('⅞'),
769            (sgroup!(num), num!("3")) if xnum!(num, "0") && vs => vulg('↉'),
770            (sgroup!(num), num!("10")) if xnum!(num, "1") && vs => vulg('⅒'),
771            (sgroup!(num), num!("9")) if xnum!(num, "1") && vs => vulg('⅑'),
772            (sgroup!(num), num!("8")) if xnum!(num, "1") && vs => vulg('⅛'),
773            (sgroup!(num), num!("7")) if xnum!(num, "1") && vs => vulg('⅐'),
774            (sgroup!(num), num!("6")) if xnum!(num, "1") && vs => vulg('⅙'),
775            (sgroup!(num), num!("5")) if xnum!(num, "1") && vs => vulg('⅕'),
776            (sgroup!(num), num!("4")) if xnum!(num, "1") && vs => vulg('¼'),
777            (sgroup!(num), num!("3")) if xnum!(num, "1") && vs => vulg('⅓'),
778            (sgroup!(num), num!("2")) if xnum!(num, "1") && vs => vulg('½'),
779            (sgroup!(num), num!("5")) if xnum!(num, "2") && vs => vulg('⅖'),
780            (sgroup!(num), num!("3")) if xnum!(num, "2") && vs => vulg('⅔'),
781            (sgroup!(num), num!("8")) if xnum!(num, "3") && vs => vulg('⅜'),
782            (sgroup!(num), num!("5")) if xnum!(num, "3") && vs => vulg('⅗'),
783            (sgroup!(num), num!("4")) if xnum!(num, "3") && vs => vulg('¾'),
784            (sgroup!(num), num!("5")) if xnum!(num, "4") && vs => vulg('⅘'),
785            (sgroup!(num), num!("8")) if xnum!(num, "5") && vs => vulg('⅝'),
786            (sgroup!(num), num!("6")) if xnum!(num, "5") && vs => vulg('⅚'),
787            (sgroup!(num), num!("8")) if xnum!(num, "7") && vs => vulg('⅞'),
788            (num!("0"), sgroup!(den)) if xnum!(den, "3") && vs => vulg('↉'),
789            (num!("1"), sgroup!(den)) if xnum!(den, "10") && vs => vulg('⅒'),
790            (num!("1"), sgroup!(den)) if xnum!(den, "9") && vs => vulg('⅑'),
791            (num!("1"), sgroup!(den)) if xnum!(den, "8") && vs => vulg('⅛'),
792            (num!("1"), sgroup!(den)) if xnum!(den, "7") && vs => vulg('⅐'),
793            (num!("1"), sgroup!(den)) if xnum!(den, "6") && vs => vulg('⅙'),
794            (num!("1"), sgroup!(den)) if xnum!(den, "5") && vs => vulg('⅕'),
795            (num!("1"), sgroup!(den)) if xnum!(den, "4") && vs => vulg('¼'),
796            (num!("1"), sgroup!(den)) if xnum!(den, "3") && vs => vulg('⅓'),
797            (num!("1"), sgroup!(den)) if xnum!(den, "2") && vs => vulg('½'),
798            (num!("2"), sgroup!(den)) if xnum!(den, "5") && vs => vulg('⅖'),
799            (num!("2"), sgroup!(den)) if xnum!(den, "3") && vs => vulg('⅔'),
800            (num!("3"), sgroup!(den)) if xnum!(den, "8") && vs => vulg('⅜'),
801            (num!("3"), sgroup!(den)) if xnum!(den, "5") && vs => vulg('⅗'),
802            (num!("3"), sgroup!(den)) if xnum!(den, "4") && vs => vulg('¾'),
803            (num!("4"), sgroup!(den)) if xnum!(den, "5") && vs => vulg('⅘'),
804            (num!("5"), sgroup!(den)) if xnum!(den, "8") && vs => vulg('⅝'),
805            (num!("5"), sgroup!(den)) if xnum!(den, "6") && vs => vulg('⅚'),
806            (num!("7"), sgroup!(den)) if xnum!(den, "8") && vs => vulg('⅞'),
807            (sgroup!(num), sgroup!(den)) if xnum!(num, "0") && xnum!(den, "3") && vs => vulg('↉'),
808            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "10") && vs => vulg('⅒'),
809            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "9") && vs => vulg('⅑'),
810            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "8") && vs => vulg('⅛'),
811            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "7") && vs => vulg('⅐'),
812            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "6") && vs => vulg('⅙'),
813            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "5") && vs => vulg('⅕'),
814            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "4") && vs => vulg('¼'),
815            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "3") && vs => vulg('⅓'),
816            (sgroup!(num), sgroup!(den)) if xnum!(num, "1") && xnum!(den, "2") && vs => vulg('½'),
817            (sgroup!(num), sgroup!(den)) if xnum!(num, "2") && xnum!(den, "5") && vs => vulg('⅖'),
818            (sgroup!(num), sgroup!(den)) if xnum!(num, "2") && xnum!(den, "3") && vs => vulg('⅔'),
819            (sgroup!(num), sgroup!(den)) if xnum!(num, "3") && xnum!(den, "8") && vs => vulg('⅜'),
820            (sgroup!(num), sgroup!(den)) if xnum!(num, "3") && xnum!(den, "5") && vs => vulg('⅗'),
821            (sgroup!(num), sgroup!(den)) if xnum!(num, "3") && xnum!(den, "4") && vs => vulg('¾'),
822            (sgroup!(num), sgroup!(den)) if xnum!(num, "4") && xnum!(den, "5") && vs => vulg('⅘'),
823            (sgroup!(num), sgroup!(den)) if xnum!(num, "5") && xnum!(den, "8") && vs => vulg('⅝'),
824            (sgroup!(num), sgroup!(den)) if xnum!(num, "5") && xnum!(den, "6") && vs => vulg('⅚'),
825            (sgroup!(num), sgroup!(den)) if xnum!(num, "7") && xnum!(den, "8") && vs => vulg('⅞'),
826            // frac like
827            (iden!("a"), iden!("c")) if self.vulgar_fracs => vulg('℀'),
828            (iden!("a"), iden!("s")) if self.vulgar_fracs => vulg('℁'),
829            (iden!("A"), iden!("S")) if self.vulgar_fracs => vulg('⅍'),
830            (iden!("c"), iden!("o")) if self.vulgar_fracs => vulg('℅'),
831            (iden!("c"), iden!("u")) if self.vulgar_fracs => vulg('℆'),
832            (sgroup!(num), iden!("c")) if xiden!(num, "a") && vs => vulg('℀'),
833            (sgroup!(num), iden!("s")) if xiden!(num, "a") && vs => vulg('℁'),
834            (sgroup!(num), iden!("S")) if xiden!(num, "A") && vs => vulg('⅍'),
835            (sgroup!(num), iden!("o")) if xiden!(num, "c") && vs => vulg('℅'),
836            (sgroup!(num), iden!("u")) if xiden!(num, "c") && vs => vulg('℆'),
837            (iden!("a"), sgroup!(den)) if xiden!(den, "c") && vs => vulg('℀'),
838            (iden!("a"), sgroup!(den)) if xiden!(den, "s") && vs => vulg('℁'),
839            (iden!("A"), sgroup!(den)) if xiden!(den, "S") && vs => vulg('⅍'),
840            (iden!("c"), sgroup!(den)) if xiden!(den, "o") && vs => vulg('℅'),
841            (iden!("c"), sgroup!(den)) if xiden!(den, "u") && vs => vulg('℆'),
842            (sgroup!(num), sgroup!(den)) if xiden!(num, "a") && xiden!(den, "c") && vs => vulg('℀'),
843            (sgroup!(num), sgroup!(den)) if xiden!(num, "a") && xiden!(den, "s") && vs => vulg('℁'),
844            (sgroup!(num), sgroup!(den)) if xiden!(num, "A") && xiden!(den, "S") && vs => vulg('⅍'),
845            (sgroup!(num), sgroup!(den)) if xiden!(num, "c") && xiden!(den, "o") && vs => vulg('℅'),
846            (sgroup!(num), sgroup!(den)) if xiden!(num, "c") && xiden!(den, "u") && vs => vulg('℆'),
847            // one fracs
848            (num!("1"), den) if vsf => self.render_sone(numer, den),
849            (sgroup!(num), den) if vsf && self.strip_brackets && xnum!(num, "1") => {
850                self.render_sone(numer, den)
851            }
852            // normal
853            (sgroup!(num), sgroup!(den)) if self.strip_brackets && self.script_fracs => {
854                let rend_num = self.render_expression(num);
855                let rend_den = self.render_expression(den);
856                if rend_num.sup && rend_den.sub {
857                    rend_num
858                        .map(|iter| ExprMappedIter(iter.map(|c| superscript_char(c).unwrap())))
859                        .chain(RenderChars::from('⁄'))
860                        .chain(
861                            rend_den.map(|iter| {
862                                ExprMappedIter(iter.map(|c| subscript_char(c).unwrap()))
863                            }),
864                        )
865                        .map(|iter| SimpleFracIter::StrippedScript(Box::new(iter)))
866                } else {
867                    gsfrac(self.render_simple(numer), self.render_simple(denom))
868                }
869            }
870            (num, sgroup!(den)) if self.strip_brackets && self.script_fracs => {
871                let rend_num = self.render_simple(num);
872                let rend_den = self.render_expression(den);
873                if rend_num.sup && rend_den.sub {
874                    rend_num
875                        .map(|iter| SimpMappedIter(iter.map(|c| superscript_char(c).unwrap())))
876                        .chain(RenderChars::from('⁄'))
877                        .chain(rend_den.map(|iter| {
878                            Box::new(ExprMappedIter(iter.map(|c| subscript_char(c).unwrap())))
879                        }))
880                        .map(SimpleFracIter::DenomStrippedScript)
881                } else {
882                    gsfrac(rend_num, self.render_simple(denom))
883                }
884            }
885            (sgroup!(num), den) if self.strip_brackets && self.script_fracs => {
886                let rend_num = self.render_expression(num);
887                let rend_den = self.render_simple(den);
888                if rend_num.sup && rend_den.sub {
889                    rend_num
890                        .map(|iter| {
891                            Box::new(ExprMappedIter(iter.map(|c| superscript_char(c).unwrap())))
892                        })
893                        .chain(RenderChars::from('⁄'))
894                        .chain(
895                            rend_den.map(|iter| {
896                                SimpMappedIter(iter.map(|c| subscript_char(c).unwrap()))
897                            }),
898                        )
899                        .map(SimpleFracIter::NumerStrippedScript)
900                } else {
901                    gsfrac(self.render_simple(numer), rend_den)
902                }
903            }
904            (num, den) => {
905                let rend_num = self.render_simple(num);
906                let rend_den = self.render_simple(den);
907                if self.script_fracs && rend_num.sup && rend_den.sub {
908                    rend_num
909                        .map(|iter| SimpMappedIter(iter.map(|c| superscript_char(c).unwrap())))
910                        .chain(RenderChars::from('⁄'))
911                        .chain(
912                            rend_den.map(|iter| {
913                                SimpMappedIter(iter.map(|c| subscript_char(c).unwrap()))
914                            }),
915                        )
916                        .map(SimpleFracIter::Script)
917                } else {
918                    gsfrac(rend_num, rend_den)
919                }
920            }
921        }
922    }
923
924    #[inline]
925    fn render_fone<'a>(&self, den: &ScriptFunc<'a>) -> RenderChars<FracIter<'a>> {
926        let rend_den = self.render_scriptfunc(den);
927        if rend_den.sub {
928            RenderChars::from('⅟')
929                .chain(
930                    rend_den.map(|iter| FuncMappedIter(iter.map(|c| subscript_char(c).unwrap()))),
931                )
932                .map(FracIter::VulgOne)
933        } else {
934            RenderChars::from("1/").chain(rend_den).map(FracIter::One)
935        }
936    }
937
938    #[allow(clippy::too_many_lines)]
939    fn render_frac<'a>(&self, frac: &Frac<'a>) -> RenderChars<FracIter<'a>> {
940        let sv = self.script_fracs && self.vulgar_fracs;
941        match (&frac.numer, &frac.denom) {
942            // simple frac
943            (script_func!(num), script_func!(den)) => {
944                self.render_simplefrac(num, den).map(FracIter::Simple)
945            }
946            // one vulgar
947            (script_func!(num!("1")), den) if sv => self.render_fone(den),
948            (script_func!(sgroup!(num)), den) if sv && self.strip_brackets && xnum!(num, "1") => {
949                self.render_fone(den)
950            }
951            // normal fractions
952            (script_func!(sgroup!(num)), den) if self.strip_brackets && self.script_fracs => {
953                let rend_num = self.render_expression(num);
954                let rend_den = self.render_scriptfunc(den);
955                if rend_num.sup && rend_den.sub {
956                    rend_num
957                        .map(|iter| {
958                            Box::new(ExprMappedIter(iter.map(|c| superscript_char(c).unwrap())))
959                        })
960                        .chain(RenderChars::from('⁄'))
961                        .chain(
962                            rend_den.map(|iter| {
963                                FuncMappedIter(iter.map(|c| subscript_char(c).unwrap()))
964                            }),
965                        )
966                        .map(FracIter::NumerStrippedScript)
967                } else {
968                    gfrac(self.render_scriptfunc(&frac.numer), rend_den)
969                }
970            }
971            (num, script_func!(sgroup!(den))) if self.strip_brackets && self.script_fracs => {
972                let rend_num = self.render_scriptfunc(num);
973                let rend_den = self.render_expression(den);
974                if rend_num.sup && rend_den.sub {
975                    rend_num
976                        .map(|iter| FuncMappedIter(iter.map(|c| superscript_char(c).unwrap())))
977                        .chain(RenderChars::from('⁄'))
978                        .chain(rend_den.map(|iter| {
979                            Box::new(ExprMappedIter(iter.map(|c| subscript_char(c).unwrap())))
980                        }))
981                        .map(FracIter::DenomStrippedScript)
982                } else {
983                    gfrac(rend_num, self.render_scriptfunc(&frac.denom))
984                }
985            }
986            (num, den) => {
987                let rend_num = self.render_scriptfunc(num);
988                let rend_den = self.render_scriptfunc(den);
989                if self.script_fracs && rend_num.sup && rend_den.sub {
990                    rend_num
991                        .map(|iter| FuncMappedIter(iter.map(|c| superscript_char(c).unwrap())))
992                        .chain(RenderChars::from('⁄'))
993                        .chain(
994                            rend_den.map(|iter| {
995                                FuncMappedIter(iter.map(|c| subscript_char(c).unwrap()))
996                            }),
997                        )
998                        .map(FracIter::Script)
999                } else {
1000                    gfrac(rend_num, rend_den)
1001                }
1002            }
1003        }
1004    }
1005
1006    fn render_intermediate<'a>(
1007        &self,
1008        inter: &Intermediate<'a>,
1009    ) -> RenderChars<IntermediateIter<'a>> {
1010        match inter {
1011            Intermediate::ScriptFunc(sf) => {
1012                self.render_scriptfunc(sf).map(IntermediateIter::ScriptFunc)
1013            }
1014            Intermediate::Frac(frac) => self.render_frac(frac).map(IntermediateIter::Frac),
1015        }
1016    }
1017
1018    fn render_expression<'a>(&self, expr: &Expression<'a>) -> RenderChars<ExpressionIter<'a>> {
1019        let inters: RenderChars<_> = expr
1020            .iter()
1021            .map(|inter| self.render_intermediate(inter))
1022            .collect();
1023        inters
1024    }
1025
1026    /// Render an input string with the given options
1027    #[must_use]
1028    pub fn render<'a>(&self, inp: &'a str) -> RenderedUnicode<'a> {
1029        let parsed = parse_unicode(inp);
1030        let rendered = self.render_expression(&parsed);
1031        RenderedUnicode(rendered.iter)
1032    }
1033}
1034
1035/// Rendered unicode
1036///
1037/// This can be formatted to get a string, [consumed into a `Write`][RenderedUnicode::into_write],
1038/// or iterated as `char`s.
1039#[derive(Debug, Clone)]
1040pub struct RenderedUnicode<'a>(ExpressionIter<'a>);
1041
1042impl Iterator for RenderedUnicode<'_> {
1043    type Item = char;
1044
1045    fn next(&mut self) -> Option<Self::Item> {
1046        self.0.next()
1047    }
1048}
1049
1050impl FusedIterator for RenderedUnicode<'_> {}
1051
1052impl RenderedUnicode<'_> {
1053    /// Write out, consuming self in the process
1054    ///
1055    /// This avoids the clone necessary when formatting.
1056    ///
1057    /// # Errors
1058    ///
1059    /// If there are any io errors writing.
1060    pub fn into_write<O: Write>(self, out: &mut O) -> io::Result<()> {
1061        for chr in self {
1062            write!(out, "{chr}")?;
1063        }
1064        Ok(())
1065    }
1066}
1067
1068impl fmt::Display for RenderedUnicode<'_> {
1069    fn fmt(&self, out: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1070        for chr in self.clone() {
1071            write!(out, "{chr}")?;
1072        }
1073        Ok(())
1074    }
1075}
1076
1077/// Parse asciimath using the conventions of this renderer
1078#[must_use]
1079pub fn parse_unicode(inp: &str) -> Expression {
1080    asciimath_parser::parse_tokens(Tokenizer::with_tokens(inp, &*TOKEN_MAP, true))
1081}
1082
1083/// Convert an asciimath string into unicode and write it to the writer
1084///
1085/// # Errors
1086///
1087/// If one is thrown by the writer
1088pub fn write_unicode<O: Write>(inp: &str, out: &mut O) -> io::Result<()> {
1089    InlineRenderer::default().render(inp).into_write(out)
1090}
1091
1092/// Convert an asciimath string into a unicode string
1093#[must_use]
1094pub fn convert_unicode(inp: &str) -> String {
1095    InlineRenderer::default().render(inp).collect()
1096}
1097
1098#[cfg(test)]
1099mod tests {
1100    use super::{InlineRenderer, SkinTone};
1101
1102    #[test]
1103    fn example() {
1104        let ex = "sum_(i=1)^n i^3=((n(n+1))/2)^2";
1105        let expected = "∑₍ᵢ₌₁₎ⁿi³=(ⁿ⁽ⁿ⁺¹⁾⁄₂)²";
1106
1107        let res = super::convert_unicode(ex);
1108        assert_eq!(res, expected);
1109
1110        let mut res = Vec::new();
1111        super::write_unicode(ex, &mut res).unwrap();
1112        assert_eq!(res, expected.as_bytes());
1113
1114        let rend = InlineRenderer::default().render(ex);
1115        assert_eq!(format!("{rend}"), expected);
1116
1117        let mut res = Vec::new();
1118        rend.into_write(&mut res).unwrap();
1119        assert_eq!(res, expected.as_bytes());
1120    }
1121
1122    #[test]
1123    fn vulgar_fracs() {
1124        let opts = InlineRenderer {
1125            vulgar_fracs: true,
1126            ..Default::default()
1127        };
1128        let res: String = opts.render("1/2").collect();
1129        assert_eq!(res, "½");
1130
1131        let res: String = opts.render("a / s").collect();
1132        assert_eq!(res, "℁");
1133    }
1134
1135    #[test]
1136    fn stripped_vulgar_fracs() {
1137        let opts = InlineRenderer {
1138            vulgar_fracs: true,
1139            strip_brackets: true,
1140            ..Default::default()
1141        };
1142        let res: String = opts.render("(1)/2").collect();
1143        assert_eq!(res, "½");
1144
1145        let res: String = opts.render("7/[8]").collect();
1146        assert_eq!(res, "⅞");
1147
1148        let res: String = opts.render("{a} / (s)").collect();
1149        assert_eq!(res, "℁");
1150    }
1151
1152    #[test]
1153    fn script_fracs() {
1154        let opts = InlineRenderer {
1155            script_fracs: true,
1156            strip_brackets: false,
1157            ..Default::default()
1158        };
1159        let res: String = opts.render("y / x").collect();
1160        assert_eq!(res, "ʸ⁄ₓ");
1161
1162        let res: String = opts.render("(y) / x").collect();
1163        assert_eq!(res, "⁽ʸ⁾⁄ₓ");
1164    }
1165
1166    #[test]
1167    fn stripped_script_fracs() {
1168        let opts = InlineRenderer {
1169            script_fracs: true,
1170            ..Default::default()
1171        };
1172
1173        let res: String = opts.render("(y) / x").collect();
1174        assert_eq!(res, "ʸ⁄ₓ");
1175
1176        let res: String = opts.render("y / [x]").collect();
1177        assert_eq!(res, "ʸ⁄ₓ");
1178
1179        let res: String = opts.render("(y)/[x]").collect();
1180        assert_eq!(res, "ʸ⁄ₓ");
1181    }
1182
1183    #[test]
1184    fn one_fracs() {
1185        let res = super::convert_unicode("1/x");
1186        assert_eq!(res, "⅟ₓ");
1187
1188        let res = super::convert_unicode("1 / sinx");
1189        assert_eq!(res, "⅟ₛᵢₙ ₓ");
1190
1191        let opts = InlineRenderer {
1192            script_fracs: false,
1193            vulgar_fracs: false,
1194            strip_brackets: false,
1195            ..Default::default()
1196        };
1197        let res: String = opts.render("1 / sinx").collect();
1198        assert_eq!(res, "1/sin x");
1199    }
1200
1201    #[test]
1202    fn normal_fracs() {
1203        let opts = InlineRenderer {
1204            script_fracs: false,
1205            vulgar_fracs: false,
1206            strip_brackets: false,
1207            ..Default::default()
1208        };
1209
1210        let res: String = opts.render("sinx / cosy").collect();
1211        assert_eq!(res, "sin x/cos y");
1212    }
1213
1214    #[test]
1215    fn unary() {
1216        let res = super::convert_unicode("sqrt x");
1217        assert_eq!(res, "√x");
1218
1219        let res = super::convert_unicode("vec x");
1220        assert_eq!(res, "vec x");
1221
1222        let res = super::convert_unicode("bbb E");
1223        assert_eq!(res, "𝔼");
1224
1225        let res = super::convert_unicode("bbb (E)");
1226        assert_eq!(res, "𝔼");
1227
1228        let res = super::convert_unicode("dot x");
1229        assert_eq!(res, "ẋ");
1230
1231        let res = super::convert_unicode("dot{x}");
1232        assert_eq!(res, "ẋ");
1233
1234        let res = super::convert_unicode("norm x");
1235        assert_eq!(res, "||x||");
1236
1237        let res = super::convert_unicode("sqrt overline x");
1238        assert_eq!(res, "√x̅");
1239
1240        let res = super::convert_unicode("sqrt overline(x)");
1241        assert_eq!(res, "√x̅");
1242    }
1243
1244    #[test]
1245    fn binary() {
1246        let res = super::convert_unicode("root 3 x");
1247        assert_eq!(res, "∛x");
1248
1249        let res = super::convert_unicode("root {4} x");
1250        assert_eq!(res, "∜x");
1251
1252        let res = super::convert_unicode("stackrel *** =");
1253        assert_eq!(res, "≛");
1254
1255        let res = super::convert_unicode("overset a x");
1256        assert_eq!(res, "x\u{0363}");
1257
1258        let res = super::convert_unicode("overset (e) {y}");
1259        assert_eq!(res, "y\u{0364}");
1260
1261        let res = super::convert_unicode("oversetasinx");
1262        assert_eq!(res, "overset a sin x");
1263    }
1264
1265    #[test]
1266    fn functions() {
1267        let res = super::convert_unicode("sin x/x");
1268        assert_eq!(res, "ˢⁱⁿ ˣ⁄ₓ");
1269    }
1270
1271    #[test]
1272    fn script() {
1273        let res = super::convert_unicode("x^sin x");
1274        assert_eq!(res, "xˢⁱⁿ ˣ");
1275
1276        let res = super::convert_unicode("x^vec(x)");
1277        assert_eq!(res, "xᵛᵉᶜ ⁽ˣ⁾");
1278
1279        let res = super::convert_unicode("x_x^y");
1280        assert_eq!(res, "xₓʸ");
1281
1282        let res = super::convert_unicode("x_y^sin x");
1283        assert_eq!(res, "x_y^sin x");
1284
1285        let res = super::convert_unicode("x^sin rho");
1286        assert_eq!(res, "x^sin ρ");
1287
1288        let res = super::convert_unicode("x_x");
1289        assert_eq!(res, "xₓ");
1290
1291        let res = super::convert_unicode("x_y");
1292        assert_eq!(res, "x_y");
1293    }
1294
1295    #[test]
1296    fn text() {
1297        let res = super::convert_unicode("\"text\"");
1298        assert_eq!(res, "text");
1299    }
1300
1301    #[test]
1302    fn matrix() {
1303        let opts = InlineRenderer::default();
1304
1305        let res: String = opts.render("[ [x, y], [a, b] ]").collect();
1306        assert_eq!(res, "[[x,y],[a,b]]");
1307    }
1308
1309    #[test]
1310    fn skin_tone() {
1311        let opts = InlineRenderer {
1312            skin_tone: SkinTone::Default,
1313            ..Default::default()
1314        };
1315        let res: String = opts.render(":hand:").collect();
1316        assert_eq!(res, "✋");
1317
1318        let opts = InlineRenderer {
1319            skin_tone: SkinTone::Dark,
1320            ..Default::default()
1321        };
1322        let res: String = opts.render(":hand:").collect();
1323        assert_eq!(res, "✋🏿");
1324    }
1325}