## Coverage Report

#### Created: 2026-05-25 08:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/runner/work/MathCAT/MathCAT/src/lib.rs

    Line
    Count
    Source
    1
    #![cfg_attr(coverage, feature(coverage_attribute))]
    2
    #![allow(clippy::needless_return)]
    3
    4
    //! A library for generating speech and braille from MathML
    5
    //!
    6
    //! Typical usage is:
    7
    //! 1. Set the rules directory [`set_rules_dir`]
    8
    //! 2. Set whatever preferences are need with repeated calls to [`set_preference`].
    9
    //! 3. Set MathML via [`set_mathml`]
    10
    //!    A string representing the cleaned up MathML along with `id`s on each node is returned for highlighting if desired
    11
    //! 4. Get the speech [`get_spoken_text`] or (Unicode) braille [`get_braille`].
    12
    //!
    13
    //! The expression can be navigated also.
    14
    //! This is done in one of two ways:
    15
    //! 1. Pass key strokes to allow a user to navigate the MathML by calling [`do_navigate_keypress`]; the speech is returned.
    16
    //! 2. Pass the MathCAT navigation command directory by called [`do_navigate_command`]; the speech is return returned.
    17
    //!
    18
    //! To get the MathML associated with the current navigation node, call [`get_navigation_mathml`].
    19
    //! To just get the `id` and offset from the id of the current navigation node, call [`get_navigation_mathml_id`].
    20
    ///
    21
    /// This module re-exports anyhow types. Use `bail!` for early returns and
    22
    /// `context()`/`with_context()` on Result to add context (replacing old `chain_err()`).
    23
    pub mod errors {
    24
        pub use anyhow::{anyhow, bail, Error, Result, Context};
    25
    }
    26
    27
    pub mod interface;
    28
    #[cfg(feature = "include-zip")]
    29
    pub use shim_filesystem::ZIPPED_RULE_FILES;
    30
    31
    mod canonicalize;
    32
    mod infer_intent;
    33
    pub mod speech;
    34
    mod braille;
    35
    mod navigate;
    36
    mod prefs;
    37
    mod tts;
    38
    mod xpath_functions;
    39
    mod definitions;
    40
    pub mod pretty_print;
    41
    mod chemistry;
    42
    43
    pub mod shim_filesystem; // really just for override_file_for_debugging_rules, but the config seems to throw it off
    44
    pub use interface::*;
    45
    use crate::errors::{bail, Result};
    46
    47
    #[cfg(test)]
    48
    0
    pub fn init_logger() {
    49
    0
        env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug"))
    50
    0
            .is_test(true)
    51
    0
            .format_timestamp(None)
    52
    0
            .format_module_path(false)
    53
    0
            .format_indent(None)
    54
    0
            .format_level(false)
    55
    0
            .init();
    56
    0
    }
    57
    58
    /// Build Absolute path to rules dir for testing
    59
    251
    pub fn abs_rules_dir_path() -> String {
    60
        cfg_if::cfg_if! {
    61
        if #[cfg(feature = "include-zip")] {
    62
              return "Rules".to_string();
    63
        } else {
    64
            // Package root (see tests/common/mod.rs `abs_rules_dir_path` for rationale).
    65
    251
            return std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
    66
    251
                .join("Rules")
    67
    251
                .to_str()
    68
    251
                .expect("CARGO_MANIFEST_DIR and Rules path must be UTF-8")
    69
    251
                .to_string();
    70
            }
    71
        }
    72
    251
    }
    73
    74
    141
    pub fn are_strs_canonically_equal_with_locale(test: &str, target: &str, ignore_attrs: &[&str], block_separators: &str, decimal_separators: &str) -> Result<()> {
    75
        use crate::{interface::*, pretty_print::mml_to_string};
    76
        use sxd_document::parser;
    77
        use crate::canonicalize::canonicalize;
    78
        use std::panic::{catch_unwind, AssertUnwindSafe};
    79
    80
    141
        crate::interface::init_panic_handler();
    81
    141
        let result = catch_unwind(AssertUnwindSafe(|| {
    82
            // this forces initialization
    83
    141
            crate::interface::set_rules_dir(abs_rules_dir_path()).unwrap();
    84
    141
            set_preference("Language", "en").unwrap();
    85
    141
            set_preference("BlockSeparators", block_separators).unwrap();
    86
    141
            set_preference("DecimalSeparators", decimal_separators).unwrap();
    87
    141
            crate::speech::SPEECH_RULES.with(|rules|  rules.borrow_mut().read_files().unwrap());
    88
    89
    141
            let package1 = &parser::parse(test).expect("Failed to parse test input");
    90
    141
            let mathml = get_element(package1);
    91
    141
            trim_element(mathml, false);
    92
    141
            let mathml_test = canonicalize(mathml).unwrap();
    93
    94
    141
            let package2 = &parser::parse(target).expect("Failed to parse target input");
    95
    141
            let mathml_target = get_element(package2);
    96
    141
            trim_element(mathml_target, false);
    97
    98
    141
            match is_same_element(mathml_test, mathml_target, ignore_attrs) {
    99
    141
                Ok(_) => Ok( () ),
    100
    0
                Err(e) => {
    101
    0
                    bail!("{}\nResult:\n{}\nTarget:\n{}", e, mml_to_string(mathml_test), mml_to_string(mathml_target));
    102
                },
    103
            }
    104
    141
        }));
    105
    141
        match crate::interface::report_any_panic(result) {
    106
    140
            Ok(()) => Ok(()),
    107
    1
            Err(e) => {
    108
    1
                eprintln!("{}", e);
    109
    1
                Err(e)
    110
            }
    111
        }
    112
    141
    }
    113
    114
    /// sets locale to be US standard
    115
    30
    pub fn are_strs_canonically_equal(test: &str, target: &str, ignore_attrs: &[&str]) -> bool {
    116
    30
        are_strs_canonically_equal_with_locale(test, target, ignore_attrs, ", \u{00A0}\u{202F}", ".").is_ok()
    117
    30
    }
    118
    119
    /// Like `are_strs_canonically_equal` but returns `Result` for use in `#[test]` functions that return `Result<()>`.
    120
    102
    pub fn are_strs_canonically_equal_result(test: &str, target: &str, ignore_attrs: &[&str]) -> Result<()> {
    121
    102
        are_strs_canonically_equal_with_locale(test, target, ignore_attrs, ", \u{00A0}\u{202F}", ".")
    122
    102
    }