diff --git a/docs/helpers.md b/docs/helpers.md index 1d2e2d17..59b8387a 100644 --- a/docs/helpers.md +++ b/docs/helpers.md @@ -6,7 +6,7 @@ This page is a work-in-progress. ## Getting Started If you plan to work on MathCAT development, you need to make use of github: 1. Fork the MathCAT repo at `github.com/NSoiffer/MathCAT` -2. Clone the the forked copy so you have a local copy to work on. +2. Clone the forked copy so you have a local copy to work on. 3. Checkout the branch I create for your work (typically the country code for your translation) and work in that branch. If you are unfamiliar with these steps, a simple search will turn up lots of places that describe how to do them. They are simple, so don't get put off by your unfamiliarity. @@ -25,11 +25,11 @@ Note: The MathCAT settings dialog looks for files named `XXX_Rules.yaml` and add These files have auto-generated initial translations. Even though they are translated, `t:` (see below) is used, not the upper case `T:`. This is because each translation should be verified to be correct and when verified, then change to the uppercase version. See below for more comments about the auto translations. - * In some languages it doesn't make sense to says "_the_ square root of x" (and maybe "of"). If that is the case, just change those to empty strings. + * In some languages it doesn't make sense to say "_the_ square root of x" (and maybe "of"). If that is the case, just change those to empty strings. * Some languages, the word order changes -- feel free to move the words around, but pay attention to the indentation. Indentation is meaningful in YAML. * In some languages, you may want to add words that aren't in the English version, perhaps before or after existing phrases. Feel free to add them -- they can be conditionally added using `test` if needed. Please contact @NSoiffer if you need help with this. - * Pausing between words/phrases can greatly help make understandable. The pausing is choosen based on English. You should adjust pauses based on what sounds good in speech synthesizers for your language. It is very simple to add, remove, or change the amount of pauses. All pauses are scaled to the current speech rate. + * Pausing between words/phrases can greatly help make speech understandable. The pausing is chosen based on English. You should adjust pauses based on what sounds good in speech synthesizers for your language. It is very simple to add, remove, or change the amount of pauses. All pauses are scaled to the current speech rate. 3. The unicode files (`unicode.yaml` and `unicode-full.yaml`). These contain characters like `<` and `∫`. * You should start with translating `unicode.yaml`. These represent the vast majority of math symbols used. Currently the list is based on experience as to which are the most commonly used Unicode symbols, but I plan to make use of statistics from actual books to refine the list even further. There are about 270 characters to translate in `unicode.yaml`, although ~50 of them are Greek letters (which is hopefully simple). Just like the speech rule files, these files have auto-generated initial translations and the translations should be verified and the `t:` changed to `T:`. @@ -81,15 +81,15 @@ If SRE and MathPlayer agree, or if only one of SRE or MathPlayer has a translati - "!": [t: "factorielle"] # 0x21 (en: 'factorial') ``` -If the MathPlayer and SRE translations disagree, then the translations that agrees with the google translation will be chosen and the other translation included in a comment. For example: +If the MathPlayer and SRE translations disagree, then the translation that agrees with the google translation will be chosen and the other translation included in a comment. For example: ``` else: [t: "parenthèse gauche"] # (en: 'left paren', MathPlayer: 'parenthèse ouvrante') ``` -If none of the translations agree, than one of the translations is picked and the other translations are in comment. For example: +If none of the translations agree, then one of the translations is picked and the other translations are in a comment. For example: ``` else: [t: "parenthèse gauche"] # (en: 'open paren', MathPlayer: 'parenthèse ouvrante', google: 'parenthèse ouverte') ``` -Finally, if there there is no translation, then the google translation is given and is marked with a comment "google translation". There is a significant chance that this is not a good translation so pay special attention to those. Here is an example where there is only a google translation +Finally, if there is no translation, then the google translation is given and is marked with a comment "google translation". There is a significant chance that this is not a good translation so pay special attention to those. Here is an example where there is only a google translation ``` then: [t: "ligne verticale"] # (en: 'vertical line', google translation) ``` @@ -104,7 +104,7 @@ Once you've done some translations and want to try them out, you can do so immed 5. If there is an error (often you won't hear speech), open NVDA's log (in NVDA's "Tools" submenu). The error should be listed there. The error messages are explained below. 6. When you make a change, MathCAT should notice the file is changed and reload it. There is currently a bug that this is not done for files that are `include`d in from a file (e.g., all those in the Shared directory). If you make a change to one of those files, either reload MathCAT (NVDA Tools:Reload Plugins) or restart NVDA. -Translating the settings dialog: this is a separate process from translating the speech. This done by volunteers that do other addon translations also. See [this mailing list](https://groups.io/g/nvda-translations) for more info. +Translating the settings dialog: this is a separate process from translating the speech. This is done by volunteers that do other addon translations also. See [this mailing list](https://groups.io/g/nvda-translations) for more info. ### Automatic tests for your translation Testing is very important! MathCAT is written in Rust and has a large number of automated tests. These tests take advantage of the builtin Rust test system. Hence, to write and verify your own tests, you need to [download and install Rust](https://www.rust-lang.org/tools/install). You do not need to know Rust -- you will simply change some strings from what they are in English to what you think they should be in your language. @@ -163,7 +163,7 @@ These tools will look for untranslated and translated text. If you want support for a new braille language, you probably need to start from scratch unless the language is similar to an existing braille language. You will need to create three `.yaml` files in `Rules\Braille\your-braille-language`. This should mirror the files that are in the other braille directories: 1. xxx_Rules.yaml -- where 'xxx' is the name of your new braille language. These will contain the rules that translate MathML to braille -2. unicode.yaml -- this is a translation of the more common braille characters. Use `Nemeth\unicode.yaml` as a starting point for the the translation. Convert the `t: xxx` into what is appropriate for your language. You likely need to delete some logic or maybe add some of your own for characters that might be represented differently based on context. For example, in Nemeth, a "," is represented differently if it is part of a number. +2. unicode.yaml -- this is a translation of the more common braille characters. Use `Nemeth\unicode.yaml` as a starting point for the translation. Convert the `t: xxx` into what is appropriate for your language. You likely need to delete some logic or maybe add some of your own for characters that might be represented differently based on context. For example, in Nemeth, a "," is represented differently if it is part of a number. 3. unicode-full.yaml -- this is the rest of the character translations. The reason for two separate unicode files is that having a shorter file for the most common characters means startup takes less time. The goal of that file is to capture 99.99% of the characters used. @@ -411,7 +411,7 @@ Note: all YAML files begin with "---". That indicates the beginning of a "docume Note: for "pause", the "auto" value will calculate a pausing amount based on the complexity of the surrounding parts. The more complex they are, the longer the pause (up to a limit). The basic idea is that you want to give the listener time to digest and separate out the two parts when one or both are more complicated. -In addition to having a named rule, the speech rule file supports including other speech rules files. This lets various speech speech rule styles share common features. Inclusion is done via an entry in place of a speech rule: +In addition to having a named rule, the speech rule file supports including other speech rules files. This lets various speech rule styles share common features. Inclusion is done via an entry in place of a speech rule: ``` -include: file_name ``` diff --git a/docs/index.md b/docs/index.md index 8c09fff6..752ce49f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,7 +6,7 @@ is a library that supports conversion of MathML to: * Braille (Nemeth, UEB Technical, and eventually other braille math codes) * Navigation of math (in multiple ways including overviews) -A goal of MathCAT is to be an easy to use library for screen readers and other assistive technology to use to produce high quality speech and/or braille from MathML. It is a follow-on project from MathPlayer (see below) and uses lessons learned from it to do to produce even higher quality speech, navigation, and braille. MathCAT takes advantage of some new ideas the [MathML Working Group](https://mathml-refresh.github.io/charter-drafts/math-2020.html) is developing to allow authors to express their intent when they use a notation. E.g., $(3, 6)$ could be a point in the plane or an open interval, or even a shorthand notation for the greatest common divisor. When that information is conveyed in the MathML, MathCAT will use it to generate more natural sounding speech. +A goal of MathCAT is to be an easy to use library for screen readers and other assistive technology to use to produce high quality speech and/or braille from MathML. It is a follow-on project from MathPlayer (see below) and uses lessons learned from it to produce even higher quality speech, navigation, and braille. MathCAT takes advantage of some new ideas the [MathML Working Group](https://mathml-refresh.github.io/charter-drafts/math-2020.html) is developing to allow authors to express their intent when they use a notation. E.g., $(3, 6)$ could be a point in the plane or an open interval, or even a shorthand notation for the greatest common divisor. When that information is conveyed in the MathML, MathCAT will use it to generate more natural sounding speech. Todo: incorporation of third party libraries to support a common subset of TeX math commands along with ASCIIMath. @@ -214,4 +214,4 @@ For more information about what happened to MathPlayer and how MathCAT came to b All along, I've been pushing to make math work on the web and make it accessible. While at Wolfram Research, I helped get the W3C MathML effort started and have been involved with the working group ever since. I currently chair the W3C Math Working Group. I've been a member on several other committees over the years pushing strongly to make sure they incorporated math accessibility into their standards. Some of the these groups include NIMAS, EPUB, and PDF/UA. -I'm very honored that in 2023, the National Federation of the Blind gave me the $25,000 Jacob Bolotin award. I donated $15,000 of that to the _open collective_ to improve MathML support in browsers. [Click this link for how you can help improve MathML support in browsers](https://opencollective.com/mathml-core-support). \ No newline at end of file +I'm very honored that in 2023, the National Federation of the Blind gave me the $25,000 Jacob Bolotin award. I donated $15,000 of that to the _open collective_ to improve MathML support in browsers. [Click this link for how you can help improve MathML support in browsers](https://opencollective.com/mathml-core-support). diff --git a/docs/nav-commands.md b/docs/nav-commands.md index 55b60b16..8c788e2a 100644 --- a/docs/nav-commands.md +++ b/docs/nav-commands.md @@ -36,7 +36,7 @@ Note: while navigating an expression, "control+c" copies the math content of the - +Cntrl+Shift + +Ctrl+Shift @@ -319,7 +319,7 @@ MathCAT supports three different navigation modes: enhanced, simple, and charact ## Typical Use Typically, you will start at the first term of an expression and move right as needed. -You might move up and down levels if needed. This done with the arrow keys. +You might move up and down levels if needed. This is done with the arrow keys. `alt+ctrl+arrow` is used to move around tabular entries. Backspace will take you back to where you were, which diff --git a/src/braille.rs b/src/braille.rs index f259ca0b..e283b353 100644 --- a/src/braille.rs +++ b/src/braille.rs @@ -1618,7 +1618,7 @@ fn stands_alone(chars: &[char], i: usize) -> (bool, &[char], usize) { } return (is_alone, &chars[i..i+2+n_right_matched], n_letters); - /// chars before before 'L' + /// chars before 'L' fn left_side_stands_alone(chars: &[char]) -> bool { // scan backwards to skip letters and intervening chars // once we hit an intervening char, only intervening chars are allowed if standing alone @@ -2561,7 +2561,7 @@ impl BrailleChars { (None, None) => (), (Some(dot), Some(comma)) => { if comma < dot { - // switch dot/comma -- using "\x01" as a temp when switching the the two chars + // switch dot/comma -- using "\x01" as a temp when switching the two chars let switched = text.replace('.', "\x01").replace(',', ".").replace('\x01', ","); mn_node.set_text(&switched); } diff --git a/src/canonicalize.rs b/src/canonicalize.rs index ba70147b..c6396899 100644 --- a/src/canonicalize.rs +++ b/src/canonicalize.rs @@ -403,7 +403,7 @@ pub fn get_presentation_element(element: Element) -> (usize, Element) { /// 2. normalize the characters /// 3. clean up "bad" MathML based on known output from some converters (TODO: still a work in progress) /// 4. the tree is "parsed" based on the mo (priority)/mi/mn's in an mrow -/// * this adds mrows mrows and some invisible operators (implied times, function app, ...) +/// * this adds mrows and some invisible operators (implied times, function app, ...) /// * extra mrows are removed /// * implicit mrows are turned into explicit mrows (e.g, there will be a single child of 'math') /// @@ -1127,7 +1127,7 @@ impl CanonicalizeContext { i += 1; } } - children = mathml.children(); // 'children' moved above, so need need new values + children = mathml.children(); // 'children' moved above, so need new values } else { // bad mathml such as ' ' -- don't add to new_children i += 1; @@ -1266,7 +1266,7 @@ impl CanonicalizeContext { following.len() == 1 && name(following_child) == "mn" { return true; } - // only want want one "∷" + // only want one "∷" let is_before = is_proportional_before_colon(preceding.iter().rev()); if let Some(is_before) = is_before && !is_before { @@ -1374,7 +1374,7 @@ impl CanonicalizeContext { fn clean_chemistry_leaf(mathml: Element) -> Element { if !(is_chemistry_off(mathml) || mathml.attribute(MAYBE_CHEMISTRY).is_some()) { assert!(name(mathml)=="mi" || name(mathml)=="mtext"); - // this is hack -- VII is more likely to be roman numeral than the molecule V I I so prevent that from happening + // this is a hack -- VII is more likely to be roman numeral than the molecule V I I so prevent that from happening // FIX: come up with a less hacky way to prevent chem element misinterpretation let text = as_text(mathml); if text.len() > 2 && is_roman_number_match(text) { @@ -3410,7 +3410,7 @@ impl CanonicalizeContext { // if there isn't an obvious one, we have parsed the left, but not the right, so discount that // Trig functions have some special syntax - // We need to to treat '-' as prefix for things like "sin -2x" + // We need to treat '-' as prefix for things like "sin -2x" // Need to be careful because (sin - cos)(x) needs an infix '-' // Return either the prefix or infix version of the operator if next_node.is_some() && @@ -3712,7 +3712,7 @@ impl CanonicalizeContext { // Names like "Tr" are likely function names, single letter names like "M" or "J" are iffy // This needs to be after the chemical state check above to rule out Cl(g), etc - // This would be better if if were part of 'likely_names' as "[A-Za-z]+", but reg exprs don't work in HashSets. + // This would be better if it were part of 'likely_names' as "[A-Za-z]+", but reg exprs don't work in HashSets. // FIX: create our own struct and write appropriate traits for it and then it could work let mut chars = base_name.chars(); let first_char = chars.next().unwrap(); // we know there is at least one byte in it, hence one char @@ -4309,7 +4309,7 @@ impl CanonicalizeContext { if !ptr_eq(current_op.op, &ILLEGAL_OPERATOR_INFO) { if current_op.op.is_left_fence() || current_op.op.is_prefix() { if top(&parse_stack).is_operand { - // will end up with operand operand -- need to choose operator associated with prev child + // will end up with duplicate operands -- need to choose operator associated with prev child // we use the original input here because in this case, we need to look to the right of the ()s to deal with chemical states let likely_function_name = self.is_function_name(as_element(children[i_child-1]), Some(&children[i_child..])); let implied_operator = if likely_function_name== FunctionNameCertainty::True { @@ -6701,4 +6701,3 @@ mod canonicalize_tests { } - diff --git a/src/definitions.rs b/src/definitions.rs index 227383c7..ddf9b583 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -6,16 +6,16 @@ //! There is no escaping some implementation details. //! Because these definitions are stored in global variables, the variables need to be protected //! in some way so they can be written at runtime when the files are read. -//! This is done by putting them in side of a lock (`thread_local`). +//! This is done by putting them inside of a lock (`thread_local`). //! -//! Furthermore, it was necessary to use use `RefCell` and `Rc` to deal with interior mutability. +//! Furthermore, it was necessary to use `RefCell` and `Rc` to deal with interior mutability. //! All of this means that a lock needs to be obtained _and_ the contents borrowed to access a definition. //! //! To minimize the global variable footprint, all of the definitions are put inside of a single global variable [`DEFINITIONS`]. //! -//! //! Note: some of the variable are `vec`s and some are `hashset`s. +//! //! Note: some of the variables are `vec`s and some are `hashset`s. //! Numbers are typically vectors so that indexing a digit is easy. -//! Others such a `functions_names` are a hashset because you just want to know if an `mi` is a known name or not. +//! Others such as `functions_names` are a hashset because you just want to know if an `mi` is a known name or not. //! The functions `as_vec` and `as_hashset` should be used on the appropriate variable. //! ## Names //! The names of "variables" in the definition files use camel case (e.g., "FunctionNames"). In the code, to fit with rust @@ -394,4 +394,4 @@ mod tests { assert_eq!(names.get("xxx"), None); }); } -} \ No newline at end of file +} diff --git a/src/navigate.rs b/src/navigate.rs index c7af7de6..9b1761e6 100644 --- a/src/navigate.rs +++ b/src/navigate.rs @@ -491,7 +491,7 @@ pub fn do_navigate_command_string(mathml: Element, nav_command: &'static str) -> }; } // we should always find the start node. - // however, if were were navigating by character, then switched the NavMode, the intent tree might not have that node in it + // however, if we were navigating by character, then switched the NavMode, the intent tree might not have that node in it let start_node = match get_start_node(nav_intent, nav_state) { Ok(node) => node, Err(_) => { diff --git a/src/prefs.rs b/src/prefs.rs index a8c5d681..e2e8d5a5 100644 --- a/src/prefs.rs +++ b/src/prefs.rs @@ -1,7 +1,7 @@ //! Preferences come from either the user or are programmatically set by the AT. -//! The either source can set any preference, but users and AT typically set different preferences. +//! Either source can set any preference, but users and AT typically set different preferences. //! -//! User prefs are read in from a YAML file (prefs.yaml). The can be written by hand. +//! User prefs are read in from a YAML file (prefs.yaml). They can be written by hand. //! In the future, there will hopefully be a nice UI that writes out the YAML file. //! //! AT prefs are set via the API given in the [crate::interface] module. @@ -207,7 +207,7 @@ thread_local!{ /// PreferenceManager keeps track of user and api prefs along with current files /// -/// If one one the `FileAndTime` files changes while the program is running, the values will auto-update +/// If one of the `FileAndTime` files changes while the program is running, the values will auto-update /// Among other things, that means that a UI that changes a user pref will be reflected the next time someone gets speech, braille, etc. // // Note: I experimented with PREF_MANAGER being a Result in the case of no rule files, diff --git a/src/shim_filesystem.rs b/src/shim_filesystem.rs index 1d99bef9..1c6c5491 100644 --- a/src/shim_filesystem.rs +++ b/src/shim_filesystem.rs @@ -34,7 +34,7 @@ cfg_if! { use std::io::Read; use std::collections::{HashMap, HashSet}; thread_local! { - // mapping the file names to whether they are are directory or a file + // mapping the file names to whether they are a directory or a file // Note: these are always stored with "/" as the path separator static DIRECTORIES: RefCell> = RefCell::new(HashSet::with_capacity(127)); // if a file, we note whether it is in ZIPPED_RULE_FILES or the index of a zipped file within ZIPPED_RULE_FILES diff --git a/src/speech.rs b/src/speech.rs index 4c7832d1..fb985a7d 100644 --- a/src/speech.rs +++ b/src/speech.rs @@ -2042,7 +2042,7 @@ impl FilesAndTimes { } - // check the time stamp on the included files -- if the head file hasn't changed, the the paths for the included files will the same + // check the time stamp on the included files -- if the head file hasn't changed, the paths for the included files will be the same for file in &self.ft { if !file.is_up_to_date() { return false; @@ -2933,4 +2933,4 @@ cfg_if::cfg_if! {if #[cfg(not(feature = "include-zip"))] { // assert_eq!(result.unwrap(), r#"DEBUG(*[2]/*[3][DEBUG(text()='(')], "DEBUG(*[2]/*[3][DEBUG(text()='(')], \"text()='(')]\")"#); // } -} \ No newline at end of file +}