diff --git a/mathfly/apps/texmaker.py b/mathfly/apps/texmaker.py new file mode 100644 index 0000000..a0057b9 --- /dev/null +++ b/mathfly/apps/texmaker.py @@ -0,0 +1,81 @@ + + +from dragonfly import (Grammar, Dictation, Function, Choice, Repeat, + IntegerRef) + +from mathfly.lib.actions import Text, Key, Mouse, AppContext +from mathfly.lib import control +from mathfly.lib.merge.mergerule import MergeRule + +# Texmaker keyboard shortcuts can be changed at 'Options - Configure TeXmaker - Shortcuts - Menus - Tools'self + + +class TexmakerRule(MergeRule): + pronunciation = "texmaker" + + mapping = { + # file + "new [file]": Key("c-n"), + "open": Key("c-o"), + "open recent": Key("a-f, down:3, right"), + "close": Key("c-w"), + "exit": Key("c-q"), + "restore previous session": Key("cs-f8"), + + # edit + "[go to] line ": Key("c-g") + Text("%(m)s") + Key("enter"), + "comment": Key("c-t"), + "uncomment": Key("c-u"), + "indent": Key("c-rangle"), + "(outdent | unindent)": Key("c-langle"), + "find []": Key("c-f/5") + Text("%(text)s"), + "find next []": Key("c-m") * Repeat(extra="n"), + "replace": Key("c-r"), + "check spelling": Key("cs-f7"), + "refresh structure": Key("cs-f1"), + + # tools + # if you have f1 set to turn on/off microphone, you will need to reset the Texmaker shortcut + "quick build": Key("f1"), + # "LaTeX": Key("f2"), # not sure what this does so I'm going to comment it out + "view DVI": Key("f3"), + "DVI to postscript": Key("f4"), + "view postscript": Key("f5"), + "PDF latex": Key("f6"), + "view PDF": Key("f7"), + "postscript to PDF": Key("f8"), + "DVI to PDF": Key("f9"), + "view log": Key("f10"), + "bibtech": Key("f11"), + "make index": Key("f12"), + + + # view + # Texmaker doesn't seem to have tabs unless I'm missing something + "next (document | dock) []": Key("a-pgdown") * Repeat(extra='n'), + "(previous | prior) (document | dock)": Key("a-pgup") * Repeat(extra='n'), + "full-screen": Key("cs-f11"), + "switch pane": Key("c-space"), # switch between editor and embedded viewer + + + } + + + extras = [ + Dictation("text"), + IntegerRef("n", 1, 10), + IntegerRef("m", 1, 1000), + ] + + defaults = { + + } + + +#--------------------------------------------------------------------------- + +context = AppContext(executable="texmaker") +grammar = Grammar("Texmaker", context=context) +rule = TexmakerRule(name="Texmaker") +grammar.add_rule(rule) +grammar.load() diff --git a/mathfly/apps/texmaker_accessibility.py b/mathfly/apps/texmaker_accessibility.py new file mode 100644 index 0000000..3c1193f --- /dev/null +++ b/mathfly/apps/texmaker_accessibility.py @@ -0,0 +1,120 @@ +""" +All credit to James Stout (aka WolfManStout) + +These are text manipulation commands that emulate Dragon's "full text control" in a a very small number of applications +the applications I have seen it work in are Texmaker, Chrome, and Firefox. + +In order for these commands to work you need to install some PREREQUISITES. +For instructions on installing the prerequisites for these commands, +please see https://github.com/wolfmanstout/pyia2 + +I will supplement the instructions given there, here. +1) you need to download or clone the repository there. +2) you need to Install python 2.7 and pip for Windows (but you probably have already done that) +3) Install comtypes library using pip + If you're using powershell, I believe the way to do that is to type in: + py -2 -m pip install comtypes +4) "Register IAccessible2Proxy.dll with Windows (Note: this needs to be done with administration priveleges)" + This is done by: + a) going into the terminal in administrator mode + b) navigating to the directory where you have the file IAccessible2Proxy.dll (this file is included in the pyia repository linked to above which you need to download) + c) typing in: regsvr32 IAccessible2Proxy.dll + d) pressing enter + If I recall, if you do this correctly you should get a pop up box saying that it was successful. + +For further information about these commands see: +http://handsfreecoding.org/2018/12/27/enhanced-text-manipulation-using-accessibility-apis/ + +In my experience, these commands don't always work. when they don't work, +you will probably get a message in the Natlink window saying something like +"nothing is focused" or "focused item is not text". When this happens, I recommend +switching to Google Chrome for a second (possibly the address bar if necessary since the commands are known to work there well) +and then switching back to the application you want, in this case Texmaker. +In my experience this will fix the problem temporarily. +""" + +from dragonfly import (Grammar, Dictation, Function, Compound, Alternative, + Literal, CursorPosition, TextQuery, Choice, Repeat, + IntegerRef) + +from dragonfly import get_accessibility_controller + +from mathfly.lib.actions import Text, Key, Mouse, AppContext +from mathfly.lib import control +from mathfly.lib.merge.mergerule import MergeRule + +accessibility = get_accessibility_controller() + +class TexmakerAccessibilityRule(MergeRule): + pronunciation = "texmaker accessibility" + + mapping = { + + + # Accessibility API Mappings + "go before ": Function( + lambda text_position_query: accessibility.move_cursor( + text_position_query, CursorPosition.BEFORE)), + "go after ": Function( + lambda text_position_query: accessibility.move_cursor( + text_position_query, CursorPosition.AFTER)), + "destruction ": Function(accessibility.select_text), + "words delete": Function( + lambda text_query: accessibility.replace_text(text_query, "")), + "replace with ": Function( + accessibility.replace_text), + + } + + + extras = [ + Dictation("replacement"), + Compound( + name="text_query", + spec=("[[([] |)] ] " + "([] |)"), + extras=[Dictation("start_phrase", default=""), + Alternative([Literal("before"), Literal("after")], + name="start_relative_position"), + Dictation("start_relative_phrase", default=""), + Literal("through", "through", value=True, default=False), + Dictation("end_phrase", default=""), + Alternative([Literal("before"), Literal("after")], + name="end_relative_position"), + Dictation("end_relative_phrase", default="")], + value_func=lambda node, extras: TextQuery( + start_phrase=str(extras["start_phrase"]), + start_relative_position=(CursorPosition[extras["start_relative_position"].upper()] + if "start_relative_position" in extras else None), + start_relative_phrase=str(extras["start_relative_phrase"]), + through=extras["through"], + end_phrase=str(extras["end_phrase"]), + end_relative_position=(CursorPosition[extras["end_relative_position"].upper()] + if "end_relative_position" in extras else None), + end_relative_phrase=str(extras["end_relative_phrase"]))), + Compound( + name="text_position_query", + spec=" [ ]", + extras=[Dictation("phrase", default=""), + Alternative([Literal("before"), Literal("after")], + name="relative_position"), + Dictation("relative_phrase", default="")], + value_func=lambda node, extras: TextQuery( + end_phrase=str(extras["phrase"]), + end_relative_position=(CursorPosition[extras["relative_position"].upper()] + if "relative_position" in extras else None), + end_relative_phrase=str(extras["relative_phrase"]))) + ] + + defaults = { + + } + + +#--------------------------------------------------------------------------- + +context = AppContext(executable="texmaker") +grammar = Grammar("TexmakerAccessibility", context=context) +rule = TexmakerAccessibilityRule(name="TexmakerAccessibility") +grammar.add_rule(rule) +grammar.load() diff --git a/mathfly/config/settings.toml b/mathfly/config/settings.toml index bca56f8..0e06918 100644 --- a/mathfly/config/settings.toml +++ b/mathfly/config/settings.toml @@ -10,7 +10,9 @@ ccr_modules = ["core", "alias" ] app_modules = ["sublime", - "sumatrapdf" + "sumatrapdf", + "texmaker_accessibility", + "texmaker", ] max_ccr_repetitions = 16 alternative_letters = false