class DevelopmentHelp(MappingRule): mapping = { # caster development tools "(show | open) documentation": BringApp(settings.SETTINGS["paths"]["DEFAULT_BROWSER_PATH"]) + WaitWindow(executable=settings.get_default_browser_executable()) + Key('c-t') + WaitWindow(title="New Tab") + Text('http://dragonfly.readthedocs.org/en/latest') + Key('enter'), "open natlink folder": R(BringApp("C:/Windows/explorer.exe", settings.SETTINGS["paths"]["BASE_PATH"].replace("/", "\\")), rdescript="Open Natlink Folder"), "refresh debug file": Function(devgen.refresh), "Agrippa <filetype> <path>": Function(grep_this), "run rule complexity test": Function(lambda: run_tests()), "run unit tests": Function(testrunner.run_tests), "run remote debugger": Function(run_remote_debugger), } extras = [ Dictation("text"), Choice("path", { "natlink": "c:/natlink/natlink", "sea": "C:/", }), Choice("filetype", { "java": "*.java", "python": "*.py", }) ] defaults = {"text": ""}
class CppSnippetExample(MappingRule): pronunciation = "sublime snippet" mapping = { "<snippet>": R(Function(insert_snippet)), "<snippet_variants> [<n>]": R(Function(insert_snippet_with_variants)), "variant <n>": R(Key("c-z") + Function(insert_variant)), "display variants": R(Key("c-z") + Function(display_variants)), "small test": R( Function(send_sublime, c="insert_snippe", data={ "contents": "${1:$PARAK}=2", "PARAK": "y" })) + R(Text("hello")), "small jerry": R(Function(send_sublime, c="prev_field", data={})), } extras = [ IntegerRefST("n", 1, 10), Choice("snippet", {k: v for k, v in snippets.items() if isinstance(v, str)}), Choice("snippet_variants", {k: v for k, v in snippets.items() if not isinstance(v, str)}), ] defaults = {}
class UnimpairedRule(MappingRule): mapping = { "edit <dir>": Key("%(dir)s, c"), "space <dir>": Key("%(dir)s, space"), "file <dir>": Key("%(dir)s, f"), "(lint | lock) <dir>": Key("%(dir)s, l"), "(quick | bug) <dir>": Key("%(dir)s, q"), # Ack puts search results in quickfixlist, so it should follow search "big <ack>": Key("%(ack)s, q"), } extras = [ IntegerRef("n", 1, 10), Choice("dir", { "up": "lbracket", "down": "rbracket", }), Choice("ack", { "pecks": "lbracket", "next": "rbracket", }) ] defaults = { 'n': 1, }
class DouglasGridRule(MappingRule): mapping = { "<x> [by] <y> [<action>]": R(Function(send_input)), "<x1> [by] <y1> (grab | select) <x2> [by] <y2>": R(Function(send_input_select)), "<x1> [by] <y1> (grab | select) <x2>": R(Function(send_input_select_short)), "squat": R(Function(store_first_point)), "bench": R(Function(select_text)), SymbolSpecs.CANCEL: R(Function(kill)), } extras = [ IntegerRefST("x", 0, 300), IntegerRefST("y", 0, 300), IntegerRefST("x1", 0, 300), IntegerRefST("y1", 0, 300), IntegerRefST("x2", 0, 300), IntegerRefST("y2", 0, 300), Choice("action", { "kick": 0, "psychic": 1, "move": 2, }), Choice("point", { "one": 1, "two": 2, }), ] defaults = { "action": -1, }
class ChessInputRule(MergeRule): pronunciation = "chess input" mapping = { "calibrate <corner> corner": R(Function(calibrate)), "<chess_letter> <chess_number> <chess_letter2> <chess_number2>": R(Function(move)), "flip board": R(Function(flip)) } extras = [ Choice("corner", { "left top": True, "top left": True, "right bottom": False, "bottom right": False, }), Choice("chess_letter", LETTERS), Choice("chess_letter2", LETTERS), Choice("chess_number", NUMBERS), Choice("chess_number2", NUMBERS), ] defaults = {}
class Shortcuts(MergeRule): mapping = { "<single_shortcut>": Function(single_press), "<repeat_shortcut> [<n500>]": Function(repeat_press), "work <n12>": Function(workspace_switcher), "switch [<n100>]": Key('alt:down,tab:%(n100)s,alt:up'), "swap [<n100>]": Key('alt:down,backtick:%(n100)s,alt:up'), "swipe [<n100>]": Key('alt:down,ctrl:down,tab:%(n100)s,ctrl:down,alt:up'), "window move <n12>": Function(workspace_mover), "window <window_direction>": Function(resize_window), "launcher": Key("win:down,ctrl:down,l,ctrl:up,win:up"), # "swap <n100>": Key('alt:down/25,tab/25:%(n100)s,alt:up') } extras = [ IntegerRef("n100", 1, 100), IntegerRef("n500", 1, 500), IntegerRef("n12", 1, 13), Choice("single_shortcut", single_shortcut), Choice("repeat_shortcut", repeat_shortcut), Choice("window_direction", { "left": "left", "right": "right", "maximize": "maximize", "minimize": "minimize", }) ] defaults = { "n100": 1, "n500": 1, }
class CppSnippetExampleExperimental(MappingRule): pronunciation = "sublime snippet" mapping = { "<snippet>": R(Function(insert_snippet)), "<snippet_variants> [<n>]": R(Function(insert_snippet_with_variants)), "variant <n>": R(Key("c-z") + Function(insert_variant)), "display variants": R(Key("c-z") + Function(display_variants)), "apply <transformation>": R(Key("c-z") + Function(transform_last_snippet)), "small test": R(Function(send_sublime,c = "insert_snippet",data = {"contents":"${1:${PARAK:y}}=2 + ${PARAK:z}","PARAK":"x"})), "small jerry": R(Function(send_sublime,c = "prev_field",data = {})), "jerry": R(Function(store_and_next)), "<snippet> over": R(Function(insert_snippet_with_defaults)), "<snippet_variants> [<n>] over": R(Function(insert_snippet_with_variants_and_defaults)), } extras = [ IntegerRefST("n",1,10), Choice("snippet",{k:v for k,v in snippets.items() if isinstance(v,str)}), Choice("snippet_variants",{k:v for k,v in snippets.items() if not isinstance(v,str)}), Choice("transformation",transformations), ] defaults = {}
def _deserialize(self): """ This _deserialize creates mapping which uses the user-made extras. """ self._initialize() self._smr_mapping = { "bring me <program>": R(Function(self._bring_program)), "bring me <website>": R(Function(self._bring_website)), "bring me <folder> [in <app>]": R(Function(self._bring_folder)), "bring me <file>": R(Function(self._bring_file)), "refresh bring me": R(Function(self._load_and_refresh)), "<launch_type> to bring me as <key>": R(Function(self._bring_add)), "to bring me as <key>": R(Function(self._bring_add_auto)), "remove <key> from bring me": R(Function(self._bring_remove)), "restore bring me defaults": R(Function(self._bring_reset_defaults)), } self._smr_extras = [ Choice( "launch_type", { "[current] program": "program", "website": "website", "folder": "folder", "file": "file", }), Choice("app", { "terminal": "terminal", "explorer": "explorer", }), Dictation("key"), ] self._smr_extras.extend(self._rebuild_items()) self._smr_defaults = {"app": None}
class FoodGroupRule(CompoundRule): spec = "(I ate <food> <time> | <time> I ate <food>) [and thought it was <opinion>]" time = { "(two days ago | day before yesterday)": 2, "yesterday": 1, "today": 0, } food = { "(a Granny Smith | an) apple": "fruit", "an orange": "fruit", "a hamburger": "meat", "a [juicy] steak": "meat", } extras = [ Choice("time", time), Choice("food", food), Dictation("opinion"), ] def _process_recognition(self, node, extras): days_ago = extras["time"] foodgroup = extras["food"] print "You ate %s %d days ago." % (foodgroup, days_ago) if "opinion" in extras: print "You thought it was %s." % (extras["opinion"])
class Format(MappingRule): mapping = { "set [<big>] format " "(<capitalization> <spacing> | <capitalization> | <spacing>) " "[(bow|bowel)]": Function(textformat.set_text_format), "clear castervoice [<big>] formatting": Function(textformat.clear_text_format), "peek [<big>] format": Function(textformat.peek_text_format), "(<capitalization> <spacing> | <capitalization> | <spacing>) " "[(bow|bowel)] <textnv> [brunt]": Function(textformat.master_format_text), "[<big>] format <textnv>": Function(textformat.prior_text_format), "<word_limit> [<big>] format <textnv>": Function(textformat.partial_format_text), } extras = [ Choice("big", { "big": True, }), Choice( "capitalization", { "yell": 1, "tie": 2, "gerrish": 3, "sing": 4, "laws": 5, "say": 6, "cop": 7, "slip": 8, }), Choice( "spacing", { "gum": 1, "gun": 1, "spine": 2, "snake": 3, "pebble": 4, "incline": 5, "dissent": 6, "descent": 6, }), Choice("word_limit", { "single": 1, "double": 2, "triple": 3, "Quadra": 4 }), Dictation("textnv"), ] defaults = { "big": False, "capitalization": 0, "spacing": 0, }
class HardwareRule(MappingRule): mapping = { # Windows 10 changes volume by increments 2 "volume <volume_mode> [<n_volume>]": R(Key("%(volume_mode)s") * Repeat(extra="n_volume")), "media <multimedia_control> [<n_media>]": R(Key("%(multimedia_control)s") * Repeat(extra="n_media")), "change monitor": R(Key("w-p") + Pause("100") + Function(change_monitor)) } extras = [ IntegerRefST("n_media", 1, 15), IntegerRefST("n_volume", 1, 50), Choice("multimedia_control", { "next": "tracknext", "back": "trackprev", "play|pause": "playpause", }), Choice("volume_mode", { "mute|unmute": "volumemute", "up": "volumeup", "down": "volumedown", }) ] defaults = { "n_volume": 1, "n_media": 1, "volume_mode": "setsysvolume", }
class UnicodeAlphabet(MergeRule): pronunciation = "unicode alphabet" __name__ = "unicode alphabet" mapping = { "[<big>] <letter> [<accent>]": R(Function(write_letter, extra={"big", "letter", "accent"}), rdescript="Spell"), } extras = [ get_alphabet_choice("letter"), Choice("big", { "big": "big", }), Choice( "accent", { "grave": u'\u0300', "acute": u'\u0301', "circumflex": u'\u0302', "tilde": u'\u0303', "caron": u'\u030C', "ring": u'\u030A', "diaresis": u'\u0308', #perhaps others, cedilla or ogonek #"said Hilda": u'\u0327', #"organic": u'\u0328', }), ] defaults = { "big": "", }
class GridControlRule(MergeRule): mapping = { "[<pre>] <color> <n> [<action>]": R(Function(send_input, nexus=_NEXUS), rdescript="Rainbow Grid: Action"), "exit | escape | cancel": R(Function(kill, nexus=_NEXUS), rdescript="Exit Rainbow Grid"), } extras = [ IntegerRefST("pre", 0, 9), Choice( "color", { "red": 0, "(orange | tan | brown)": 1, "yellow": 2, "green": 3, "blue": 4, "purple": 5 }), Choice("action", { "kick": 0, "psychic": 1, }), IntegerRefST("n", 0, 100), ] defaults = { "pre": 0, "action": -1, }
class sn_nested(NestedRule): mapping = { "[<before>] integral from <sequence1> to <sequence2>": [ Function(lambda: texchar("int")) + Key("c-l"), Key("right, c-h"), Key("right") ], "[<before>] definite from <sequence1> to <sequence2>": [ Key("c-6, right, c-l"), Key("right, c-h"), Key("right, c-left, left") ], "[<before>] differential <sequence1> by <sequence2>": [Key("c-f, d"), Key("down, d"), Key("right")], "[<before>] sum from <sequence1> to <sequence2>": [ Key("f10, i, down:11, enter/25, a, enter, f10, i, down:11, enter/25, b, enter" ) + Function(lambda: texchar("sum")) + Key("down"), Key("up:2"), Key("right") ], "[<before>] limit from <sequence1> to <sequence2>": [ Key("f10, i, down:11, enter/25, b, enter") + Function(lambda: texchar("lim")) + Key("down"), Function(lambda: texchar("rightarrow")), Key("right") ], "[<before>] argument that <minmax> <sequence1>": [ Key("f10, i, down:11, enter/25, b, enter") + Text("arg%(minmax)s") + Key("down"), Key("right"), None ], "[<before>] <minmax> by <sequence1>": [ Key("f10, i, down:11, enter/25, b, enter") + Text("%(minmax)s") + Key("down"), Key("right"), None ], "[<before>] <script1> <singleton1> [<after>]": [Key("%(script1)s"), Key("right"), None], "[<before>] <script1> <singleton1> <script2> <singleton2> [<after>]": [Key("%(script1)s"), Key("right, %(script2)s"), Key("right")], } extras = [ Choice("minmax", { "(minimum | minimises)": "min", "(maximum | maximises)": "max", }), Choice("script1", { "sub": "c-l", "super": "c-h", }), Choice("script2", { "sub": "c-l", "super": "c-h", }), ]
class NormalActionRule(CompoundRule): spec = "<action> [<scope>]" extras = [Choice("action", _actions), Choice("scope", _scopes)] def _process_recognition(self, node, extras): action = extras["action"] scope = None if "scope" in extras: scope = extras["scope"] edit(action, scope)
class LaTeX(MergeRule): non = LaTeXNon pronunciation = BINDINGS["pronunciation"] mapping = { "insert comment": Text("% "), BINDINGS["class_prefix"] + " [<class>]": tex_funcs.back_curl("documentclass", "%(class)s"), BINDINGS["environment_prefix"] + " <environment>": Function(tex_funcs.begin_end), # BINDINGS["package_prefix"] + " [<packopts>]": Function(tex_funcs.packages), # BINDINGS["symbol_prefix"] + " <symbol>": Function(tex_funcs.symbol), BINDINGS["symbol_prefix"] + " <misc_symbol>": Function( lambda misc_symbol: execution.alternating_command(misc_symbol)), BINDINGS["greek_prefix"] + " [<big>] <greek_letter>": Function(tex_funcs.greek_letters), # BINDINGS["command_prefix"] + " <command>": tex_funcs.back_curl("%(command)s", ""), BINDINGS["command_prefix"] + " <commandnoarg>": Text("\\%(commandnoarg)s "), BINDINGS["command_prefix"] + " my (bib resource | bibliography)": tex_funcs.back_curl("addbibresource", BINDINGS["bibliography_path"]), BINDINGS["command_prefix"] + " quote": Function(tex_funcs.quote), # BINDINGS["template_prefix"] + " <template>": Function(execution.template), } extras = [ Choice("big", {CORE["capitals_prefix"]: True}), Choice("packopts", BINDINGS["packages"]), Choice("class", BINDINGS["document_classes"]), Choice("greek_letter", BINDINGS["greek_letters"]), Choice("symbol", BINDINGS["symbols"]), Choice("misc_symbol", BINDINGS["misc_symbols"]), Choice("commandnoarg", BINDINGS["commandnoarg"]), Choice("command", BINDINGS["command"]), Choice("environment", BINDINGS["environments"]), Choice("template", BINDINGS["templates"]), ] defaults = { "big": False, "packopts": "", "class": "", }
class GlobalCommandRule(TortoiseRule): spec = config.tortoisesvn.global_command extras = [ Choice("command", config.tortoisesvn.actions), Choice("predef", config.tortoisesvn.predef), ] def _process_recognition(self, node, extras): path_list = [extras["predef"]] command = extras["command"] self._execute_command(path_list, command)
class NormalModeToInsertModeCommands(MappingRule): mapping = { "insert": Key("i"), "(shift|big) insert": Key("I"), 'change <no_count_motion>': Key('c,%(no_count_motion)s,'), '[<n>] change <optional_count_motion>': Text('%(n)d') + Key('c,%(optional_count_motion)s'), '<n> change <mandatory_count_motion>': Text('%(n)d') + Key('c,%(mandatory_count_motion)s'), '[<n>] chan <text_object_selection_object>': Text('%(n)d') + Key("c,a,%(text_object_selection_object)s"), '[<n>] chin <text_object_selection_object>': Text('%(n)d') + Key("c,i,%(text_object_selection_object)s"), '[<n>] chat <letter>': Text('%(n)d') + Key("c,t,%(letter)s"), '[<n>] chaff <letter>': Text('%(n)d') + Key("c,f,%(letter)s"), '[<n>] chew': Text('%(n)d') + Key('c,w'), '[<n>] change <find_motion>': Text('%(n)d') + Key('c,%(find_motion)s'), "(big|shift) change": Key("C"), "change (char|letter)": Key("s"), "(sub|change) line": Key("S"), "(after|append)": Key("a"), "(shift|big) (after|append)": Key("A"), "open": Key("o"), "(shift|big) open": Key("O"), } extras = [ LetterRef('letter'), Choice('no_count_motion', no_count_motion_keys), Choice('optional_count_motion', optional_count_motion_keys), Choice('mandatory_count_motion', mandatory_count_motion_keys), Choice('text_object_selection', text_object_keys), Choice('text_object_selection_object', text_object_selection_objects), FindMotionRef('find_motion'), IntegerRef('n', 1, 101, default=1), ]
class CustomKeysRule(MappingRule): mapping = { "windows": Key('win:down/3, win:up/3'), "caster reboot": Mimic("reboot caster"), "magic":Mouse("left:down/3, left:up/3"), "space bar":Key("space:down/3, space:up/3"), "foot pedal <footPedalMode>":Function(setFootPedalMode), "ecks box controller <onOff>":Function(setControllerMode), "look":Key("f15") # "foot pedal mouse":Function(lambda:writeIni("footMode","mouse")) } extras = [ Choice("footPedalMode",foot_pedal_modes), Choice("onOff",{"on":"on","off":"off"}) ]
class SudokuGridRule(MergeRule): ''' Rules for sudoku grid. We can either move the mouse or drag it. The number n is one of the numbered squares. The grid portion is a number from 1-9 referencing an inner unnumbered square. ''' pronunciation = "sudoku grid" mapping = { "curse <xn> by <yn> [grid <hexdigit>]": R(Function(move_mouse)), "drag <xn> by <yn> [grid <hexdigit>]": R(Function(drag_mouse)), } extras = [ IntegerRef("yn", -1, 100), IntegerRef("xn", -1, 100), IntegerRef("sn", 0, 10), Choice( "hexdigit", { "zero": 0, "one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "arch": 10, "brov": 11, "char": 12, "delta": 13, "echo": 14, "foxy": 15, }), Choice("action", { "move": 0, "kick": 1, "kick (double | 2)": 2, "psychic": 3, }), ] defaults = { "xn": 0, "yn": 0, "hexdigit": None, "action": 0, }
class HTML(MergeRule): mapping = { "insert <element>": Function(insert), } extras = [ Choice("element", BINDINGS["elements"]), ]
def test_natlink_compiler(self): from dragonfly.engines.backend_natlink.compiler import NatlinkCompiler extras = [ Choice("food", { "(an | a juicy) apple": "good", "a [greasy] hamburger": "bad" }) ] rule = CompoundRule('ExampleCustomRule', "I want to eat <food>", extras) grammar = Grammar(name="mygrammar") grammar.add_rule(rule) c = NatlinkCompiler() (compiled_grammar, rule_names) = c.compile_grammar(grammar) assert rule_names == (None, "ExampleCustomRule") if PY2: assert compiled_grammar.encode( "hex" ) == "0000000000000000040000001c0000001c000000010000004578616d706c65437573746f6d52756c650000000500000000000000060000000000000002000000900000000c0000000100000049000000100000000200000077616e74000000000c00000003000000746f00000c00000004000000656174000c000000050000006100000010000000060000006772656173790000140000000700000068616d6275726765720000000c00000008000000616e000010000000090000006a75696379000000100000000a0000006170706c6500000003000000e0000000e00000000100000001000000010000000100000001000000030000000100000003000000020000000300000003000000030000000400000002000000010000000100000002000000010000000100000003000000050000000100000004000000030000000600000002000000040000000300000007000000020000000100000001000000010000000100000002000000030000000800000001000000010000000300000005000000030000000900000002000000010000000200000002000000030000000a000000020000000100000002000000020000000200000001000000" else: assert codecs.encode( compiled_grammar, "hex_codec" ) == b"0000000000000000040000001c0000001c000000010000004578616d706c65437573746f6d52756c650000000500000000000000060000000000000002000000900000000c0000000100000049000000100000000200000077616e74000000000c00000003000000746f00000c00000004000000656174000c00000005000000616e00000c000000060000006100000010000000070000006a7569637900000010000000080000006170706c6500000010000000090000006772656173790000140000000a00000068616d62757267657200000003000000e0000000e00000000100000001000000010000000100000001000000030000000100000003000000020000000300000003000000030000000400000002000000010000000100000002000000010000000100000001000000020000000300000005000000010000000100000003000000060000000300000007000000020000000100000002000000020000000300000008000000020000000100000001000000010000000300000006000000010000000400000003000000090000000200000004000000030000000a000000020000000100000002000000020000000200000001000000"
def get_alphabet_choice(spec): return Choice( spec, { "arch": "a", "brov": "b", "char": "c", "delta": "d", "echo": "e", "foxy": "f", "goof": "g", "hotel": "h", "India": "i", "julia": "j", "kilo": "k", "Lima": "l", "Mike": "m", "Novakeen": "n", "oscar": "o", "prime": "p", "Quebec": "q", "Romeo": "r", "Sierra": "s", "tango": "t", "uniform": "u", "victor": "v", "whiskey": "w", "x-ray": "x", "yankee": "y", "Zulu": "z", })
class MouseAlternativesRule(MappingRule): mapping = { "legion [<monitor>] [<rough>]": R( Function(navigation.mouse_alternates, mode="legion") + Function(utilities.focus_mousegrid, gridtitle="legiongrid")), "rainbow [<monitor>]": R( Function(navigation.mouse_alternates, mode="rainbow") + Function(utilities.focus_mousegrid, gridtitle="rainbowgrid")), "douglas [<monitor>]": R( Function(navigation.mouse_alternates, mode="douglas") + Function(utilities.focus_mousegrid, gridtitle="douglasgrid")), "sudoku [<monitor>]": R( Function(navigation.mouse_alternates, mode="sudoku") + Function(utilities.focus_mousegrid, gridtitle="sudokugrid")), } extras = [ IntegerRefST("monitor", 1, 10), Choice("rough", { "rough": True, "detailed": False }) ] defaults = {"rough": True}
class KeystrokeRule(MappingRule): exported = False mapping = grammarCfg.cmd.map extras = [ IntegerRef("n", 1, 100), Dictation("text"), Dictation("text2"), Choice("char", specialCharMap), Choice("modifier1", modifierMap), Choice("modifier2", modifierMap), Choice("modifierSingle", singleModifierMap), Choice("pressKey", pressKeyMap), ] defaults = { "n": 1, }
class SudokuGridRule(MappingRule): pronunciation = "sudoku grid" mapping = { "<n> [grid <s>] [<action>]": R(Function(move_mouse)), "[<n0>] [grid <s0>] drag <n> [grid <s>] [<action>]": R(Function(drag_mouse)), "escape": R(Function(kill)), SymbolSpecs.CANCEL: R(Function(kill)), } extras = [ IntegerRefST("n", -1, 1500), IntegerRefST("n0", -1, 1500), IntegerRefST("s", 0, 10), IntegerRefST("s0", 0, 10), Choice("action", { "move": 0, "kick": 1, "kick (double | 2)": 2, "psychic": 3, }), ] defaults = { "n": 0, "n0": 0, "s": 0, "s0": 0, "action": 0, }
def get_alphabet_choice(spec): return Choice( spec, { "arch": "a", "brov": "b", "chair": "c", "dell": "d", "etch": "e", "fomp": "f", "goof": "g", "hark": "h", "ice": "i", "jinks": "j", "koop": "k", "lug": "l", "Mike": "m", "nerb": "n", "ork": "o", "pooch": "p", "quash": "q", "rosh": "r", "souk": "s", "teek": "t", "unks": "u", "verge": "v", "womp": "w", "trex": "x", "yang": "y", "zooch": "z", })
class LegionGridRule(MappingRule): mapping = { "<n> [<action>]": R(Function(send_input)), "refresh": R(Function(Grid.mouse_alternates, mode="legion")), SymbolSpecs.CANCEL + " {weight=2}": R(Function(Grid.kill)), "<n1> (select | light) <n2>": R(Function(drag_highlight)), } extras = [ Choice("action", { "kick": 0, "psychic": 1, "select | light": 2, }), ShortIntegerRef("n", 0, 1000), ShortIntegerRef("n1", 0, 1000), ShortIntegerRef("n2", 0, 1000), ] defaults = { "action": -1, }
class Bash(MergeRule): mapping = { "pseudo-": Text("sudo "), "change": Text("cd "), "list": Key("l,s,enter"), "sublime": Text("subl "), "home": Text("~/"), "pie": Text("py"), "copy": Key("cs-c"), "copy <t>": Function(copy), "paste": Key("cs-v"), "paste <t>": Function(paste), "make directory": Text("mkdir "), ".Thought": Text(".."), "parent": Text("../"), "remote <ssh_server>": Text('ssh %(ssh_server)s'), "dropbox": Text("cd ~/Dropbox/"), "reset": Key("c-c,c-c,up,enter") } extras = [ Choice('ssh_server', {}), Dictation("t"), ] defaults = { "t": 'default', }
class SnapWindowRule(CompoundRule): spec = 'snap window to <region>' extras = [ Choice( 'region', { 'top left': [0, 0, 0.5, 0.5], 'top half': [0, 0, 1, 0.5], 'top right': [0.5, 0, 0.5, 0.5], 'right half': [0.5, 0, 0.5, 1], 'bottom right': [0.5, 0.5, 0.5, 0.5], 'bottom half': [0, 0.5, 1, 0.5], 'bottom left': [0, 0.5, 0.5, 0.5], 'left half': [0, 0, 0.5, 1], 'whole monitor': [0, 0, 1, 1], }) ] @staticmethod def snap_window(window, region_spec): monitor = window.get_containing_monitor().rectangle pos = Rectangle(monitor.x1 + monitor.dx * region_spec[0], monitor.y1 + monitor.dy * region_spec[1], monitor.dx * region_spec[2], monitor.dy * region_spec[3]) window.restore() window.set_position(pos) def _process_recognition(self, node, extras): self.snap_window(Window.get_foreground(), extras['region'])