def test_seeker_backward(self): for i in range(0, 2): '''make 2 fake NullActions''' trigger1 = NullAction(rspec="bell") trigger2 = NullAction(rspec="door") trigger1.set_nexus(self.nexus) trigger2.set_nexus(self.nexus) '''make fake StackItemRegisteredActions''' alt2 = MockAlternative(u"my", u"spoken", u"words") sira1 = StackItemRegisteredAction(trigger1, {"_node": alt2}) sira2 = StackItemRegisteredAction(trigger2, {"_node": alt2}) '''add them''' self.nexus.state.add(sira1) self.nexus.state.add(sira2) '''set up backward looking seeker''' mutable_string = {"value": ""} def append_a(): mutable_string["value"] += "a" def append_b(): mutable_string["value"] += "b" def append_c(): mutable_string["value"] += "c" def append_d(): mutable_string["value"] += "d" '''create context levels''' set_1_1 = S(["arch"], append_a) set_1_2 = S(["bell"], append_b) level_1 = L(set_1_1, set_1_2) set_2_1 = S(["cellar"], append_c) set_2_2 = S(["door"], append_d) level_2 = L(set_2_1, set_2_2) '''create context seeker''' levels = [level_1, level_2] seeker = ContextSeeker(back=levels) if i == 0: seeker.reverse = True seeker.set_nexus(self.nexus) '''create context seeker stack item''' alt = MockAlternative(u"my", u"spoken", u"words") stack_seeker = StackItemSeeker(seeker, {"_node": alt}) '''add it''' self.nexus.state.add(stack_seeker) if i == 0: self.assertEqual(mutable_string["value"], "db") else: self.assertEqual(mutable_string["value"], "bd")
def __init__(self, node, grammar, stat_msg=None, is_reset=False): # for self modification self.node = node first = False if self.master_node == None: self.master_node = self.node first = True self.post = ContextSeeker(forward=[L(S(["cancel"], self.reset_node, consume=False))], rspec=self.master_node.spec) if self.stat_msg == None: self.stat_msg = stat_msg mapping = {} extras = [] defaults = {} # each child node gets turned into a mapping key/value for child in self.node.children: child.fill_out_rule(mapping, extras, defaults, self) if len(mapping)==0: if self.stat_msg!=None and not first: self.stat_msg.text("Node Reset")# status window messaging self.reset_node() for child in self.node.children: child.fill_out_rule(mapping, extras, defaults, self) else: if self.stat_msg!=None and not first and not is_reset:# status window messaging self.stat_msg.hint("\n".join([x.get_spec_and_base_and_node()[0] for x in self.node.children])) MappingRule.__init__(self, "node_" + str(self.master_node.spec), mapping, extras, defaults) self.grammar = grammar
def test_asynchronous_finisher(self): '''make termination action''' termination = NullAction(rspec="kill") termination.set_nexus(self.nexus) alt = MockAlternative(u"my", u"spoken", u"words") sira = StackItemRegisteredAction(termination, {"_node": alt}) '''setup function for asynchronous finisher''' mutable_integer = {"value": 0} def increment(): mutable_integer["value"] += 1 # '''make asynchronous action''' asynchronous = AsynchronousAction([L(S(["kill"], lambda: None))], blocking=False, finisher=Function(increment)) asynchronous.set_nexus(self.nexus) '''make StackItemAsynchronous''' sia1 = StackItemAsynchronous(asynchronous, {"_node": alt}) '''add it''' self.nexus.state.add(sia1) # self.nexus.state.add(sira) '''finisher should be executed when asynchronous finishes''' self.assertEqual(mutable_integer["value"], 1)
def test_seeker_defaulting_and_chaining(self): '''this action makes the first seeker default''' action = NullAction(rspec="clean") action.set_nexus(self.nexus) alt = MockAlternative(u"my", u"spoken", u"words") sira = StackItemRegisteredAction(action, {"_node": alt}) self.nexus.state.add(sira) # mutable_integer = {"value": 0} def increment(): mutable_integer["value"] += 1 '''make backward seekers''' back_seeker = ContextSeeker(back=[ L(S(["def"], Function(lambda: None)), S(["abc"], Function(increment))) ], rspec="abc") back_seeker.set_nexus(self.nexus) '''create backward seeker stack items''' stack_seeker1 = StackItemSeeker(back_seeker, {"_node": alt}) stack_seeker2 = StackItemSeeker(back_seeker, {"_node": alt}) '''add one''' self.nexus.state.add(stack_seeker1) '''at this point, the first seeker should have defaulted and done nothing''' self.assertEqual(mutable_integer["value"], 0) self.nexus.state.add(stack_seeker2) '''the second context seeker should have been triggered by the first, incrementing the value''' self.assertEqual(mutable_integer["value"], 1)
def test_cancel(self): mutable_integer = {"value": 0} def increment(): mutable_integer["value"] += 1 '''make fake AsynchronousAction''' context_set = S(["test", "words"], increment) unused_context_set = S(["other"], Text, "words") context_level = L(context_set, unused_context_set) aa1 = AsynchronousAction([context_level], time_in_seconds=0.2, repetitions=20, blocking=False) aa1.set_nexus(self.nexus) '''make fake StackItemAsynchronous''' alt = MockAlternative(u"gray", u"fox") sia1 = StackItemAsynchronous( aa1, {"_node": alt}) # the dictionary is fake Dragonfly data '''add it''' self.nexus.state.add(sia1) '''make fake canceling RegisteredAction''' cancel = R(NullAction(), rspec="test") cancel.set_nexus(self.nexus) '''make fake StackItemRegisteredAction''' alt2 = MockAlternative(u"my", u"spoken", u"words") sira1 = StackItemRegisteredAction(cancel, {"_node": alt2}) '''add it''' self.nexus.state.add(sira1) '''AsynchronousAction should have executed exactly once, when it was added, then immediately gotten canceled''' self.assertEqual(mutable_integer["value"], 1)
def __init__(self, base, rspec="default", rdescript="unnamed command (CA)", instructions="instructions missing", nexus=None): self.set_nexus(nexus) on_complete = AsynchronousAction.hmc_complete( lambda data: receive_response(data), self.nexus()) AsynchronousAction.__init__( self, [L(S(["cancel"], on_complete))], 1, 60, rdescript, False ) # cannot block, if it does, it'll block its own confirm command self.base = base self.rspec = rspec self.instructions = instructions mutable_integer = {"value": 0} def receive_response( data ): # signals to the stack to cease waiting, return True terminates ''' receives response from homunculus, uses it to stop the stack and tell the ConfirmAction how to execute ''' mutable_integer["value"] = data["confirm"] self.mutable_integer = mutable_integer
def __init__(self, executable=None, title=None, time_in_seconds=1, repetitions=15, rdescript="unnamed command (SFW)", blocking=False): assert executable != None or title != None, "SuperFocusWindow needs executable or title" def attempt_focus(): for win in Window.get_all_windows(): w = win found_match = True if title != None: found_match = title in w.title if found_match and executable != None: found_match = executable in w.executable if found_match: try: # this is still broken win32gui.SetWindowPos( w.handle, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE) win32gui.SetWindowPos( w.handle, win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE) win32gui.SetWindowPos( w.handle, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_SHOWWINDOW + win32con.SWP_NOMOVE + win32con.SWP_NOSIZE) Key("alt").execute() time.sleep(0.5) win32gui.SetForegroundWindow(w.handle) w.set_foreground() except Exception: utilities.report("Unable to set focus:\ntitle: " + w.title + "\nexe: " + w.executable) break # do not assume that it worked success = SuperFocusWindow.focus_was_success(title, executable) if not success: if title != None: print "title failure: ", title, w.title if executable != None: print "executable failure: ", executable, w.executable, executable in w.executable return success forward = [L(S(["cancel"], attempt_focus))] AsynchronousAction.__init__( self, forward, time_in_seconds=time_in_seconds, repetitions=repetitions, rdescript=rdescript, blocking=blocking, finisher=Function(control.nexus().intermediary.text, message="SuperFocus Complete") + Key("escape")) self.show = False
def settings_window(nexus): h_launch.launch(settings.WXTYPE_SETTINGS) on_complete = AsynchronousAction.hmc_complete( lambda data: receive_settings(data), nexus) AsynchronousAction([L(S(["cancel"], on_complete))], time_in_seconds=1, repetitions=300, blocking=False).execute()
def test_blocking(self): '''tests: 1 - successful termination (queued actions execute immediately) 2 - unsuccessful termination (queued actions are dropped) 3 - cancellation (queued actions are dropped) ''' for i in range(0, 3): '''make fake AsynchronousAction''' context_set = S(["cancel", "words"], NullAction()) context_level = L(context_set) aa1 = AsynchronousAction([context_level], blocking=True) # turn blocking on aa1.set_nexus(self.nexus) '''make fake StackItemAsynchronous''' alt = MockAlternative(u"run", u"blocker") sia1 = StackItemAsynchronous( aa1, {"_node": alt}) # the dictionary is fake Dragonfly data '''add it''' self.nexus.state.add(sia1) '''blocked function''' mutable_integer = {"value": 0} def increment(): mutable_integer["value"] += 1 '''make fake incrementing RegisteredAction''' inc = R(Function(increment), rspec="inc") inc.set_nexus(self.nexus) '''make fake StackItemRegisteredAction''' alt2 = MockAlternative(u"my", u"spoken", u"words") sira1 = StackItemRegisteredAction(inc, {"_node": alt2}) '''add it''' self.nexus.state.add(sira1) '''incrementing should be blocked at this point''' self.assertEqual(mutable_integer["value"], 0) if i == 0: '''incrementing should happen that moment of unblocking''' self.nexus.state.terminate_asynchronous(True) self.assertEqual(mutable_integer["value"], 1) elif i == 1: '''incrementing gets dropped''' self.nexus.state.terminate_asynchronous(False) self.assertEqual(mutable_integer["value"], 0) elif i == 2: '''make fake canceling RegisteredAction''' cancel = NullAction(rspec="cancel") cancel.set_nexus(self.nexus) '''make fake StackItemRegisteredAction''' alt3 = MockAlternative(u"my", u"cancel", u"words") sira2 = StackItemRegisteredAction(cancel, {"_node": alt3}) '''add it''' self.nexus.state.add(sira2) '''incrementing gets dropped''' self.assertEqual(mutable_integer["value"], 0)
def chain_alias(self): text = read_highlighted(10) if text is not None: h_launch.launch(settings.QTYPE_INSTRUCTIONS, data="Enter_spec_for_command|") on_complete = AsynchronousAction.hmc_complete( lambda data: self.refresh(data[0].replace("\n", ""), text), self.nexus) AsynchronousAction( [L(S(["cancel"], on_complete))], time_in_seconds=0.5, repetitions=300, blocking=False).execute()
def __init__(self, list_function, filter_function, selection_function, default_1=True, rspec="default", rdescript="unnamed command (FM)"): def get_choices(data): choices = list_function() if filter_function: choices = filter_function( data, choices ) # the filter function is responsible for using the data to filter the choices while len(choices) < len(FuzzyMatchAction.TEN): choices.append("") # this is questionable return choices self.choice_generator = get_choices mutable_list = { "value": None } # only generate the choices once, and show them between the action and the stack item self.mutable_list = mutable_list def execute_choice(spoken_words=[]): n = -1 while len( spoken_words ) > 2: # in the event the last words spoken were a command chain, spoken_words.pop() # get only the number trigger j = "" if len(spoken_words) > 0: j = " ".join(spoken_words) if j in FuzzyMatchAction.TEN: n = FuzzyMatchAction.TEN.index(j) if n == -1: n = 0 selection_function(mutable_list["value"][n]) def cancel_message(): control.nexus().intermediary.text("Cancel (" + rdescript + ")") forward = [ L(S([""], execute_choice, consume=False), S(["number"], execute_choice, use_spoken=True), S(["cancel", "clear"], cancel_message)) ] if not default_1: # make cancel the default context_level = forward[0] a = context_level.sets[0] context_level.sets[0] = context_level.sets[2] context_level.sets[2] = a ContextSeeker.__init__(self, None, forward, rspec, rdescript)
class StackTest(MappingRule): '''test battery for the ContextStack''' mapping = { "close last tag": ContextSeeker([ L(S(["cancel"], None), S(["html spoken"], close_last_spoken, use_spoken=True), S(["span", "div"], close_last_rspec, use_rspec=True)) ]), "html": R(Text("<html>"), rspec="html spoken"), "divider": R(Text("<div>"), rspec="div"), "span": R(Text("<span>"), rspec="span"), "backward seeker [<text>]": ContextSeeker([ L(S(["ashes"], Text("ashes1 [%(text)s] ")), S(["bravery"], Text("bravery1 [%(text)s] "))), L(S(["ashes"], Text("ashes2 [%(text)s] ")), S(["bravery"], Text("bravery2 [%(text)s] "))) ]), "forward seeker [<text>]": ContextSeeker(forward=[ L(S(["ashes"], Text("ashes1 [%(text)s] ")), S(["bravery"], Text("bravery1 [%(text)s] "))), L(S(["ashes"], Text("ashes2 [%(text)s] ")), S(["bravery"], Text("bravery2 [%(text)s] "))) ]), "asynchronous test": AsynchronousAction([ L(S(["ashes", "charcoal"], print_time, None), S(["bravery"], Text, "bravery1")) ], time_in_seconds=0.2, repetitions=20, finisher=Text(FINISHER_TEXT), blocking=False), "ashes": RegisteredAction(Text("ashes _ "), rspec="ashes"), "bravery": RegisteredAction(Text("bravery _ "), rspec="bravery"), "charcoal <text> [<n>]": R(Text("charcoal _ %(text)s"), rspec="charcoal"), "test confirm action": ConfirmAction(Key("a"), rdescript="Confirm Action Test", instructions="some words here"), "test box action": BoxAction(lambda data: _abc(data), rdescript="Test Box Action", box_type=settings.QTYPE_DEFAULT, log_failure=True), } extras = [Dictation("text"), Dictation("text2"), IntegerRefST("n", 1, 5)] defaults = {"text": "", "text2": ""}
def __init__(self, base, rspec="default", rdescript="unnamed command (RA)"): mutable_integer = {"value": 0} def check_response( ): # signals to the stack to cease waiting, return True terminates return mutable_integer["value"] != 0 self.mutable_integer = mutable_integer AsynchronousAction.__init__( self, [L(S(["cancel"], check_response, None))], 1, 60, rdescript, False ) # cannot block, if it does, it'll block its own confirm command self.base = base self.rspec = rspec
def record_from_history(self): # save the list as it was when the command was spoken self.nexus.preserved = self.nexus.history[:] # format for display formatted = "" for t in self.nexus.preserved: for w in t: formatted += w.split("\\")[0] + "[w]" formatted += "[s]" # use a response window to get a spec and word sequences for the new macro h_launch.launch(settings.QTYPE_RECORDING, data=formatted) on_complete = AsynchronousAction.hmc_complete(lambda data: self.add_recorded_macro(data), self.nexus) AsynchronousAction([L(S(["cancel"], on_complete))], time_in_seconds=0.5, repetitions=300, blocking=False).execute()
def __init__(self, receiver, rspec="default", rdescript="unnamed command (BA)", repetitions=60, box_type=settings.QTYPE_DEFAULT, box_settings={}, log_failure=False): _ = {"tries": 0} self._ = _ # signals to the stack to cease waiting, return True terminates def check_for_response(): try: _data = self.nexus().comm.get_com("hmc").get_message() except Exception: if log_failure: utilities.simple_log() _["tries"] += 1 if _["tries"] > 9: return True # try 10 times max if there's no Homonculus response else: return False if _data is None: return False try: _data.append(_["dragonfly_data"] ) # pass dragonfly data into receiver function _["dragonfly_data"] = None receiver(_data) except Exception: if log_failure: utilities.simple_log() return True AsynchronousAction.__init__( self, # cannot block, if it does, it'll block its own confirm command [L(S(["cancel"], check_for_response))], 1, repetitions, rdescript, blocking=False) self.rspec = rspec self.box_type = box_type self.box_settings = box_settings # custom instructions for setting up the tk window ("Homunculus") self.log_failure = log_failure
def _create_asynchronous(self, n): if len(self.nexus.history) == 0: return last_utterance_index = 1 if settings.WSR: # ContextStack adds the word to history before executing it if len(self.nexus.history) == 1: return last_utterance_index = 2 utterance = [ str(x) for x in " ".join(self.nexus.history[ len(self.nexus.history) - last_utterance_index]).split() ] if utterance[0] == "again": return forward = [L(S(["cancel"], lambda: self._repeat(utterance)))] AsynchronousAction(forward, rdescript="Repeat Last Action", time_in_seconds=0.2, repetitions=int(n), blocking=False).execute()
def __init__(self, node, nexus, is_reset=False): first = False if self.master_node is None: self.master_node = node self.nexus = nexus '''self.post is added to every entry in the mapping; its purpose is to handle cancels; if it detects another of itself, it does nothing; but looking forward, won't it never find itself? how is it that the node isn't constantly getting reset? ''' self.post = ContextSeeker(forward=[ L(S(["cancel"], lambda: self.reset_node(), consume=False), S([self.master_node.spec], lambda: None, consume=False)) ], rspec=self.master_node.spec) self.post.set_nexus(nexus) first = True SelfModifyingRule.__init__(self, self.master_node.spec, refresh=False) self.refresh(node, first, is_reset)
class Navigation(MergeRule): non = NavigationNon pronunciation = CCRMerger.CORE[1] mapping = { # "periodic" repeats whatever comes next at 1-second intervals until "cancel" is spoken or 100 tries occur "periodic": ContextSeeker(forward=[L(S(["cancel"], lambda: None), \ S(["*"], \ lambda fnparams: UntilCancelled(Mimic(*filter(lambda s: s != "periodic", fnparams)), 1).execute(), \ use_spoken=True))]), # VoiceCoder-inspired -- these should be done at the IDE level "fill <target>": R(Key("escape, escape, end"), show=False) + AsynchronousAction([L(S(["cancel"], Function(context.fill_within_line, nexus=_NEXUS))) ], time_in_seconds=0.2, repetitions=50, rdescript="Fill" ), "jump in": AsynchronousAction([L(S(["cancel"], context.nav, ["right", "(~[~{~<"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: In" ), "jump out": AsynchronousAction([L(S(["cancel"], context.nav, ["right", ")~]~}~>"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: Out" ), "jump back": AsynchronousAction([L(S(["cancel"], context.nav, ["left", "(~[~{~<"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: Back" ), "jump back in": AsynchronousAction([L(S(["cancel"], context.nav, ["left", "(~[~{~<"])) ], finisher=Key("right"), time_in_seconds=0.1, repetitions=50, rdescript="Jump: Back In" ), # keyboard shortcuts 'salve': R(Key("c-s"), rspec="save", rdescript="Save"), 'slap [<nnavi50>]': R(Key("enter"), rspec="slap", rdescript="Enter")* Repeat(extra="nnavi50"), 'slap up': R(Key("escape, up, end, enter"), rspec="slap up", rdescript="Line Above"), 'slap down': R(Key("escape, end, enter"), rspec="slap down", rdescript="Line Below"), 'curslap': R(Key("escape, lbrace, rbrace, left, enter"), rspec="curslap", rdescript="Curly New Line"), 'north': R(Key("c-home"), rspec="north", rdescript="Ctrl Home"), 'south': R(Key("c-end"), rspec="south", rdescript="Ctrl End"), 'east': R(Key("end"), rspec="east", rdescript="End"), 'west': R(Key("home"), rspec="west", rdescript="Home"), 'page up': R(Key("pgup"), rspec="page up", rdescript="Page Up"), 'page down': R(Key("pgdown"), rspec="page down", rdescript="Page Down"), "(<mtn_dir> | <mtn_mode> [<mtn_dir>]) [(<nnavi500> | <extreme>)]": R(Function(textformat.master_text_nav), rdescript="Keyboard Text Navigation"), "<short_mode> <key> [<nnavi500>]": R(Function(textformat.master_short), rdescript="Keyboard Shortcut"), "<short_mode> <mouse_action>": R(Function(textformat.master_short_mouse), rdescript="Mouse Shortcut"), "hold <short_mode>": R(Function(textformat.hold_modifier), rdescript="Hold Modifier"), "alt": R(Key("alt"), rdescript="Alt"), "wind": R(Key("win"), rdescript="Win"), "null": R(Key("n, u, l, l"), rdescript="Null"), "stoosh [<nnavi500>]": R(Key("c-c")+Function(navigation.clipboard_to_file, nexus=_NEXUS), rspec="stoosh", rdescript="Copy"), "cut [<nnavi500>]": R(Key("c-x")+Function(navigation.clipboard_to_file, nexus=_NEXUS), rspec="cut", rdescript="Cut"), "spark [<nnavi500>]": R(Function(navigation.drop, nexus=_NEXUS), rspec="spark", rdescript="Paste"), "deli [<nnavi50>]": R(Key("del/5"), rspec="deli", rdescript="Delete") * Repeat(extra="nnavi50"), "clear [<nnavi50>]": R(Key("backspace/5:%(nnavi50)d"), rspec="clear", rdescript="Backspace"), SymbolSpecs.CANCEL: R(Key("escape"), rspec="cancel", rdescript="Cancel Action"), "shackle": R(Key("home/5, s-end"), rspec="shackle", rdescript="Select Line"), "(tell | tau) <semi>": R(Function(navigation.next_line), rspec="tell dock", rdescript="Complete Line"), "duple [<nnavi50>]": R(Key("escape, home, s-end, c-c, end, enter, c-v"), rspec="duple", rdescript="Duplicate Line") * Repeat(extra="nnavi50"), "Kraken": R(Key("c-space"), rspec="Kraken", rdescript="Control Space"), # text formatting "set format (<spacing> <capitalization> | <capitalization> | <spacing>)": R(Function(textformat.set_text_format), rdescript="Set Text Format"), "clear caster formatting": R(Function(textformat.clear_text_format), rdescript="Clear Caster Formatting"), "peek format": R(Function(textformat.peek_text_format), rdescript="Peek Format"), "camel <textnv>": R(Function(textformat.master_format_text_camel), rdescript="Camel Case"), "pascal <textnv>": R(Function(textformat.master_format_text_pascal), rdescript="Pascal Case"), "dock mel <textnv>": R(Key("dot")+Function(textformat.master_format_text_camel), rdescript="Dot Camel Case"), "(dop|dot) scal <textnv>": R(Key("dot")+Function(textformat.master_format_text_pascal), rdescript="Dot Pascal Case"), "(<spacing> <capitalization> | <capitalization> | <spacing>) <textnv>": R(Function(textformat.master_format_text), rdescript="Text Format"), "format <textnv>": R(Function(textformat.prior_text_format), rdescript="Last Text Format"), "dredge": R(Key("a-tab"), rdescript="Alt-Tab"), } extras = [ alphanumeric.get_key_choice("key"), Choice( "short_mode", { "shift": "s", "troll": "c", "alt": "a", "wind": "w", "trot": "ca", "shoal": "cs", "tron": "wc", "shalt": "sa", "walt": "wa", "shin": "ws", "trash": "cas" }), Choice( "mouse_action", { "kick": "left", "kick mid": "middle", "psychic": "right", "dub kick": "left:2" }), IntegerRefST("nnavi50", 1, 50), IntegerRefST("nnavi500", 1, 500), Dictation("textnv"), Choice("capitalization", { "scream": 1, "scal": 2, "mel": 3, "tense": 4, "laws": 5 }), Choice("spacing", { "smash": 1, "spine": 2, "snake": 3 }), Choice("semi", { "dock": ";", "doc": ";", "sink": "" }), navigation.TARGET_CHOICE, navigation.get_direction_choice("mtn_dir"), Choice("mtn_mode", { "shin": "s", "queue": "cs", "fly": "c", }), Choice("extreme", { "Wally": "way", }), ] defaults = { "nnavi500": 1, "nnavi50": 1, "textnv": "", "capitalization": 0, "spacing": 0, "mtn_mode": None, "mtn_dir": "right", "extreme": None }
def test_seeker_consume(self): '''seeker actions have the option to not/consume their triggers; that is, the trigger actions do not execute and only act as triggers''' mutable_string = {"value": ""} def append_a(): mutable_string["value"] += "a" def append_b(): mutable_string["value"] += "b" def append_c(): mutable_string["value"] += "c" def append_d(): mutable_string["value"] += "d" def append_e(): mutable_string["value"] += "e" def append_f(): mutable_string["value"] += "f" '''create context levels''' set_1_1 = S(["arch"], append_a) set_1_2 = S(["bell"], append_b) set_1_2.consume = False level_1 = L(set_1_1, set_1_2) set_2_1 = S(["cellar"], append_c) set_2_2 = S(["door"], append_d) level_2 = L(set_2_1, set_2_2) set_3_1 = S(["echo"], append_e) set_3_2 = S(["frame"], append_f) set_3_2.consume = False level_3 = L(set_3_1, set_3_2) '''create context seeker''' levels = [level_1, level_2, level_3] seeker = ContextSeeker(forward=levels) seeker.set_nexus(self.nexus) '''create context seeker stack item''' alt = MockAlternative(u"my", u"spoken", u"words") stack_seeker = StackItemSeeker(seeker, {"_node": alt}) '''add it''' self.nexus.state.add(stack_seeker) '''make 3 fake triggering RegisteredActions; the first and third do not consume their triggers''' trigger1 = RegisteredAction(Function(append_a), rspec="bell") trigger2 = RegisteredAction(Function(append_c), rspec="door") trigger3 = RegisteredAction(Function(append_e), rspec="frame") trigger1.set_nexus(self.nexus) trigger2.set_nexus(self.nexus) trigger3.set_nexus(self.nexus) '''make fake StackItemRegisteredActions''' alt2 = MockAlternative(u"my", u"spoken", u"words") sira1 = StackItemRegisteredAction(trigger1, {"_node": alt2}) sira2 = StackItemRegisteredAction(trigger2, {"_node": alt2}) sira3 = StackItemRegisteredAction(trigger3, {"_node": alt2}) '''add them''' self.nexus.state.add(sira1) self.nexus.state.add(sira2) self.nexus.state.add(sira3) self.assertEqual(mutable_string["value"], "aebdf")
def test_actions_cleaned(self): '''these test functions should stay in sync with the clean methods for each stack action''' def registered_is_clean(r): return r.dragonfly_data is None and r.base is None def seeker_is_clean(s): result = True levels = [] if s.back is not None: levels += s.back if s.forward is not None: levels += s.forward for context_level in levels: result &= context_level.dragonfly_data is None return result def asynchronous_is_clean(a): return a.closure is None '''mock words being the same doesn't matter for this test, or most tests''' alt = MockAlternative(u"my", u"spoken", u"words") '''make fake NullActions''' action1 = NullAction(rspec="barkley") action2 = NullAction(rspec="gaiden") action3 = NullAction(rspec="is") action4 = NullAction(rspec="awesome") action1.set_nexus(self.nexus) action2.set_nexus(self.nexus) action3.set_nexus(self.nexus) action4.set_nexus(self.nexus) '''make fake StackItemRegisteredActions''' sira1 = StackItemRegisteredAction(action1, {"_node": alt}) sira2 = StackItemRegisteredAction(action2, {"_node": alt}) sira3 = StackItemRegisteredAction(action3, {"_node": alt}) sira4 = StackItemRegisteredAction(action4, {"_node": alt}) '''should not be clean before it's executed''' self.assertFalse(registered_is_clean(sira1)) '''add first one for backward seeker''' self.nexus.state.add(sira1) '''should be clean as soon as it's executed''' self.assertTrue(registered_is_clean(sira1)) '''make backward seeker''' back_seeker = ContextSeeker( back=[L(S(["minecraft"], Function(lambda: None)))]) back_seeker.set_nexus(self.nexus) '''create backward seeker stack item''' stack_seeker = StackItemSeeker(back_seeker, {"_node": alt}) '''add it''' self.nexus.state.add(stack_seeker) '''levels should be clean as soon as it's executed''' self.assertTrue( registered_is_clean(stack_seeker) and seeker_is_clean(stack_seeker)) # '''make forward seeker''' forward_seeker = ContextSeeker(forward=[ L(S(["cave"], Function(lambda: None))), L(S(["story"], Function(lambda: None))) ]) forward_seeker.set_nexus(self.nexus) '''create context seeker stack item''' stack_seeker2 = StackItemSeeker(forward_seeker, {"_node": alt}) '''add it''' self.nexus.state.add(stack_seeker2) self.nexus.state.add(sira2) '''levels should not be clean before seeker is executed''' self.assertFalse( registered_is_clean(stack_seeker2) or seeker_is_clean(stack_seeker2)) self.nexus.state.add(sira3) '''levels should be clean as soon as it's executed''' self.assertTrue( registered_is_clean(stack_seeker2) and seeker_is_clean(stack_seeker2)) # '''make asynchronous action''' asynchronous = AsynchronousAction( [L(S(["eternal", "daughter", "awesome"], lambda: None))], blocking=False) asynchronous.set_nexus(self.nexus) '''make StackItemAsynchronous''' sia1 = StackItemAsynchronous(asynchronous, {"_node": alt}) '''add it''' self.nexus.state.add(sia1) '''closure should not be clean before asynchronous is executed''' self.assertFalse( registered_is_clean(sia1) or seeker_is_clean(sia1) or asynchronous_is_clean(sia1)) self.nexus.state.add(sira4) '''closure should be clean after asynchronous is executed''' self.assertTrue( registered_is_clean(sia1) and seeker_is_clean(sia1) and asynchronous_is_clean(sia1))
def test_use_spoken_words_or_rspec(self): '''seekers can take the spoken words or rspecs of their trigger actions and feed them to the function objects of their ContextSets''' '''make triggers for context seekers (2 forward, 2 backward / 2 spoken, 2 rspec)''' action1 = NullAction(rspec="alpha") action2 = NullAction(rspec="_") action3 = NullAction(rspec="charlie") action4 = NullAction(rspec="_") action1.set_nexus(self.nexus) action2.set_nexus(self.nexus) action3.set_nexus(self.nexus) action4.set_nexus(self.nexus) alt = MockAlternative(u"_") spec1 = [u"here", u"are", u"words"] spec2 = [u"some", u"more", u"words"] sira1 = StackItemRegisteredAction(action1, {"_node": alt}) sira2 = StackItemRegisteredAction(action2, {"_node": MockAlternative(*spec1)}) sira3 = StackItemRegisteredAction(action3, {"_node": alt}) sira4 = StackItemRegisteredAction(action4, {"_node": MockAlternative(*spec2)}) # mutable_integer = {"value": 0} def increment(): mutable_integer["value"] += 1 # def _1(params): if params == "alpha": increment() def _2(params): if params == spec1: increment() def _3(params): if params == "charlie": increment() def _4(params): if params == spec2: increment() '''make seekers''' back_seeker1 = ContextSeeker( back=[L(S(["alpha"], _1, parameters="_", use_rspec=True))], rspec="_") back_seeker2 = ContextSeeker( back=[L(S(["_"], _2, parameters=["_"], use_spoken=True))], rspec="_") forward_seeker1 = ContextSeeker( forward=[L(S(["_"], _3, parameters="_", use_rspec=True))], rspec="_") forward_seeker2 = ContextSeeker( forward=[L(S(["delta"], _4, parameters=["_"], use_spoken=True))], rspec="_") back_seeker1.set_nexus(self.nexus) back_seeker2.set_nexus(self.nexus) forward_seeker1.set_nexus(self.nexus) forward_seeker2.set_nexus(self.nexus) '''create seeker stack items''' stack_seeker_b1 = StackItemSeeker(back_seeker1, {"_node": alt}) stack_seeker_b2 = StackItemSeeker(back_seeker2, {"_node": alt}) stack_seeker_f1 = StackItemSeeker(forward_seeker1, {"_node": alt}) stack_seeker_f2 = StackItemSeeker(forward_seeker2, {"_node": alt}) # '''trigger the first backward seeker; uses rspec ("alpha") ''' self.nexus.state.add(sira1) self.nexus.state.add(stack_seeker_b1) self.assertEqual(mutable_integer["value"], 1) '''trigger the second backward seeker; uses spoken words (spec1) ''' self.nexus.state.add(sira2) self.nexus.state.add(stack_seeker_b2) self.assertEqual(mutable_integer["value"], 2) '''trigger the first forward seeker; uses rspec ("charlie") ''' self.nexus.state.add(stack_seeker_f1) self.nexus.state.add(sira3) self.assertEqual(mutable_integer["value"], 3) '''trigger the first forward seeker; uses spoken words (spec2) ''' self.nexus.state.add(stack_seeker_f2) self.nexus.state.add(sira4) self.assertEqual(mutable_integer["value"], 4)
class Navigation(MergeRule): non = NavigationNon pronunciation = CCRMerger.CORE[1] mapping = { # "periodic" repeats whatever comes next at 1-second intervals until "cancel" is spoken or 100 tries occur "periodic": ContextSeeker(forward=[L(S(["cancel"], lambda: None), \ S(["*"], \ lambda fnparams: UntilCancelled(Mimic(*filter(lambda s: s != "periodic", fnparams)), 1).execute(), \ use_spoken=True))]), # VoiceCoder-inspired -- these should be done at the IDE level "fill <target>": R(Key("escape, escape, end"), show=False) + AsynchronousAction([L(S(["cancel"], Function(context.fill_within_line, nexus=_NEXUS))) ], time_in_seconds=0.2, repetitions=50, rdescript="Fill" ), "jump in": AsynchronousAction([L(S(["cancel"], context.nav, ["right", "(~[~{~<"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: In" ), "jump out": AsynchronousAction([L(S(["cancel"], context.nav, ["right", ")~]~}~>"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: Out" ), "jump back": AsynchronousAction([L(S(["cancel"], context.nav, ["left", "(~[~{~<"])) ], time_in_seconds=0.1, repetitions=50, rdescript="Jump: Back" ), "jump back in": AsynchronousAction([L(S(["cancel"], context.nav, ["left", "(~[~{~<"])) ], finisher=Key("right"), time_in_seconds=0.1, repetitions=50, rdescript="Jump: Back In" ), # keyboard shortcuts 'save': R(Key("c-s"), rspec="save", rdescript="Save"), 'shock [<nnavi50>]': R(Key("enter"), rspec="shock", rdescript="Enter")* Repeat(extra="nnavi50"), "(<mtn_dir> | <mtn_mode> [<mtn_dir>]) [(<nnavi500> | <extreme>)]": R(Function(textformat.master_text_nav), rdescript="Keyboard Text Navigation"), "stoosh [<nnavi500>]": R(Key("c-c")+Function(navigation.clipboard_to_file, nexus=_NEXUS), rspec="stoosh", rdescript="Copy"), "cut [<nnavi500>]": R(Key("c-x")+Function(navigation.clipboard_to_file, nexus=_NEXUS), rspec="cut", rdescript="Cut"), "spark [<nnavi500>]": R(Function(navigation.drop, nexus=_NEXUS), rspec="spark", rdescript="Paste"), "deli [<nnavi50>]": R(Key("del/5"), rspec="deli", rdescript="Delete") * Repeat(extra="nnavi50"), "clear [<nnavi50>]": R(Key("backspace/5:%(nnavi50)d"), rspec="clear", rdescript="Backspace"), SymbolSpecs.CANCEL: R(Key("escape"), rspec="cancel", rdescript="Cancel Action"), "shackle": R(Key("home/5, s-end"), rspec="shackle", rdescript="Select Line"), "(tell | tau) <semi>": R(Function(navigation.next_line), rspec="tell dock", rdescript="Complete Line"), "duple [<nnavi50>]": R(Key("escape, home, s-end, c-c, end, enter, c-v"), rspec="duple", rdescript="Duplicate Line") * Repeat(extra="nnavi50"), "Kraken": R(Key("c-space"), rspec="Kraken", rdescript="Control Space"), # text formatting "set format (<capitalization> <spacing> | <capitalization> | <spacing>) (bow|bowel)": R(Function(textformat.set_text_format), rdescript="Set Text Format"), "clear caster formatting": R(Function(textformat.clear_text_format), rdescript="Clear Caster Formatting"), "peek format": R(Function(textformat.peek_text_format), rdescript="Peek Format"), "(<capitalization> <spacing> | <capitalization> | <spacing>) (bow|bowel) <textnv> [brunt]": R(Function(textformat.master_format_text), rdescript="Text Format"), "format <textnv>": R(Function(textformat.prior_text_format), rdescript="Last Text Format"), "<word_limit> format <textnv>": R(Function(textformat.partial_format_text), rdescript="Partial Text Format"), "dredge": R(Key("a-tab"), rdescript="Alt-Tab"), } extras = [ IntegerRefST("nnavi50", 1, 50), IntegerRefST("nnavi500", 1, 500), Dictation("textnv"), Choice("capitalization", { "yell": 1, "tie": 2, "Gerrish": 3, "sing": 4, "laws": 5 }), Choice("spacing", { "gum": 1, "gun": 1, "spine": 2, "snake": 3 }), Choice("semi", { "dock": ";", "doc": ";", "sink": "" }), Choice("word_limit", { "single": 1, "double": 2, "triple": 3, "Quadra": 4 }), navigation.TARGET_CHOICE, navigation.get_direction_choice("mtn_dir"), Choice("mtn_mode", { "shin": "s", "queue": "cs", "fly": "c", }), Choice("extreme", { "Wally": "way", }), ] defaults = { "nnavi500": 1, "nnavi50": 1, "textnv": "", "capitalization": 0, "spacing": 0, "mtn_mode": None, "mtn_dir": "right", "extreme": None }
def __init__(self, action, t=3): AsynchronousAction.__init__(self, [L(S(["cancel"], action))], t, 100, "UC", False, None) self.show = True
class NavigationNon(MappingRule): mapping = { "<direction> <time_in_seconds>": AsynchronousAction( [L(S(["cancel"], Key("%(direction)s"), consume=False))], repetitions=1000, blocking=False), "erase multi clipboard": R(Function(navigation.erase_multi_clipboard, nexus=_NEXUS), rdescript="Erase Multi Clipboard"), "find": R(Key("c-f"), rdescript="Find"), "find next [<n>]": R(Key("f3"), rdescript="Find Next") * Repeat(extra="n"), "find prior [<n>]": R(Key("s-f3"), rdescript="Find Prior") * Repeat(extra="n"), "find everywhere": R(Key("cs-f"), rdescript="Find Everywhere"), "replace": R(Key("c-h"), rdescript="Replace"), "(F to | F2)": R(Key("f2"), rdescript="Key: F2"), "(F six | F6)": R(Key("f6"), rdescript="Key: F6"), "(F nine | F9)": R(Key("f9"), rdescript="Key: F9"), "[show] context menu": R(Key("s-f10"), rdescript="Context Menu"), 'kick': R(Function(navigation.kick, nexus=_NEXUS), rdescript="Mouse: Left Click"), 'kick mid': R(Function(navigation.kick_middle, nexus=_NEXUS), rdescript="Mouse: Middle Click"), 'psychic': R(Function(navigation.kick_right, nexus=_NEXUS), rdescript="Mouse: Right Click"), '(kick double|double kick)': R(Function(navigation.kick, nexus=_NEXUS) * Repeat(2), rdescript="Mouse: Double Click"), "shift right click": R(Key("shift:down") + Mouse("right") + Key("shift:up"), rdescript="Mouse: Shift + Right Click"), "curse <direction> [<direction2>] [<nnavi500>] [<dokick>]": R(Function(navigation.curse), rdescript="Curse"), "scree <direction> [<nnavi500>]": R(Function(navigation.wheel_scroll), rdescript="Wheel Scroll"), "colic": R(Key("control:down") + Mouse("left") + Key("control:up"), rdescript="Mouse: Ctrl + Left Click"), "garb [<nnavi500>]": R(Mouse("left") + Mouse("left") + Key("c-c") + Function(navigation.clipboard_to_file, nexus=_NEXUS), rdescript="Highlight @ Mouse + Copy"), "drop [<nnavi500>]": R(Mouse("left") + Mouse("left") + Function(navigation.drop, nexus=_NEXUS), rdescript="Highlight @ Mouse + Paste"), "sure stoosh": R(Key("c-c"), rdescript="Simple Copy"), "sure cut": R(Key("c-x"), rdescript="Simple Cut"), "sure spark": R(Key("c-v"), rdescript="Simple Paste"), "undo [<n>]": R(Key("c-z"), rdescript="Undo") * Repeat(extra="n"), "redo [<n>]": R(Key("c-y"), rdescript="Redo") * Repeat(extra="n"), "refresh": R(Key("c-r"), rdescript="Refresh"), "maxiwin": R(Key("w-up"), rdescript="Maximize Window"), "move window": R(Key("a-space, r, a-space, m"), rdescript="Move Window"), "window (left | lease) [<n>]": R(Key("w-left"), rdescript="Window Left") * Repeat(extra="n"), "window (right | ross) [<n>]": R(Key("w-right"), rdescript="Window Right") * Repeat(extra="n"), "monitor (left | lease) [<n>]": R(Key("sw-left"), rdescript="Monitor Left") * Repeat(extra="n"), "monitor (right | ross) [<n>]": R(Key("sw-right"), rdescript="Monitor Right") * Repeat(extra="n"), "(next | prior) window": R(Key("ca-tab, enter"), rdescript="Next Window"), "switch (window | windows)": R(Key("ca-tab"), rdescript="Switch Window") * Repeat(extra="n"), "next tab [<n>]": R(Key("c-pgdown"), rdescript="Next Tab") * Repeat(extra="n"), "prior tab [<n>]": R(Key("c-pgup"), rdescript="Previous Tab") * Repeat(extra="n"), "close tab [<n>]": R(Key("c-w/20"), rdescript="Close Tab") * Repeat(extra="n"), "elite translation <text>": R(Function(alphanumeric.elite_text), rdescript="1337 Text"), } extras = [ Dictation("text"), Dictation("mim"), IntegerRefST("n", 1, 50), IntegerRefST("nnavi500", 1, 500), Choice( "time_in_seconds", { "super slow": 5, "slow": 2, "normal": 0.6, "fast": 0.1, "superfast": 0.05 }), navigation.get_direction_choice("direction"), navigation.get_direction_choice("direction2"), navigation.TARGET_CHOICE, Choice("dokick", { "kick": 1, "psychic": 2 }), Choice("wm", { "ex": 1, "tie": 2 }), ] defaults = { "n": 1, "mim": "", "nnavi500": 1, "direction2": "", "dokick": 0, "text": "", "wm": 2 }
class DevRule(MappingRule): mapping = { # 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": Function(bring_test) + FocusWindow("explorer"), "reserved word <text>": Key("dquote,dquote,left") + Text("%(text)s") + Key("right, colon, tab/5:5") + Text("Text(\"%(text)s\"),"), "refresh ccr directory": Function(ccr.refresh_from_files ), # will need to disable and reenable language "Agrippa <filetype> <path>": Function(grep_this), # experimental/incomplete commands "zone test": R(Text("a") + Text("b")), "experiment <text>": Function(experiment), # # "dredge [<id> <text>]": Function(dredge), "close last tag": ContextSeeker([ L(S(["cancel"], None), S(["html spoken"], close_last_spoken, use_spoken=True), S(["span", "div"], close_last_rspec, use_rspec=True)) ]), "html": R(Text("<html>"), rspec="html spoken"), "divider": R(Text("<div>"), rspec="div"), "span": R(Text("<span>"), rspec="span"), "backward seeker [<text>]": ContextSeeker([ L(S(["ashes"], Text("ashes1 [%(text)s] ")), S(["bravery"], Text("bravery1 [%(text)s] "))), L(S(["ashes"], Text("ashes2 [%(text)s] ")), S(["bravery"], Text("bravery2 [%(text)s] "))) ]), "forward seeker [<text>]": ContextSeeker(forward=[ L(S(["ashes"], Text("ashes1 [%(text)s] ")), S(["bravery"], Text("bravery1 [%(text)s] "))), L(S(["ashes"], Text("ashes2 [%(text)s] ")), S(["bravery"], Text("bravery2 [%(text)s] "))) ]), "never-ending": AsynchronousAction([ L(S(["ashes", "charcoal"], print_time, None), S(["bravery"], Text, "bravery1")) ], time_in_seconds=0.2, repetitions=20, finisher=Text("finisher successful")), "ashes": RegisteredAction(Text("ashes fall "), rspec="ashes"), "bravery": RegisteredAction(Text("bravery is weak "), rspec="bravery"), "charcoal boy <text> [<n>]": R(Text("charcoal is dirty %(text)s"), rspec="charcoal"), "test confirm action": ConfirmAction(Key("a"), rdescript="Confirm Action Test"), "convert node <n>": R(Key("cs-right, cs-right/5:%(n)d, cs-right, c-x, c-v, comma") + Text("Text()") + Key("left, c-v"), rdescript="Convert Node"), "text action": R(Text("Text()") + Key("left"), rdescript="Node 2"), "long conversion <text>": R(Key("c-x") + Text("\"%(text)s\", Text(") + Key("c-v, rparen"), rdescript="Node 3"), } extras = [ Dictation("text"), Dictation("textnv"), IntegerRef("n", 1, 5), Choice("id", { "R": 1, "M": 2, }), Choice("path", { "natlink": "c:/natlink/natlink", "sea": "C:/", }), Choice("filetype", { "java": "*.java", "python": "*.py", }), ] defaults = {"text": "", "id": None}