## 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/main.rs

    Line
    Count
    Source
    1
    // *** MathCAT doesn't normally want to build a binary ***
    2
    // *** This file is here because it is useful for trying out things ***
    3
    #![allow(clippy::needless_return)]
    4
    5
    use libmathcat::interface::*;
    6
    use log::{debug, info};
    7
    use std::time::Instant;
    8
    use std::process::exit;
    9
    10
    11
    // Maybe also have this speak to test the TTS generation.
    12
    // There is a rust winapi crate that mirrors the WinPAI and has "Speak(...)" in it
    13
    14
    // env RUST_LOG=DEBUG cargo run --features "include-zip"
    15
    cfg_if::cfg_if! {
    16
        if #[cfg(feature = "include-zip")] {
    17
            fn get_rules_dir() -> String {
    18
              return "Rules".to_string();
    19
            }
    20
        } else {
    21
    0
            fn get_rules_dir() -> String {
    22
              // for testing with zipped rules dir
    23
              // let rules_path = std::env::current_exe().unwrap().parent().unwrap().join("../../../MathCATForPython/addon/globalPlugins/MathCAT/Rules");
    24
    0
              let rules_path = std::env::current_exe().unwrap().parent().unwrap().join("../../Rules");
    25
    0
              return rules_path.as_os_str().to_str().unwrap().to_string();
    26
    0
            }
    27
        }
    28
    }
    29
    30
    0
    fn main() {
    31
    0
      env_logger::builder()
    32
    0
          .format_timestamp(None)
    33
    0
          .format_module_path(false)
    34
    0
          .format_indent(Some(2))
    35
    0
          .format_level(false)
    36
    0
          .init();
    37
    38
    //    let expr = r#"
    39
    //    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
    40
    //    <mrow>
    41
    //      <msup>
    42
    //        <mi>e</mi>
    43
    //        <mrow>
    44
    //          <mo>&#x2212;</mo>
    45
    //          <mfrac>
    46
    //            <mn>1</mn>
    47
    //            <mn>2</mn>
    48
    //          </mfrac>
    49
    //          <msup>
    50
    //            <mrow>
    51
    //              <mrow>
    52
    //                <mo>(</mo>
    53
    //                <mrow>
    54
    //                  <mfrac>
    55
    //                    <mrow>
    56
    //                      <mi>x</mi>
    57
    //                      <mo>&#x2212;</mo>
    58
    //                      <mi>&#x03BC;</mi>
    59
    //                    </mrow>
    60
    //                    <mi>&#x03C3;</mi>
    61
    //                  </mfrac>
    62
    //                </mrow>
    63
    //                <mo>)</mo>
    64
    //              </mrow>
    65
    //            </mrow>
    66
    //            <mn>2</mn>
    67
    //          </msup>
    68
    //        </mrow>
    69
    //      </msup>
    70
    //    </mrow>
    71
    //  </math>
    72
    // "#;
    73
      // let expr = "<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'>
    74
      //       <msup intent='power($base(2, $base),silly($exp,-1.))'>
    75
      //       <mi arg='base'>x</mi>
    76
      //       <mi arg='exp'>n</mi>
    77
      //     </msup>
    78
      //       </math>
    79
      //     ";
    80
      // let expr = "<mrow intent='pre@prefix(in@infix($a, x))(post@postfix($b))'>
    81
      //     <mi arg='a'>A</mi>
    82
      //     <mover>
    83
      //         <mo intent='map'>⟶</mo>
    84
      //         <mo intent='congruence'>≅</mo>
    85
      //     </mover>
    86
      //     <mi arg='b'>B</mi>
    87
      //   </mrow>";
    88
      // let expr = "<math><mi>Na</mi><mi>S</mi><mo>(</mo><mi>l</mi><mo>)</mo></math>";
    89
    90
    91
      // let expr = "<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'>
    92
      //     <mrow>
    93
      //       <mo stretchy='false'>[</mo>
    94
      //       <mrow>
    95
      //         <mi>Co</mi>
    96
      //       </mrow>
    97
      //       <mo stretchy='false'>(</mo>
    98
      //       <mrow>
    99
      //         <mi>NH</mi>
    100
      //       </mrow>
    101
      //       <msub>
    102
      //         <mrow>
    103
      //           <mrow>
    104
      //             <mpadded width='0'>
    105
      //               <mphantom>
    106
      //                 <mi>A</mi>
    107
      //               </mphantom>
    108
      //             </mpadded>
    109
      //           </mrow>
    110
      //         </mrow>
    111
      //         <mrow>
    112
      //           <mrow>
    113
      //             <mpadded height='0'>
    114
      //               <mn>3</mn>
    115
      //             </mpadded>
    116
      //           </mrow>
    117
      //         </mrow>
    118
      //       </msub>
    119
      //       <mo stretchy='false'>)</mo>
    120
      //       <msub>
    121
      //         <mrow>
    122
      //           <mrow>
    123
      //             <mpadded width='0'>
    124
      //               <mphantom>
    125
      //                 <mi>A</mi>
    126
      //               </mphantom>
    127
      //             </mpadded>
    128
      //           </mrow>
    129
      //         </mrow>
    130
      //         <mrow>
    131
      //           <mrow>
    132
      //             <mpadded height='0'>
    133
      //               <mn>6</mn>
    134
      //             </mpadded>
    135
      //           </mrow>
    136
      //         </mrow>
    137
      //       </msub>
    138
      //       <mo stretchy='false'>]</mo>
    139
      //       <msup>
    140
      //         <mrow>
    141
      //           <mrow>
    142
      //             <mpadded width='0'>
    143
      //               <mphantom>
    144
      //                 <mi>A</mi>
    145
      //               </mphantom>
    146
      //             </mpadded>
    147
      //           </mrow>
    148
      //         </mrow>
    149
      //         <mrow>
    150
      //           <mn>3</mn>
    151
      //           <mo>+</mo>
    152
      //         </mrow>
    153
      //       </msup>
    154
      //       <mtext>&#xA0;</mtext>
    155
      //       <mo stretchy='false'>(</mo>
    156
      //       <mrow>
    157
      //         <mi>Cl</mi>
    158
      //       </mrow>
    159
      //       <msub>
    160
      //         <mrow>
    161
      //           <mrow>
    162
      //             <mpadded width='0'>
    163
      //               <mphantom>
    164
      //                 <mi>A</mi>
    165
      //               </mphantom>
    166
      //             </mpadded>
    167
      //           </mrow>
    168
      //         </mrow>
    169
      //         <mrow>
    170
      //           <mrow>
    171
      //             <mpadded height='0'>
    172
      //               <mn>3</mn>
    173
      //             </mpadded>
    174
      //           </mrow>
    175
      //         </mrow>
    176
      //       </msub>
    177
      //       <mo stretchy='false'>)</mo>
    178
      //       <msup>
    179
      //         <mrow>
    180
      //           <mrow>
    181
      //             <mpadded width='0'>
    182
      //               <mphantom>
    183
      //                 <mi>A</mi>
    184
      //               </mphantom>
    185
      //             </mpadded>
    186
      //           </mrow>
    187
      //         </mrow>
    188
      //         <mrow>
    189
      //           <mo>&#x2212;</mo>,
    190
      //         </mrow>
    191
      //       </msup>
    192
      //     </mrow>
    193
      //   </math>";
    194
    195
    0
      let expr = r#"
    196
    0
    <math> <mn>1</mn> <mi>kg</mi> <msup> <mi intent=':unit'>sec</mi> <mrow><mo>−</mo><mn>1</mn></mrow> </msup> <msup> <mi intent='unit'>m</mi> <mrow><mo>−</mo><mn>1</mn></mrow> </msup> </math>
    197
    0
    198
    0
             "#;
    199
      // let instant = Instant::now();
    200
    201
      // let rules_dir = "".to_string();    // Use MathCATRulesDir, potentially pointing to a zipped version
    202
    0
      if let Err(e) = set_rules_dir(get_rules_dir()) {
    203
    0
        eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);
    204
    0
      }
    205
    0
      debug!("Languages: {}", libmathcat::interface::get_supported_languages().unwrap_or_default().join(", "));
    206
    207
      #[cfg(feature = "include-zip")]
    208
      info!("***********include-zip is present**********");
    209
    0
      info!("Version = '{}' using Rules dir {}", get_version(), get_rules_dir());
    210
    0
      set_preference("Language", "en").unwrap();
    211
    0
      set_preference("DecimalSeparator", "Auto").unwrap();
    212
    0
      set_preference("BrailleCode", "UEB").unwrap();
    213
    0
      set_preference("BrailleNavHighlight", "On").unwrap();
    214
    0
      set_preference("TTS", "None").unwrap();
    215
    0
      set_preference("Verbosity", "Verbose").unwrap();
    216
    0
      set_preference("NavVerbosity", "Verbose").unwrap();
    217
    0
      set_preference("NavMode", "Enhanced").unwrap();
    218
    0
      set_preference("Impairment", "Blindness").unwrap();
    219
    0
      set_preference("SpeechOverrides_CapitalLetters", "").unwrap();
    220
    0
      set_preference("MathRate", "80").unwrap();
    221
      // set_preference("CapitalLetters_UseWord", "true").unwrap();
    222
      // set_preference("CapitalLetters_Pitch", "30").unwrap();
    223
    0
      set_preference("CapitalLetters_Beep", "true").unwrap();
    224
    0
      set_preference("IntentErrorRecovery", "Error").unwrap();
    225
      // set_preference("MathRate", "77").unwrap();
    226
    227
    0
      set_preference("Bookmark", "false").unwrap();
    228
    0
      set_preference("SpeechStyle", "ClearSpeak").unwrap();
    229
    0
      info!("Languages: {}", libmathcat::interface::get_supported_languages().unwrap_or_default().join(", "));
    230
    0
      info!("Speech styles: {}", libmathcat::interface::get_supported_speech_styles("ClearSpeak").unwrap_or_default().join(", "));
    231
    0
      info!("BrailleCodes: {}", libmathcat::interface::get_supported_braille_codes().unwrap_or_default().join(", "));
    232
      // set_preference("DecimalSeparators", ",").unwrap();
    233
      // set_preference("BlockSeparators", ". ").unwrap();
    234
    0
      if let Err(e) = set_mathml(expr) {
    235
    0
        eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);
    236
    0
      };
    237
    238
      // match do_navigate_command("ZoomIn".to_string())  {
    239
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    240
      //   Ok(speech) => info!("\nZoomIn speech: '{speech}'"),
    241
      // }
    242
      // match do_navigate_command("ToggleZoomLockUp".to_string()) {
    243
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    244
      //   Ok(speech) => info!("ToggleZoomLockUp speech: '{speech}'"),
    245
      // }
    246
      // match do_navigate_command("MovePrevious".to_string()) {
    247
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    248
      //   Ok(speech) => info!("MovePrevious speech: '{speech}'"),
    249
      // }
    250
      // match do_navigate_command("MovePrevious".to_string()) {
    251
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    252
      //   Ok(speech) => info!("MovePrevious speech: '{}'", speech),
    253
      // }
    254
      // match do_navigate_command("MovePrevious".to_string()) {
    255
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    256
      //   Ok(speech) => info!("MovePrevious speech: '{}'", speech),
    257
      // }
    258
      // match do_navigate_command("MoveNext".to_string()) {
    259
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    260
      //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
    261
      // }
    262
      // match do_navigate_command("MoveNext".to_string()) {
    263
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    264
      //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
    265
      // }
    266
      // match do_navigate_command("MoveNext".to_string()) {
    267
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    268
      //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
    269
      // }
    270
      // match do_navigate_command("MoveNext".to_string()) {
    271
      //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
    272
      //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
    273
      // }
    274
      // match get_spoken_text() {
    275
      //   Ok(speech) => info!("Computed speech string:\n   '{speech}'"),
    276
      //   Err(e) => eprintln!("{}", errors_to_string(&e)); exit(1);,
    277
      // }
    278
    0
      debug!("Speech language is {}", get_preference("Language").unwrap());
    279
    0
      debug!("DecimalSeparator: {:?}", get_preference("DecimalSeparator").unwrap());
    280
    0
      debug!("DecimalSeparators: {:?}, BlockSeparators: {:?}", get_preference("DecimalSeparators").unwrap(), get_preference("BlockSeparators").unwrap());
    281
    0
      debug!("SpeechStyle: {:?}", get_preference("SpeechStyle").unwrap());
    282
    0
      debug!("Verbosity: {:?}", get_preference("Verbosity").unwrap());
    283
    284
      // info!("Time taken for loading+speech+braille: {}ms", instant.elapsed().as_millis());
    285
      // let instant = Instant::now();
    286
    0
      match get_spoken_text() {
    287
    0
        Ok(speech) => info!("Computed speech string:\n   '{}'", speech),
    288
    0
        Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    289
      }
    290
      // info!("Time taken (second time for speech): {}ms", instant.elapsed().as_millis());
    291
      // info!("SpeechStyle: {:?}", get_preference("SpeechStyle"));
    292
    293
    0
      match get_braille("") {
    294
    0
        Ok(braille) => info!("Computed braille string:\n   '{braille}'"),
    295
    0
        Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    296
      }
    297
    0
      debug!("...using BrailleCode: {:?}", get_preference("BrailleCode").unwrap());
    298
      // let xpath_counts = libmathcat::speech::xpath_count();
    299
      // info!("#xpath = {}; duplicates = {}", xpath_counts.0, xpath_counts.1);
    300
      // info!("Time taken (second time for speech + braille): {}ms", instant.elapsed().as_millis());
    301
      // debug!("Hashmap sizes:\n{}", libmathcat::speech::SpeechRules::print_sizes());
    302
    0
      timing_test(expr, 000);
    303
    304
    0
    }
    305
    306
    0
    fn timing_test(expr: &str, n_loops: usize) {
    307
    0
      if n_loops == 0 {
    308
    0
        return;
    309
    0
      }
    310
    311
    0
      let n_loops_float = n_loops as f64;
    312
    0
      let instant = Instant::now();
    313
    0
      for _ in 0..n_loops {
    314
    0
        if let Err(e) = set_mathml(expr) {
    315
    0
          eprintln!("Error: exiting -- {}", errors_to_string(&e));
    316
    0
        };
    317
    0
        match get_spoken_text() {
    318
    0
          Ok(_) =>( ),
    319
    0
          Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    320
        }
    321
    0
        match get_braille("") {
    322
    0
          Ok(_) => (),
    323
    0
          Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    324
        }
    325
      }
    326
    0
      info!("Time taken (time for set, speech, {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
    327
    328
    0
      let instant = Instant::now();
    329
    0
      for _ in 0..n_loops {
    330
    0
        if let Err(e) = set_mathml(expr) {
    331
    0
          eprintln!("Error: exiting -- {}", errors_to_string(&e));
    332
    0
        };
    333
      }
    334
    0
      info!("Time taken (time for set averaged over {} loops): {}ms", n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
    335
    336
    0
      let instant = Instant::now();
    337
    0
      for _ in 0..n_loops {
    338
    0
        match get_spoken_text() {
    339
    0
          Ok(_) =>( ),
    340
    0
          Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    341
        }
    342
      }
    343
    0
      info!("Time taken (time for get_spoken_text() averaged over {} loops): {}ms", n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
    344
    345
    0
      set_preference("BrailleCode", "UEB").unwrap();
    346
    0
      get_braille("").unwrap();
    347
    0
      let instant = Instant::now();
    348
    0
      for _ in 0..n_loops {
    349
    0
        match get_braille("") {
    350
    0
          Ok(_) => (),
    351
    0
          Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
    352
        }
    353
      }
    354
    0
      info!("Time taken (time for {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
    355
    356
    0
        if let Err(e) = set_mathml(expr) {
    357
    0
          eprintln!("Error: exiting -- {}", errors_to_string(&e));
    358
    0
        };
    359
    0
      set_preference("BrailleCode", "Nemeth").unwrap();
    360
    0
      get_braille("").unwrap();
    361
    0
      let instant = Instant::now();
    362
    0
      for _ in 0..n_loops {
    363
    0
        match get_braille("") {
    364
    0
          Ok(_) => (),
    365
    0
          Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);} ,
    366
        }
    367
      }
    368
    0
      info!("Time taken (time for {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
    369
    0
    }