├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── Pip Install Dependencies.bat ├── README.md ├── SwitchHere.bat ├── _mathfly_main.py ├── install.bat ├── mathfly ├── __init__.py ├── apps │ ├── __init__.py │ ├── app_template.py │ ├── sublime.py │ ├── sumatrapdf.py │ └── wordpad.py ├── ccr │ ├── LyX.py │ ├── ScientificNotebook55.py │ ├── __init__.py │ ├── alias.py │ ├── core.py │ ├── latex.py │ └── latex_maths.py ├── config │ ├── ScientificNotebook55.toml │ ├── bin │ │ └── reboot.bat │ ├── core.toml │ ├── latex.toml │ ├── lyx.toml │ └── settings.toml ├── docs │ ├── Core.pdf │ ├── LaTeX.pdf │ ├── LyX.pdf │ ├── Scientific_Notebook.pdf │ └── source │ │ ├── Apps.md │ │ ├── Core.tex │ │ ├── LaTeX.tex │ │ ├── LyX.tex │ │ └── Scientific_Notebook.tex ├── imports.py └── lib │ ├── __init__.py │ ├── actions.py │ ├── control.py │ ├── ctrl │ ├── __init__.py │ └── nexus.py │ ├── execution.py │ ├── integers.py │ ├── latex │ ├── __init__.py │ ├── bibtexer.py │ ├── book_citation_generator.py │ └── tex_funcs.py │ ├── merge │ ├── __init__.py │ ├── ccrmerger.py │ ├── mergepair.py │ ├── mergerule.py │ ├── nestedrule.py │ └── selfmodrule.py │ ├── navigation.py │ └── utilities.py └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore junk 2 | **/ccr.toml 3 | **/aliases.toml 4 | mathfly/docs/source/*.pdf 5 | .idea/ 6 | *.pyc 7 | *.wav 8 | *.class 9 | *.aux 10 | *.run.xml 11 | *.bcf 12 | *.html 13 | *.toc 14 | *.synctex.gz 15 | test.py 16 | log.txt 17 | complexity_report* 18 | *.log 19 | *.*\# 20 | *.*~ 21 | .cache/ 22 | _*.py 23 | !_mathfly_main.py 24 | VirtualDesktopAccessor.dll -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [v1.0](https://github.com/mrob95/mathfly/tree/v1.0) (2019-04-07) 4 | **Merged pull requests:** 5 | 6 | - Delete certain words from the active vocabulary on start-up [\#7](https://github.com/mrob95/mathfly/pull/7) ([mrob95](https://github.com/mrob95)) 7 | - Add self referencing rules WIP [\#6](https://github.com/mrob95/mathfly/pull/6) ([mrob95](https://github.com/mrob95)) 8 | - Fix integer bug [\#5](https://github.com/mrob95/mathfly/pull/5) ([mrob95](https://github.com/mrob95)) 9 | - Switch to using contexts instead of manually enabling and disabling grammars [\#4](https://github.com/mrob95/mathfly/pull/4) ([mrob95](https://github.com/mrob95)) 10 | - Added numbered formula for lyx. [\#2](https://github.com/mrob95/mathfly/pull/2) ([alexboche](https://github.com/alexboche)) 11 | 12 | 13 | 14 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* -------------------------------------------------------------------------------- /Pip Install Dependencies.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Installing: dragonfly2, wxPython, pillow 3 | 4 | cd c:\python27\scripts 5 | pip install --upgrade pip 6 | pip install -U wxpython 7 | pip install -U pywin32 8 | pip install -U setuptools 9 | pip install -U future 10 | pip install -U dragonfly2 11 | pip install -U toml 12 | pip install -U beautifulsoup4 13 | pip install -U six 14 | 15 | echo ------------------------------------------ 16 | echo Mathfly Dependencies Installation Complete 17 | echo ------------------------------------------ 18 | 19 | pause -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *21/02/2021 Note: this page refers to an old version of mathfly. Talon can do everything that mathfly could and more. See the [mathfly-talon repository](https://github.com/mrob95/mathfly-talon) and [mathfly website](https://mathfly.org) for details.* 2 | 3 | # Mathfly 4 | A free, open source utility for dictating mathematical notation and LaTeX quickly and easily using [Dragon Professional Individual](https://www.nuance.com/en-gb/dragon/business-solutions/dragon-professional-individual.html). Currently supports the free, open source LyX document processor and Scientific Notebook 5.5 (allowing for drop-in replacement of MathTalk). Based on Natlink, dragonfly and Caster. With thanks to Alex Boche and David Conway. 5 | 6 | * [mathfly.org](https://mathfly.org) 7 | * [Gitter channel](https://gitter.im/mathfly-dictation/community) - [![Join the chat at https://gitter.im/mathfly-dictation/community](https://badges.gitter.im/mathfly-dictation/community.svg)](https://gitter.im/mathfly-dictation/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8 | * Contact: mike@mikeroberts.xyz 9 | * [Installation instructions](https://mathfly.org/installation.html) 10 | * [Implementation details](https://mathfly.org/implementation.html) 11 | * [Change log](CHANGELOG.md) 12 | * For complete lists of the commands which Mathfly provides, read the [Core](mathfly/docs/Core.pdf), [LyX](mathfly/docs/LyX.pdf), [Scientific Notebook 5.5](mathfly/docs/Scientific_Notebook.pdf) and [LaTeX](mathfly/docs/LaTeX.pdf) documentation. 13 | 14 | ## Quick 15 | Mathfly interprets dictated commands on-the-fly quickly and continuously, making it far faster than other systems. As fast as you can speak, Mathfly can interpret. 16 | 17 | While I have no data comparing dictation speed with normal writing speed, I will say that I have been using versions of this software to do exams throughout my economics undergraduate degree, and have never needed extra time or struggled to finish. Video demonstration: 18 | 19 | [![Brief demonstration](http://img.youtube.com/vi/7eZ6fMztvwA/0.jpg)](https://www.youtube.com/watch?v=7eZ6fMztvwA) 20 | 21 | ## Infinitely modifiable 22 | The vast majority of Mathfly's commands are contained in plaintext config files in `mathfly/config/`, designed to be easy to edit and extend. If you need a new command, it's as simple as adding one line of plaintext. If you keep getting a command wrong, you can change it. If there are commands you don't need, you can delete them. 23 | 24 | [![modification demonstration](http://img.youtube.com/vi/vLwu9SWK030/0.jpg)](https://youtu.be/vLwu9SWK030) 25 | 26 | For an even easier way of adding new commands, "alias" turns highlighted text into a new command. 27 | 28 | [![alias demonstration](http://img.youtube.com/vi/mZ-Y8O5RrUY/0.jpg)](https://www.youtube.com/watch?v=mZ-Y8O5RrUY) 29 | 30 | ## LaTeX 31 | Mathfly also contains a module for dictating into LaTeX documents, with commands for inserting objects, beginning and ending environments, reproducing premade templates, and crawling the web for references, all with simple voice commands. For a full list of commands, read the [LaTeX](mathfly/docs/LaTeX.pdf) documentation. 32 | 33 | [![LaTeX demonstration](http://img.youtube.com/vi/N9OzgJFP8tM/0.jpg)](https://youtu.be/N9OzgJFP8tM) 34 | -------------------------------------------------------------------------------- /SwitchHere.bat: -------------------------------------------------------------------------------- 1 | set currentpath=%~dp0 2 | cd C:\Python27 3 | python C:\NatLink\NatLink\confignatlinkvocolaunimacro\natlinkconfigfunctions.py -n "%currentpath:~0,-1%" -------------------------------------------------------------------------------- /_mathfly_main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | logging.basicConfig() 3 | 4 | from dragonfly import (Function, Grammar, Text, Dictation, Choice, Pause) 5 | 6 | import os, sys 7 | import natlink 8 | 9 | from mathfly.lib import control, utilities 10 | from mathfly.lib.merge.mergerule import MergeRule 11 | from mathfly.lib.merge.mergepair import MergeInf 12 | 13 | BASE_PATH = os.path.realpath(__file__).split("\\_mathfly_main.py")[0].replace("\\", "/") 14 | sys.path.append(BASE_PATH) 15 | 16 | CORE = utilities.load_toml_relative("config/core.toml") 17 | 18 | MF_NEXUS = control.nexus() 19 | MF_NEXUS.build(True) 20 | 21 | class MainRule(MergeRule): 22 | 23 | mapping = { 24 | "configure math fly [settings]": 25 | Function(utilities.load_config, config_name="settings.toml"), 26 | 27 | " ": Function(MF_NEXUS.rule_changer), 28 | 29 | "reboot dragon": Function(utilities.reboot), 30 | 31 | "rebuild math fly": Function(MF_NEXUS.build), 32 | 33 | "math fly help": Function(utilities.help), 34 | } 35 | extras=[ 36 | MF_NEXUS.generate_ccr_choices("name"), 37 | Choice("enable", { 38 | "enable": True, 39 | "disable": False 40 | }), 41 | ] 42 | 43 | grammar = Grammar('general') 44 | main_rule = MainRule() 45 | grammar.add_rule(main_rule) 46 | grammar.load() -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | set currentpath=%~dp0 2 | echo Installation path: %currentpath% 3 | 4 | cd C:\Python27 5 | 6 | echo Installing dependencies 7 | python -m pip install -r "%currentpath%requirements.txt" 8 | 9 | echo Activating natlink 10 | python C:\NatLink\NatLink\confignatlinkvocolaunimacro\natlinkconfigfunctions.py -e 11 | 12 | echo Setting natlink user directory 13 | python C:\NatLink\NatLink\confignatlinkvocolaunimacro\natlinkconfigfunctions.py -n "%currentpath:~0,-1%" 14 | 15 | echo Installed at %currentpath% 16 | 17 | pause 1 18 | -------------------------------------------------------------------------------- /mathfly/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirober/mathfly/c172f853514505045665290728e84e4e6bc796dd/mathfly/__init__.py -------------------------------------------------------------------------------- /mathfly/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirober/mathfly/c172f853514505045665290728e84e4e6bc796dd/mathfly/apps/__init__.py -------------------------------------------------------------------------------- /mathfly/apps/app_template.py: -------------------------------------------------------------------------------- 1 | from mathfly.imports import * 2 | 3 | class RuleNameRule(MergeRule): 4 | pronunciation = "AppName" 5 | mcontext = AppContext(title="AppName") 6 | 7 | mapping = { 8 | "new file" : Key("c-n"), 9 | "open file" : Key("c-o"), 10 | "print file" : Key("c-p"), 11 | 12 | "close tab" : Key("c-w"), 13 | "next tab" : Key("c-tab"), 14 | "previous tab" : Key("cs-tab"), 15 | " tab" : Key("a-%(nth)s"), 16 | 17 | "find" : Key("c-f"), 18 | "find next" : Key("f3"), 19 | "find previous" : Key("s-f3"), 20 | 21 | "zoom in" : Key("c-equals"), 22 | "zoom out" : Key("c-minus"), 23 | } 24 | 25 | extras = [ 26 | IntegerRef("n", 1, 1000), 27 | Choice("nth", { 28 | "first" : "1", 29 | "second" : "2", 30 | "third" : "3", 31 | "fourth" : "4", 32 | "fifth" : "5", 33 | "sixth" : "6", 34 | "seventh" : "7", 35 | "eighth" : "8", 36 | "(last | final)": "9", 37 | }) 38 | ] 39 | 40 | defaults = { 41 | "n": 1, 42 | } 43 | 44 | control.nexus().merger.add_non_ccr_app_rule(RuleNameRule()) 45 | -------------------------------------------------------------------------------- /mathfly/apps/sublime.py: -------------------------------------------------------------------------------- 1 | from mathfly.imports import * 2 | 3 | class SublimeRule(MergeRule): 4 | pronunciation = "sublime" 5 | mcontext = AppContext(executable="sublime_text", title="Sublime Text") 6 | 7 | mapping = { 8 | "new (file | pane)": Key("c-n"), 9 | # {"keys": ["ctrl+alt+n"], "command": "new_window"}, 10 | "new window": Key("ca-n"), 11 | "open file": Key("c-o"), 12 | # {"keys": ["ctrl+shift+o"], "command": "prompt_add_folder"}, 13 | "open folder": Key("cs-o"), 14 | "save as": Key("cs-s"), 15 | # 16 | "comment line": Key("c-slash"), 17 | "comment (block | lines)": Key("cs-slash"), 18 | "outdent lines": Key("c-lbracket"), 19 | "join lines []": Key("c-j"), 20 | "match bracket": Key("c-m"), 21 | # 22 | # "(select | sell) all": Key("c-a"), 23 | "(select | sell) scope []": Key("cs-space"), 24 | "(select | sell) brackets []": Key("cs-m"), 25 | "(select | sell) line []": Key("c-l"), 26 | "(select | sell) indent": Key("cs-j"), 27 | # {"keys": ["ctrl+alt+p"], "command": "expand_selection_to_paragraph"}, 28 | "(select | sell) paragraph": Key("ca-p"), 29 | # SelectUntil 30 | "(select | sell) until": Key("as-s"), 31 | 32 | "toggle side bar": Key("c-k, c-b"), 33 | 34 | # 35 | "find": Key("c-f"), 36 | "get all": Key("a-enter"), 37 | "replace": Key("c-h"), 38 | "edit lines": Key("cs-l"), 39 | "edit next []": Key("c-d"), 40 | "edit skip next []": Key("c-k, c-d"), 41 | "edit all": Key("c-d, a-f3"), 42 | # 43 | "transform upper": Key("c-k, c-u"), 44 | "transform lower": Key("c-k, c-l"), 45 | # {"keys": ["ctrl+k", "ctrl+t"], "command": "title_case"}, 46 | "transform title": Key("c-k, c-t"), 47 | # 48 | "line []": Key("c-g") + Text("%(n11)s" + "%(n12)s") + Key("enter"), 49 | "go to file": Key("c-p"), 50 | "go to word": Key("c-semicolon"), 51 | "go to symbol": Key("c-r"), 52 | "go to [symbol in] project": Key("cs-r"), 53 | "command pallette": Key("cs-p"), 54 | "(find | search) in (project | folder | directory)": Key("cs-f"), 55 | # 56 | "fold": Key("cs-lbracket"), 57 | "unfold": Key("cs-rbracket"), 58 | "unfold all": Key("c-k, c-j"), 59 | "fold [level] ": Key("c-k, c-%(n2)s"), 60 | # 61 | "full screen": Key("f11"), 62 | "(set | add) bookmark": Key("c-f2"), 63 | "next bookmark": Key("f2"), 64 | "previous bookmark": Key("s-f2"), 65 | "clear bookmarks": Key("cs-f2"), 66 | # 67 | "build it": Key("c-b"), 68 | # "cancel build": Key("c-break")), 69 | # 70 | "record macro": Key("c-q"), 71 | "play [back] macro []": Key("cs-q"), 72 | "(new | create) snippet": Key("a-n"), 73 | # 74 | "close tab": Key("c-w"), 75 | "next tab": Key("c-pgdown"), 76 | "previous tab": Key("c-pgup"), 77 | " tab": Key("a-%(n2)s"), 78 | # 79 | "column ": Key("as-%(cols)s"), 80 | "focus ": Key("c-%(panel)s"), 81 | "move ": Key("cs-%(panel)s"), 82 | # {"keys": ["ctrl+alt+v"], "command": "clone_file"} 83 | "split right": Key("as-2, c-1, ca-v, cs-2"), 84 | # 85 | "open terminal": Key("cs-t"), 86 | 87 | "zoom in []": Key("c-equal")*Repeat(extra="n2"), 88 | "zoom out []": Key("c-minus")*Repeat(extra="n2"), 89 | 90 | } 91 | extras = [ 92 | IntegerRef("n11", 1, 100), 93 | IntegerRef("n12", 0, 100), 94 | IntegerRef("n2", 1, 9), 95 | IntegerRef("n3", 1, 21), 96 | Choice("nth", { 97 | "first": "1", 98 | "second": "2", 99 | "third": "3", 100 | "fourth": "4", 101 | "fifth": "5", 102 | "sixth": "6", 103 | "seventh": "7", 104 | "eighth": "8", 105 | "ninth": "9", 106 | "tenth": "10", 107 | }), 108 | Choice("cols", { 109 | "one": "1", 110 | "two": "2", 111 | "three": "3", 112 | "grid": "5", 113 | }), 114 | Choice("panel", { 115 | "one": "1", 116 | "left": "1", 117 | "two": "2", 118 | "right": "2", 119 | }), 120 | ] 121 | defaults = { 122 | "n12": "", 123 | "n2": 1, 124 | "n3": 1, 125 | } 126 | 127 | 128 | #--------------------------------------------------------------------------- 129 | 130 | control.nexus().merger.add_non_ccr_app_rule(SublimeRule()) -------------------------------------------------------------------------------- /mathfly/apps/sumatrapdf.py: -------------------------------------------------------------------------------- 1 | from mathfly.imports import * 2 | 3 | class SumatraPDFRule(MergeRule): 4 | pronunciation = "SumatraPDF" 5 | mcontext = AppContext(title="SumatraPDF") 6 | 7 | mapping = { 8 | # https://www.sumatrapdfreader.org/manual.html 9 | "open file" : Key("c-o"), 10 | "print file" : Key("c-p"), 11 | 12 | "close tab" : Key("c-w"), 13 | "next tab" : Key("c-tab"), 14 | "previous tab" : Key("cs-tab"), 15 | " tab" : Key("a-%(nth)s"), 16 | 17 | "go to page" : Key("c-g"), 18 | "find" : Key("c-f"), 19 | "find next" : Key("f3"), 20 | "find previous" : Key("s-f3"), 21 | "page " : Key("c-g") + Text("%(n)s") + Key("enter"), 22 | "table of contents" : Key("f12"), 23 | 24 | "zoom in" : Key("c-equals"), 25 | "zoom out" : Key("c-minus"), 26 | "fit page" : Key("c-0"), 27 | "actual size" : Key("c-1"), 28 | "fit width" : Key("c-2"), 29 | "fit content" : Key("c-3"), 30 | "[view] single page" : Key("c-6"), 31 | "facing view" : Key("c-7"), 32 | "book view" : Key("c-8"), 33 | "rotate [right]" : Key("c-plus"), 34 | "rotate left" : Key("c-minus"), 35 | "presentation [mode]" : Key("f11"), 36 | "full screen" : Key("s-f11"), 37 | } 38 | 39 | extras = [ 40 | IntegerRef("n", 1, 1000), 41 | Choice("nth", { 42 | "first" : "1", 43 | "second" : "2", 44 | "third" : "3", 45 | "fourth" : "4", 46 | "fifth" : "5", 47 | "sixth" : "6", 48 | "seventh" : "7", 49 | "eighth" : "8", 50 | "(last | final)": "9", 51 | }) 52 | ] 53 | 54 | defaults = { 55 | "n": 1, 56 | } 57 | 58 | control.nexus().merger.add_non_ccr_app_rule(SumatraPDFRule()) 59 | -------------------------------------------------------------------------------- /mathfly/apps/wordpad.py: -------------------------------------------------------------------------------- 1 | from mathfly.imports import * 2 | 3 | class WordPadRule(MergeRule): 4 | pronunciation = "WordPad" 5 | mcontext = AppContext(title="WordPad") 6 | 7 | mapping = { 8 | "new file" : Key("c-n"), 9 | "open file" : Key("c-o"), 10 | "print file" : Key("c-p"), 11 | 12 | "page down []" : Key("c-pagedown:%(n)s"), 13 | "page up []" : Key("c-pageup:%(n)s"), 14 | } 15 | 16 | extras = [ 17 | IntegerRef("n", 1, 1000), 18 | ] 19 | 20 | defaults = { 21 | "n": 1, 22 | } 23 | 24 | control.nexus().merger.add_non_ccr_app_rule(WordPadRule()) 25 | -------------------------------------------------------------------------------- /mathfly/ccr/LyX.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created Jan 2019 3 | 4 | @author: Mike Roberts, Alex Boche 5 | ''' 6 | from mathfly.imports import * 7 | 8 | BINDINGS = utilities.load_toml_relative("config/lyx.toml") 9 | CORE = utilities.load_toml_relative("config/core.toml") 10 | 11 | def greek(big, greek_letter): 12 | if big: 13 | greek_letter = greek_letter.title() 14 | Text("\\" + greek_letter + " ").execute() 15 | 16 | def matrix(rows, cols): 17 | Text("\\" + BINDINGS["matrix_style"] + " ").execute() 18 | Key("a-m, w, i, "*(rows-1) + "a-m, c, i, "*(cols-1)).execute() 19 | 20 | class lyx_nested(NestedRule): 21 | mapping = { 22 | "[] integral from to ": 23 | [Text("\\int _"), Key("right, caret"), Key("right")], 24 | 25 | "[] definite from to ": 26 | [Key("a-m, lbracket, right, underscore"), 27 | Key("right, caret"), Key("right, left:2")], 28 | 29 | "[] differential by ": 30 | [Key("a-m, f, d"), Key("down, d"), Key("right")], 31 | 32 | "[] sum from to ": 33 | [Text("\\stackrelthree ") + Key("down") + Text("\\sum ") + Key("down"), 34 | Key("up:2"), Key("right")], 35 | 36 | "[] limit from to ": 37 | [Text("\\underset \\lim ") + Key("down"), 38 | Text("\\rightarrow "), Key("right")], 39 | 40 | "[] argument that ": 41 | [Text("\\underset \\arg \\%(minmax)s ") + Key("down"), 42 | Key("right"), None], 43 | 44 | "[] by ": 45 | [Text("\\underset \\%(minmax)s ") + Key("down"), 46 | Key("right"), None], 47 | 48 | "[] []": 49 | [Key("%(script1)s"), Key("right"), None], 50 | 51 | "[] []": 52 | [Key("%(script1)s"), Key("right, %(script2)s"), Key("right")], 53 | } 54 | extras = [ 55 | Choice("minmax", { 56 | "(minimum | minimises)": "min", 57 | "(maximum | maximises)": "max", 58 | }), 59 | Choice("script1", { 60 | "sub": "_", 61 | "super": "^", 62 | }), 63 | Choice("script2", { 64 | "sub": "_", 65 | "super": "^", 66 | }), 67 | ] 68 | 69 | class lyx_mathematicsNon(MergeRule): 70 | mapping = { 71 | "": 72 | Key("%(control)s"), 73 | " []": 74 | Key("%(control_repeat)s")*Repeat(extra="n"), 75 | } 76 | extras = [ 77 | IntegerRef("n", 1, 10), 78 | Choice("control", BINDINGS["control"]), 79 | Choice("control_repeat", BINDINGS["control_repeat"]), 80 | ] 81 | defaults = { 82 | "n": 1, 83 | } 84 | 85 | class lyx_mathematics(MergeRule): 86 | non = lyx_mathematicsNon 87 | nested = lyx_nested 88 | mwith = CORE["pronunciation"] 89 | mcontext = AppContext(executable="lyx") 90 | pronunciation = BINDINGS["pronunciation"] 91 | 92 | mapping = { 93 | BINDINGS["symbol1_prefix"] + " ": 94 | Text("\\%(symbol1)s "), 95 | 96 | BINDINGS["symbol2_prefix"] + " ": 97 | Text("\\%(symbol2)s "), 98 | 99 | BINDINGS["accent_prefix"] + " ": 100 | Key("a-m, %(accent)s"), 101 | 102 | BINDINGS["text_prefix"] + " ": 103 | Text("\\%(text_modes)s "), 104 | 105 | BINDINGS["greek_prefix"] + " [] ": 106 | Function(greek), 107 | 108 | "": 109 | Key("%(misc_lyx_keys)s"), 110 | 111 | "": 112 | Alternating("command"), 113 | 114 | "matrix by ": 115 | Function(matrix), 116 | 117 | " ": 118 | Key("a-m, f") + Text("%(numbers)s") + Key("down") + Text("%(denominator)s") + Key("right"), 119 | 120 | } 121 | 122 | extras = [ 123 | IntegerRef("rows", 1, BINDINGS["max_matrix_size"]), 124 | IntegerRef("cols", 1, BINDINGS["max_matrix_size"]), 125 | IntegerRef("numbers", 0, CORE["numbers_max"]), 126 | Choice("big", {CORE["capitals_prefix"]: True}), 127 | Choice("greek_letter", BINDINGS["greek_letters"]), 128 | Choice("symbol1", BINDINGS["tex_symbols1"]), 129 | Choice("symbol2", BINDINGS["tex_symbols2"]), 130 | Choice("accent", BINDINGS["accents"]), 131 | Choice("text_modes", BINDINGS["text_modes"]), 132 | Choice("misc_lyx_keys", BINDINGS["misc_lyx_keys"]), 133 | Choice("command", BINDINGS["misc_lyx_commands"]), 134 | Choice("denominator", BINDINGS["denominators"]), 135 | ] 136 | 137 | defaults = { 138 | "big": False, 139 | } 140 | 141 | control.nexus().merger.add_app_rule(lyx_mathematics()) 142 | -------------------------------------------------------------------------------- /mathfly/ccr/ScientificNotebook55.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Sep 4, 2018 3 | 4 | @author: Mike Roberts 5 | ''' 6 | from mathfly.imports import * 7 | 8 | BINDINGS = utilities.load_toml_relative("config/ScientificNotebook55.toml") 9 | CORE = utilities.load_toml_relative("config/core.toml") 10 | 11 | #--------------------------------------------------------------------------- 12 | 13 | def texchar(symbol): 14 | keychain = "ctrl:down, " 15 | for character in symbol: 16 | keychain = keychain + character + ", " 17 | keychain=keychain + "ctrl:up" 18 | Key(keychain).execute() 19 | 20 | def greek(big, greek_letter): 21 | if big: 22 | greek_letter = greek_letter.upper() 23 | Key("c-g, " + greek_letter).execute() 24 | 25 | def matrix(rows, cols): 26 | Key("f10/5, i/5, down:8, enter/50").execute() 27 | Key(str(rows) + "/50, tab, " + str(cols) + "/50, enter").execute() 28 | 29 | class sn_nested(NestedRule): 30 | mapping = { 31 | "[] integral from to ": 32 | [Function(lambda: texchar("int")) + Key("c-l"), 33 | Key("right, c-h"), Key("right")], 34 | 35 | "[] definite from to ": 36 | [Key("c-6, right, c-l"), 37 | Key("right, c-h"), Key("right, c-left, left")], 38 | 39 | "[] differential by ": 40 | [Key("c-f, d"), Key("down, d"), Key("right")], 41 | 42 | "[] sum from to ": 43 | [Key("f10, i, down:11, enter/25, a, enter, f10, i, down:11, enter/25, b, enter") + Function(lambda: texchar("sum")) + Key("down"), 44 | Key("up:2"), Key("right")], 45 | 46 | "[] limit from to ": 47 | [Key("f10, i, down:11, enter/25, b, enter") + Function(lambda: texchar("lim")) + Key("down"), 48 | Function(lambda: texchar("rightarrow")), 49 | Key("right")], 50 | 51 | "[] argument that ": 52 | [Key("f10, i, down:11, enter/25, b, enter") + Text("arg%(minmax)s") + Key("down"), 53 | Key("right"), None], 54 | 55 | "[] by ": 56 | [Key("f10, i, down:11, enter/25, b, enter") + Text("%(minmax)s") + Key("down"), 57 | Key("right"), None], 58 | 59 | "[] []": 60 | [Key("%(script1)s"), Key("right"), None], 61 | 62 | "[] []": 63 | [Key("%(script1)s"), Key("right, %(script2)s"), Key("right")], 64 | 65 | } 66 | extras = [ 67 | Choice("minmax", { 68 | "(minimum | minimises)": "min", 69 | "(maximum | maximises)": "max", 70 | }), 71 | Choice("script1", { 72 | "sub": "c-l", 73 | "super": "c-h", 74 | }), 75 | Choice("script2", { 76 | "sub": "c-l", 77 | "super": "c-h", 78 | }), 79 | ] 80 | 81 | class sn_mathematicsNon(MergeRule): 82 | mapping = { 83 | "text ": 84 | Key("c-t") + Function(lambda dict: Text(str(dict).capitalize()).execute()), 85 | "": 86 | Key("%(control)s"), 87 | } 88 | extras = [ 89 | Dictation("dict"), 90 | IntegerRef("n", 1, 10), 91 | Choice("control", BINDINGS["control"]), 92 | ] 93 | 94 | 95 | class sn_mathematics(MergeRule): 96 | non = sn_mathematicsNon 97 | mwith = CORE["pronunciation"] 98 | mcontext = AppContext(executable="scientific notebook") 99 | pronunciation = BINDINGS["pronunciation"] 100 | 101 | nested = sn_nested 102 | 103 | mapping = { 104 | BINDINGS["symbol_prefix"] + " ": 105 | Function(texchar), 106 | # 107 | BINDINGS["greek_prefix"] + " [] ": 108 | Function(greek), 109 | BINDINGS["accent_prefix"] + " ": 110 | Key("%(accent)s"), 111 | 112 | BINDINGS["unit_prefix"] + " ": 113 | Alternating("units"), 114 | 115 | "": 116 | Key("%(misc_sn_keys)s"), 117 | "": 118 | Text("%(misc_sn_text)s"), 119 | 120 | "matrix by ": 121 | Function(matrix), 122 | 123 | " ": 124 | Key("c-f") + Text("%(numbers)s") + Key("down") + Text("%(denominator)s") + Key("right"), 125 | } 126 | 127 | extras = [ 128 | IntegerRef("rows", 1, BINDINGS["max_matrix_size"]), 129 | IntegerRef("cols", 1, BINDINGS["max_matrix_size"]), 130 | IntegerRef("numbers", 0, CORE["numbers_max"]), 131 | Choice("big", {CORE["capitals_prefix"]: True}), 132 | Choice("greek_letter", BINDINGS["greek_letters"]), 133 | Choice("units", BINDINGS["units"]), 134 | Choice("symbol", BINDINGS["tex_symbols"]), 135 | Choice("accent", BINDINGS["accents"]), 136 | Choice("misc_sn_keys", BINDINGS["misc_sn_keys"]), 137 | Choice("misc_sn_text", BINDINGS["misc_sn_text"]), 138 | Choice("denominator", BINDINGS["denominators"]), 139 | ] 140 | 141 | defaults = { 142 | "big": False, 143 | } 144 | 145 | control.nexus().merger.add_app_rule(sn_mathematics()) 146 | -------------------------------------------------------------------------------- /mathfly/ccr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirober/mathfly/c172f853514505045665290728e84e4e6bc796dd/mathfly/ccr/__init__.py -------------------------------------------------------------------------------- /mathfly/ccr/alias.py: -------------------------------------------------------------------------------- 1 | from mathfly.imports import * 2 | 3 | MF_NEXUS = control.nexus() 4 | 5 | class Alias(SelfModifyingRule): 6 | mapping = {"default command": ""} 7 | key = "aliases" 8 | pronunciation = "alias" 9 | 10 | def delete_all(self, key): 11 | utilities.save_toml_relative({}, "config/aliases.toml") 12 | self.refresh() 13 | 14 | def alias(self, spec): 15 | spec = str(spec) 16 | e, text = utilities.read_selected(True) 17 | if spec and text: 18 | self.refresh(spec, str(text)) 19 | 20 | def refresh(self, *args): 21 | '''args: spec, text''' 22 | aliases = utilities.load_toml_relative("config/aliases.toml") 23 | if not Alias.key in aliases: 24 | aliases[Alias.key] = {} 25 | if len(args) > 0: 26 | aliases[Alias.key][args[0]] = args[1] 27 | utilities.save_toml_relative(aliases, "config/aliases.toml") 28 | mapping = {} 29 | for spec in aliases[Alias.key]: 30 | mapping[spec] = Function(utilities.paste_string, 31 | content=str(aliases[Alias.key][spec])) 32 | mapping["alias "] = Function(lambda s: self.alias(s)) 33 | mapping["delete aliases"] = Function(self.delete_all, key=Alias.key) 34 | self.reset(mapping) 35 | 36 | control.nexus().merger.add_selfmodrule(Alias()) 37 | -------------------------------------------------------------------------------- /mathfly/ccr/core.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Sep 4, 2018 3 | 4 | @author: Mike Roberts 5 | ''' 6 | from mathfly.imports import * 7 | 8 | SETTINGS = utilities.load_toml_relative("config/settings.toml") 9 | CORE = utilities.load_toml_relative("config/core.toml") 10 | 11 | _LETTERS, _DIRECTIONS = "letters", "directions" 12 | if SETTINGS["alternative_letters"]: 13 | _LETTERS += "_alt" 14 | if SETTINGS["alternative_directions"]: 15 | _DIRECTIONS += "_alt" 16 | 17 | def alphabet(big, letter): 18 | if big: 19 | letter = letter.upper() 20 | Key(letter).execute() 21 | 22 | class coreNon(MergeRule): 23 | mapping = { 24 | "configure " + CORE["pronunciation"]: 25 | Function(utilities.load_config, config_name="core.toml"), 26 | "configure scientific notebook": 27 | Function(utilities.load_config, config_name="ScientificNotebook55.toml"), 28 | "configure (LyX | licks)": 29 | Function(utilities.load_config, config_name="lyx.toml"), 30 | 31 | " []": 32 | Key("%(noCCR_repeatable_key)s")*Repeat(extra="n"), 33 | "": 34 | Key("%(noCCR_non_repeatable_key)s"), 35 | } 36 | extras = [ 37 | IntegerRef("n", 1, 10), 38 | Choice("noCCR_repeatable_key", CORE["noCCR_repeatable_keys"]), 39 | Choice("noCCR_non_repeatable_key", CORE["noCCR_non_repeatable_keys"]), 40 | ] 41 | defaults = { 42 | "n": 1, 43 | } 44 | 45 | class core(MergeRule): 46 | non = coreNon 47 | 48 | pronunciation = CORE["pronunciation"] 49 | 50 | mapping = { 51 | "[] ": 52 | Function(alphabet), 53 | CORE["numbers_prefix"] + " ": 54 | Text("%(numbers)s"), 55 | "": 56 | Key("%(punctuation)s"), 57 | 58 | "( | []) [( | )]": 59 | Function(navigation.text_nav), 60 | " []": 61 | Key("%(repeatable_key)s")*Repeat(extra="n"), 62 | "": 63 | Key("%(non_repeatable_key)s"), 64 | 65 | CORE["dictation_prefix"] + " ": 66 | Function(lambda text: Text(str(text).lower()).execute()), 67 | 68 | "shift click": 69 | Key("shift:down") + Mouse("left") + Key("shift:up"), 70 | } 71 | 72 | extras = [ 73 | Dictation("text"), 74 | IntegerRef("n", 1, 10), 75 | IntegerRef("n50", 1, 50), 76 | IntegerRefMF("numbers", 0, CORE["numbers_max"]), 77 | Choice("big", {CORE["capitals_prefix"]: True}), 78 | Choice("letter", CORE[_LETTERS]), 79 | Choice("punctuation", CORE["punctuation"]), 80 | Choice("repeatable_key", CORE["repeatable_keys"]), 81 | Choice("non_repeatable_key", CORE["non_repeatable_keys"]), 82 | Choice("direction", CORE[_DIRECTIONS]), 83 | Choice("modifier", CORE["modifiers"]), 84 | Choice("extreme", {CORE["extreme"]: True}), 85 | ] 86 | 87 | defaults = { 88 | "big" : False, 89 | "extreme" : False, 90 | "n" : 1, 91 | "n50" : 1, 92 | "direction": "left", 93 | "modifier" : "", 94 | } 95 | 96 | 97 | control.nexus().merger.add_global_rule(core()) -------------------------------------------------------------------------------- /mathfly/ccr/latex.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Sep 4, 2018 3 | @author: Mike Roberts 4 | ''' 5 | from mathfly.imports import * 6 | 7 | BINDINGS = utilities.load_toml_relative("config/latex.toml") 8 | CORE = utilities.load_toml_relative("config/core.toml") 9 | 10 | class LaTeXNon(MergeRule): 11 | mapping = { 12 | "configure " + BINDINGS["pronunciation"]: 13 | Function(utilities.load_config, config_name="latex.toml"), 14 | 15 | "add to bibliography": 16 | Function(tex_funcs.selection_to_bib, bib_path=BINDINGS["bibliography_path"]), 17 | 18 | "(open | edit) bibliography": 19 | Function(utilities.load_text_file, path=BINDINGS["bibliography_path"]), 20 | 21 | BINDINGS["template_prefix"] + "