libmathcat/
lib.rs

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