libmathcat/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! A library for generating speech and braille from MathML
//! 
//! Typical usage is:
//! 1. Set the rules directory [`set_rules_dir`]
//! 2. Set whatever preferences are need with repeated calls to [`set_preference`].
//! 3. Set MathML via [`set_mathml`]
//!    A string representing the cleaned up MathML along with `id`s on each node is returned for highlighting if desired
//! 4. Get the speech [`get_spoken_text`] or (Unicode) braille [`get_braille`].
//!
//! The expression can be navigated also.
//! This is done in one of two ways:
//! 1. Pass key strokes to allow a user to navigate the MathML by calling [`do_navigate_keypress`]; the speech is returned.
//! 2. Pass the MathCAT navigation command directory by called [`do_navigate_command`]; the speech is return returned.
//! 
//! To get the MathML associated with the current navigation node, call [`get_navigation_mathml`].
//! To just get the `id` and offset from the id of the current navigation node, call [`get_navigation_mathml_id`].
#![recursion_limit = "1024"]

#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain! {
        // foreign_links {
        //     Io(std::io::Error);
        //     HttpRequest(reqwest::Error);
        // }
    }
}

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate log;

#[macro_use]
extern crate cfg_if;


pub mod interface;
#[cfg(feature = "include-zip")]
pub use shim_filesystem::ZIPPED_RULE_FILES;

mod canonicalize;
mod infer_intent;
pub mod speech;
mod braille;
mod navigate;
mod prefs;
mod tts;
mod xpath_functions;
mod definitions;
mod pretty_print;
mod chemistry;

pub mod shim_filesystem; // really just for override_file_for_debugging_rules, but the config seems to throw it off
pub use interface::*;

#[cfg(test)]
pub fn init_logger() {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug"))
        .is_test(true)
        .format_timestamp(None)
        .format_module_path(false)
        .format_indent(None)
        .format_level(false)
        .init();
}

#[cfg(test)]
/// Build Absolute path to rules dir for testing
pub fn abs_rules_dir_path() -> String {
    return std::env::current_exe().unwrap().parent().unwrap()
                .join("../../../Rules")
                .to_str().unwrap().to_string();
    // use std::path::PathBuf;
    // let out_dir = std::env::var_os("OUT_DIR").unwrap();
    // println!("abs_rules_dir_path: out_dir={:?}", out_dir);
    // let out_dir = PathBuf::from(&out_dir);
    // return PathBuf::from(&out_dir).join("Rules").to_string_lossy().to_string();
}

#[cfg(test)]
pub fn are_strs_canonically_equal_with_locale(test: &str, target: &str, block_separators: &str, decimal_separators: &str) -> bool {
    use crate::{interface::*, pretty_print::mml_to_string};
    use sxd_document::parser;
    use crate::canonicalize::canonicalize;
    // this forces initialization
    crate::interface::set_rules_dir(abs_rules_dir_path()).unwrap();
    crate::speech::SPEECH_RULES.with(|rules|  rules.borrow_mut().read_files().unwrap());
    set_preference("BlockSeparators".to_string(), block_separators.to_string()).unwrap();
    set_preference("DecimalSeparators".to_string(), decimal_separators.to_string()).unwrap();
    
    let package1 = &parser::parse(test).expect("Failed to parse test input");
    let mathml = get_element(package1);
    trim_element(&mathml);
    // debug!("test:\n{}", mml_to_string(&mathml));
    let mathml_test = canonicalize(mathml).unwrap();
   
    let package2 = &parser::parse(target).expect("Failed to parse target input");
    let mathml_target = get_element(package2);
    trim_element(&mathml_target);
    // debug!("target:\n{}", mml_to_string(&mathml_target));

    match is_same_element(&mathml_test, &mathml_target) {
        Ok(_) => return true,
        Err(e) => panic!("{}\nResult:\n{}\nTarget:\n{}", e, mml_to_string(&mathml_test), mml_to_string(&mathml_target)),
    }
}

#[cfg(test)]
// sets locale to be US standard
pub fn are_strs_canonically_equal(test: &str, target: &str) -> bool {
    return are_strs_canonically_equal_with_locale(test, target, ", \u{00A0}\u{202F}", ".");
}