def __init__(self, name, max=4, min=1, default=None): Repetition.__init__(self, child=Empty(), min=min, max=max + 1, name=name, default=default)
def __init__(self, name, command, terminal_command, context): # Here we define this rule's spoken-form and special elements. Note that # nested_repetitions is the only one that contains Repetitions, and it # is not itself repeated. This is for performance purposes. spec = ("[<sequence>] " "[<nested_repetitions>] " "[<terminal_command>] " "[<final_command>]") extras = [ Repetition(command, min=1, max=5, name="sequence"), Alternative([RuleRef(rule=character_rule)], name="nested_repetitions"), ElementWrapper("terminal_command", terminal_command), RuleRef(rule=final_rule, name="final_command"), ] defaults = { "sequence": [], "nested_repetitions": None, "terminal_command": None, "final_command": None, } CompoundRule.__init__(self, name=name, spec=spec, extras=extras, defaults=defaults, exported=True, context=context)
class VimCommand(CompoundRule): spec = ('[<app>] [<literal>]') extras = [ Repetition(Alternative([ruleCommand, RuleRef(Insertion())]), max=10, name='app'), RuleRef(LiteralIdentifierInsertion(), name='literal') ] def _process_recognition(self, node, extras): insertion_buffer = [] commands = [] if 'app' in extras: for chunk in extras['app']: commands.extend(chunk) if 'literal' in extras: commands.extend(extras['literal']) for command in commands: mode, command = command if mode == 'i': insertion_buffer.append(command) else: execute_insertion_buffer(insertion_buffer) insertion_buffer = [] command.execute(extras) execute_insertion_buffer(insertion_buffer)
class ExampleRule(MappingRule): mapping = { # Recognise 'hello' followed by arbitrary dictation. # This mapping cannot be matched using Pocket Sphinx because the # engine's support for dictation has been temporarily disabled. "hello <dictation>": Function(print_, dict(dictation="x")), # You still can use Mimic or engine.mimic() to match dictation. "say hello world": Mimic("hello", "WORLD"), # Update and recognise from a dragonfly list. "update list": Function(update_list), "<lst>": Function(print_, dict(lst="x")), # Command to type numbers, e.g. 'type one two three'. "type <numbers>": Function(type_numbers), # Write transcript files used for training models. "(make|write) transcripts": Function(write_transcripts), } extras = [ Dictation("dictation"), ListRef("lst", lst), Repetition(IntegerRef("n", 1, 20), min=1, max=16, name="numbers"), ]
def __init__( self, name, options, alias=None, base_options=[], ): alias = alias or name self.base_options = base_options super(GitCommandRule, self).__init__( name=name, spec='[help] ({}) <options>'.format(alias), exported=False, extras=[ Repetition( name='options', min=0, max=10, child=RuleRef( MappingRule( name=name + '_options', mapping=options, exported=False, )), ) ], )
def __init__(self, name): element = Repetition(LetterRef(), min=1, max=32, name=name) def modifier(v): return ','.join(v) super(LetterSequenceRef, self).__init__(element, modifier)
class SpellingRule(CompoundRule): spec = "(letters|spell) <letter_sequence>" extras = [ Repetition(chc_base.letter, min=1, max=26, name="letter_sequence") ] def _process_recognition(self, node, extras): for letter in extras["letter_sequence"]: T(letter).execute()
class MyBasicRule(BasicRule): element = Repetition( Alternative(( Literal("test one", value=Function(lambda: func(1))), Literal("test two", value=Function(lambda: func(2))), Literal("test three", value=Function(lambda: func(3))), )), 1, 5 )
def __init__(self, name = None, repeatables = None, finishers = None, max = 10, exported = True): if repeatables is None: repeatables = self.repeatables if finishers is None: finishers = self.finishers repeatablesRule = Repetition(Alternative(repeatables), min=1, max=max, name='repeatables') finishersRule = Alternative(finishers, name='finishers') extras = [repeatablesRule, finishersRule] MappingRule.__init__(self, name = name, extras = extras, exported = exported)
def __init__(self, mapping, extras=None, defaults=None): mapping_rule = MappingRule(mapping=mapping, extras=extras, defaults=defaults, exported=False) single = RuleRef(rule=mapping_rule) series = Repetition(single, min=1, max=16, name="series") compound_spec = "<series>" compound_extras = [series] CompoundRule.__init__(self, spec=compound_spec, extras=compound_extras, exported=True)
def __init__(self, mapping_rule): single = RuleRef(rule=mapping_rule) series = Repetition(single, min=1, max=16, name="series") compound_spec = "<series>" compound_extras = [series] CompoundRule.__init__(self, spec=compound_spec, extras=compound_extras, exported=True)
def create(*from_rules, max_repetitions=50): name = "CCR" rules = [] for rule in from_rules: rules.append(RuleRef(rule=rule)) name += "_" + rule.name single_action = Alternative(rules) sequence = Repetition(single_action, min=1, max=max_repetitions, name="sequence") return CCRRule(name=name, spec=CCRRule.spec, extras=[sequence])
def __init__(self, name, context, rules): self._name = name rule_refs = list() for rule_ in rules: rule_refs.append(RuleRef(rule=rule_)) # max should not be greater than 7 self.extras.append( Repetition(Alternative(rule_refs), min=1, max=6, name="sequence")) super(RepeatRule, self).__init__(context=context)
class ColumnModePrintRule(CompoundRule): spec = "<alphabet> <n> stop" extras = [ Repetition(Integer("n", 0, 10), 0, 10, "n"), Repetition(natoAlphabet, 2, 3, "alphabet") ] def _process_recognition(self, node, extras): natoNumbers = extras["alphabet"] numbers = extras["n"] # Move to the correct column press('home') rightPresses = [] for i in range(natoNumbers[0] - 1): rightPresses.append('right') press(rightPresses) if (natoNumberToLetter(natoNumbers[1]) == "n"): typewrite("".join(str(x) for x in numbers)) elif (natoNumberToLetter(natoNumbers[1]) == "t"): if (len(numbers) == 3): typewrite(".0" + str(numbers[0]) + ":" + str(numbers[1]) + str(numbers[2]) + ":00") elif (len(numbers) == 4): typewrite("." + str(numbers[0]) + str(numbers[1]) + ":" + str(numbers[2]) + str(numbers[3]) + ":00") elif (natoNumberToLetter(natoNumbers[1]) == "d"): if (len(numbers) == 3): typewrite("0" + str(numbers[0]) + " - " + str(numbers[1]) + str(numbers[2])) elif (len(numbers) == 4): typewrite( str(numbers[0]) + str(numbers[1]) + " - " + str(numbers[2]) + str(numbers[3])) # Make sure we keep our row selected press(["right", "left"])
def __init__(self, element, name=None, exported=None): """ :param element: element whose value is an ActionBase :param name: """ if name is None: name = self.__class__.__name__ + str(self._repeat_action_rule_count) RepeatActionRule._repeat_action_rule_count += 1 spec = "<sequence> [<n> times]" extras = [Repetition(element, min=1, max=7, name="sequence"), IntegerRef("n", 1, 100), ] self.defaults = {'n': 1} super(RepeatActionRule, self).__init__(name=name, spec=spec, extras=extras, exported=exported)
class ColumnNumberPrintRule(CompoundRule): spec = "<alphabet> <n> stop" extras = [Repetition(Integer("n", 0, 10), 0, 10, "n"), natoAlphabet] def _process_recognition(self, node, extras): natoNumber = extras["alphabet"] numbers = extras["n"] # Move to the correct column press('home') rightPresses = [] for i in range(natoNumber - 1): rightPresses.append('right') press(rightPresses) typewrite("".join(str(x) for x in numbers)) # Make sure we keep our row selected press(["right", "left"])
def makePrefixedCompoundRule(prefix, mappingRule): alts = [] alts.append(RuleRef(rule=mappingRule())) singleAction = Alternative(alts) seq = Repetition(singleAction, min=1, max=16, name="mySequence") class PrefixCompoundRule(CompoundRule): spec = prefix + " <mySequence>" extras = [seq] defaults = {} def _process_recognition(self, node, extras): sequence = extras["mySequence"] for action in sequence: action.execute() release.execute() dynamicName = "Prefix" + prefix + "Rule" PrefixCompoundRule.__name__ = dynamicName PrefixCompoundRule.__qualname__ = dynamicName return PrefixCompoundRule
def _add_repeater(self, matches, top_level_matches): """ Takes a tuple of bools, corresponding to which contexts were matched, and loads a SubGrammar containing a RepeatRule with all relevant commands in. """ matched_commands = [] for command_list in [ l for (l, b) in zip(self.context_commands, matches) if b ]: matched_commands.extend(command_list) matched_commands.extend(self.core_commands) if not matched_commands: return alts = Alternative(matched_commands) repeater = SimpleRule( name="Repeater%s" % self.counter(), element=Repetition(alts, min=1, max=self.MAX_REPETITIONS), context=None, ) subgrammar = SubGrammar("SG%s" % self.counter()) subgrammar.add_rule(repeater) if top_level_matches: command_lists = [ l for (l, b) in zip(self.top_level_commands, top_level_matches) if b ] matched_top_level_commands = process_top_level_commands( command_lists, alts) top_level_rules = SimpleRule( name="CommandsRef%s" % self.counter(), element=Alternative(matched_top_level_commands), ) subgrammar.add_rule(top_level_rules) subgrammar.load() self.grammar_map[matches] = subgrammar
def test_basic_rule(self): """ Verify that BasicRules can be loaded and recognized correctly. """ test = [] func = lambda x: test.append(x) # Test using BasicRule directly. rule = BasicRule(element=Repetition( Alternative(( Literal("test one", value=Function(lambda: func(1))), Literal("test two", value=Function(lambda: func(2))), Literal("test three", value=Function(lambda: func(3))), )), 1, 5 )) self.add_rule(rule) self.recognize("test one test two test three".split()) assert test == [1, 2, 3], "BasicRule was not processed correctly" # Remove the rule and clear the test list. self.grammar.remove_rule(rule) del test[:] # Test using a sub-class of BasicRule. class MyBasicRule(BasicRule): element = Repetition( Alternative(( Literal("test one", value=Function(lambda: func(1))), Literal("test two", value=Function(lambda: func(2))), Literal("test three", value=Function(lambda: func(3))), )), 1, 5 ) self.add_rule(MyBasicRule()) self.recognize("test one test two test three".split()) assert test == [1, 2, 3], "BasicRule was not processed correctly"
class MoveRule(CompoundRule): spec = "<type> <direction> <n>" extras = [ Choice("type", { 'Break': 'Break', 'Move': 'Move' }), Optional( Choice("direction", { 'left': 'left', 'up': 'up', 'down': 'down', 'right': 'right' }), "direction"), Optional(Repetition(Integer("n", 0, 10), 0, 10, "n"), "n") ] def _process_recognition(self, node, extras): numbers = extras["n"] direction = extras["direction"] if (direction == None): direction = 'down' total = "".join(str(x) for x in numbers) if (total == ""): total = "1" total = int(total) presses = [] if (type == "Break"): presses.append('home') for i in range(total): presses.append(direction) press(presses)
def process_top_level_commands(command_lists, alts): """ Once we have begun creating a new subgrammar, we have access to all of the ccr commands which will be active in this context (alts). We now use these to replace the CommandsRef placeholders with Repetition(alts) in a new extras dict, and recreate the top level commands using this dict. """ commands = [] for command_list in command_lists: new_extras = {} for n, e in command_list[0]._extras.items(): if isinstance(e, CommandsRef): new_extras[n] = Repetition(alts, e.min, e.max, e.name, e.default) else: new_extras[n] = e new_command_list = [ BoundCompound(c._spec, new_extras, value=c._value) for c in command_list ] commands.extend(new_command_list) return commands
RuleRef(rule=window_control.NudgeRule()), RuleRef(rule=window_control.ResizeRule()), RuleRef(rule=window_control.StretchRule()), ] try: # putstringcommands is not included in the pushed source, because it contains personal data. from ccr import putstringcommands if putstringcommands.PutStringCommandsRule: alternatives.append(RuleRef(rule=putstringcommands.PutStringCommandsRule())) except (ImportError, NameError) as e: pass single_action = Alternative(alternatives) sequence = Repetition(single_action, min=1, max=16, name="sequence") class ChainRule(CompoundRule): spec = "<sequence>" extras = [ sequence, # Sequence of actions defined above. ] # - node -- root node of the recognition parse tree. # - extras -- dict of the "extras" special elements: # . extras["sequence"] gives the sequence of actions. def _process_recognition(self, node, extras): # print "extras: " + str(extras) # print "sequence: " + str(sequence) # print "node words: " + str(node.words()) # print "node: " + str(node)
def value(self, node): return self.delimiter.join(Repetition.value(self, node))
def __init__(self, delimiter, *args, **kwargs): Repetition.__init__(self, *args, **kwargs) self.delimiter = delimiter
class ExcelRule(MappingRule): mapping = { "next sheet [<n>]": R(Key("c-pgdown")) * Repeat(extra='n'), "(prior | previous) sheet [<n>]": R(Key("c-pgup")) * Repeat(extra='n'), "[select] cell <column_1> <row_1>": R(Key("c-g") + Text("%(column_1)s%(row_1)s") + Key("enter")), "select <column_1> <row_1> through <column_2> <row_2>": R( Key("c-g") + Text("%(column_1)s%(row_1)s:%(column_2)s%(row_2)s") + Key("enter")), "go to cell": R(Key("c-g")), "select current column": R(Key("c-space")), "select current row": R(Key("s-space")), "top of column": R(Key("c-up")), "beginning of row": R(Key("c-left")), "insert stuff": R(Key("cs-plus")), "insert row": R(Key("cs-plus, a-r, enter")), "insert column": R(Key("cs-plus, a-c, enter")), "insert cell [to the] left": R(Key("cs-plus, a-i, enter")), "insert cell above": R(Key("cs-plus, a-d, enter")), "insert pivot table": R(Key("a-n, v")), "insert pivot chart": R(Key("a-n, s, z, c")), "add-ins": R(Key("a-t, i")), "add border": R(Key("cs-ampersand")), "arrange Windows": R(Key("a-w/10, a")), "auto sum": R(Key("a-equal")), "freeze panes": R(Key("a-w, f")), # From Mark Lillibridge regarding the edit cell command below: # There are at least two modes, edit (blue background) and enter (yellow background). # In enter mode for formulas, arrow keys select a # cell (range if shifted), whereas in edit mode, they move the cursor # inside the formula. For non-formulas, in enter mode, the arrows # finished entering the current cell and move to another cell. # # and "edit cell" initially switch to edit mode then # toggle thereafter for the given cell. Typing initially puts you in # enter mode. # # edit cell: always edits directly in cell (blue background) # # this has the effect of pressing F2 without DNS around. # # Want "edit directly in cell" option turned off: # Office button->advanced-> turn off allow editing directly in cells # (Dragon handles edit in cell directly badly) # # First time, edits current cell via formula bar. Unlike with # editing directly in a cell, this highlights ranges and cells used. "toggle edit cell": R(Key("f2")), } extras = [ Dictation("dict"), ShortIntegerRef("n", 1, 10), ShortIntegerRef("row_1", 1, 100), ShortIntegerRef("row_2", 1, 100), # change max to 3 if you want sequences of lentgh three and so on Repetition(Choice("alphabet1", alphabet_support.caster_alphabet()), min=1, max=2, name="column_1"), Repetition(Choice("alphabet2", alphabet_support.caster_alphabet()), min=1, max=2, name="column_2") ] defaults = {"n": 1, "dict": ""}
class TextManipulation(MergeRule): pronunciation = "text manipulation" mapping = { # PROBLEM: sometimes Dragon thinks the variables are part of dictation. # replace text or character "replace <direction> [<number_of_lines_to_search>] [<occurrence_number>] <dictation> with <dictation2>": R(Function( text_manipulation_support.copypaste_replace_phrase_with_phrase, dict(dictation="replaced_phrase", dictation2="replacement_phrase"), dictation_versus_character="dictation"), rdescript= "Text Manipulation: replace text to the left or right of the cursor" ), "replace <direction> [<number_of_lines_to_search>] [<occurrence_number>] <character> with <character2>": R(Function( text_manipulation_support.copypaste_replace_phrase_with_phrase, dict(character="replaced_phrase", character2="replacement_phrase"), dictation_versus_character="character"), rdescript= "Text Manipulation: replace character to the left of the cursor"), # remove text or character "remove <direction> [<number_of_lines_to_search>] [<occurrence_number>] <dictation>": R(Function(text_manipulation_support.copypaste_remove_phrase_from_text, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript= "Text Manipulation: remove chosen phrase to the left or right of the cursor" ), "remove <direction> [<number_of_lines_to_search>] [<occurrence_number>] <character>": R(Function(text_manipulation_support.copypaste_remove_phrase_from_text, dict(character="phrase"), dictation_versus_character="character"), rdescript= "Text Manipulation: remove chosen character to the left of the cursor" ), # remove until text or character "remove <direction> [<number_of_lines_to_search>] until [<before_after>] [<occurrence_number>] <dictation>": R(Function(text_manipulation_support.copypaste_delete_until_phrase, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript="Text Manipulation: delete until chosen phrase"), "remove <direction> [<number_of_lines_to_search>] until [<before_after>] [<occurrence_number>] <character>": R(Function(text_manipulation_support.copypaste_delete_until_phrase, dict(character="phrase"), dictation_versus_character="character"), rdescript="Text Manipulation: delete until chosen character"), # move cursor "(go | move) <direction> [<number_of_lines_to_search>] [<before_after>] [<occurrence_number>] <dictation>": R(Function(text_manipulation_support.move_until_phrase, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript= "Text Manipulation: move to chosen phrase to the left or right of the cursor" ), "(go | move) <direction> [<number_of_lines_to_search>] [<before_after>] [<occurrence_number>] <character_sequence> [over]": Function( lambda direction, before_after, number_of_lines_to_search, occurrence_number, character_sequence: text_manipulation_support.move_until_phrase( direction, before_after, "".join(character_sequence), number_of_lines_to_search, occurrence_number, "character")), # select text or character "grab <direction> [<number_of_lines_to_search>] [<occurrence_number>] <dictation>": R(Function(text_manipulation_support.select_phrase, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript="Text Manipulation: select chosen phrase"), "grab <direction> [<number_of_lines_to_search>] [<occurrence_number>] <character>": R(Function( text_manipulation_support.select_phrase, dict(character="phrase", dictation_versus_character="character")), rdescript="Text Manipulation: select chosen character"), # select until text or character "grab <direction> [<number_of_lines_to_search>] until [<before_after>] [<occurrence_number>] <dictation> ": R(Function(text_manipulation_support.select_until_phrase, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript="Text Manipulation: select until chosen phrase"), "grab <direction> [<number_of_lines_to_search>] until [<before_after>] [<occurrence_number>] <character>": R(Function(text_manipulation_support.select_until_phrase, dict(character="phrase"), dictation_versus_character="character"), rdescript="Text Manipulation: select until chosen character"), # capitalized 1st word of text or character "capital <direction> [<number_of_lines_to_search>] [<occurrence_number>] [<letter_size>] <dictation>": R(Function( text_manipulation_support.copypaste_change_phrase_capitalization, dict(dictation="phrase"), dictation_versus_character="dictation"), rdescript="Text Manipulation: change capitalization phrase"), "capital <direction> [<number_of_lines_to_search>] [<occurrence_number>] [<letter_size>] <character>": R(Function( text_manipulation_support.copypaste_change_phrase_capitalization, dict(character="phrase"), dictation_versus_character="character"), rdescript="Text Manipulation: change capitalization character"), } new_text_punc_dict = text_punc_dict() new_text_punc_dict.update(alphabet_support.caster_alphabet()) new_text_punc_dict.update(number_dict) character_dict = new_text_punc_dict character_choice_object = Choice("character_choice", character_dict) extras = [ Repetition(character_choice_object, min=1, max=3, name="character_sequence"), Dictation("dict"), Dictation("dictation"), Dictation("dictation2"), Dictation("text"), IntegerRefST("n", 1, 100), IntegerRefST("m", 1, 100), IntegerRefST("wait_time", 1, 1000), IntegerRefST("number_of_lines_to_search", 1, 50), Choice("character", character_dict), Choice("character2", character_dict), Choice("single_character", character_dict), Choice( "direction", { "lease": "left", "ross": "right", "sauce": "up", "dunce": "down", # note: "sauce" (i.e. "up") will be treated the same as "lease" (i.e. "left") except that # the default number_of_lines_to_search will be set to 3 # in the same way, "dunce" (i.e. "down") will be treated the same as # "ross" (i.e. "right") }), Choice("before_after", { "before": "before", "after": "after", }), Choice( "letter_size", { "upper": "upper", "upward": "upper", "lower": "lower", "lowered": "lower", }), Choice( "occurrence_number", { "first": 1, "second": 2, "third": 3, "fourth": 4, "fifth": 5, "sixth": 6, "seventh": 7, "eighth": 8, "ninth": 9, "tenth": 10, }), ] defaults = { "before_after": None, "letter_size": "upper", "number_of_lines_to_search": 0, # before changing this default, please read the function deal_with_up_down_directions "occurrence_number": 1, } # if direction is up or down, the default number_of_lines_to_search
#import words #import programs release = Key("shift:up, ctrl:up, alt:up") alternatives = [] alternatives.append(RuleRef(rule=keyboard.KeystrokeRule())) """ alternatives.append(RuleRef(rule=words.FormatRule())) alternatives.append(RuleRef(rule=words.ReFormatRule())) alternatives.append(RuleRef(rule=words.NopeFormatRule())) alternatives.append(RuleRef(rule=programs.ProgramsRule())) """ root_action = Alternative(alternatives) sequence = Repetition(root_action, min=1, max=16, name="sequence") class RepeatRule(CompoundRule): # Here we define this rule's spoken-form and special elements. spec = "<sequence> [[[and] repeat [that]] <n> times]" extras = [ sequence, # Sequence of actions defined above. IntegerRef("n", 1, 100), # Times to repeat the sequence. ] defaults = { "n": 1, # Default repeat count. } def _process_recognition(self, node, extras): # @UnusedVariable sequence = extras["sequence"] # A sequence of actions.
for c in commands: Key(c).execute() Breathe.add_commands( # Commands will be active either when we are editing a python file # or after we say "enable python". pass None for the commands to be global. # context = AppContext(title=".py") | CommandContext("python"), context = AppContext(title='Gmail') | AppContext(title='Mail -') | context, mapping = { 'message <commands>': Function(do_commands), '[<n>] message next': Key('j:%(n)d'), '[<n>] message previous': Key('k:%(n)d'), }, extras = [ Repetition(Choice('message', { 'select': 'x', 'next': 'j', 'previous': 'k', 'archive': 'e', 'delete': '#', 'reply': 'r', 'reply all': 'a', 'send': 'c-enter', 'view': 'enter', 'compose': 'c', }), name='commands', max=20), IntegerRef("n", 1, 20, default=1), Dictation("text", default=""), ] )
def value(self, node): return int("".join(Repetition.value(self, node)))
def __init__(self, name, min, max, *args, **kw): Repetition.__init__(self, self.child, min, max, name=name, *args, **kw)
"<format_type> <dictation>": Function(format_text), "control <letter>": Key("c-%(letter)s"), "equals": Text(" = "), } extras = [ letter_choice("letter"), formatting_choice("format_type"), IntegerRef("n", 1, 100), Dictation("dictation"), ] letter = RuleRef(rule=LetterRule(), name='letter') letter_sequence = Repetition(Alternative([letter]), min=1, max=12, name="letter_sequence") class LetterSequenceRule(CompoundRule): spec = "<letter_sequence>" extras = [letter_sequence] def _process_recognition(self, node, extras): letter_sequence = extras["letter_sequence"] for letter in letter_sequence: letter.execute() Key("shift:up, ctrl:up").execute()
from dragonfly import RuleRef, Repetition, CompoundRule, Dictation, IntegerRef, Grammar, MappingRule, Key from keystroke import KeystrokeRule from letterRule import LetterRule from windowss import WindowsKeyRule4 import shared shared.letter = RuleRef(rule=LetterRule(), name='letter') shared.keystroke = RuleRef(rule=KeystrokeRule(), name='keystroke') shared.letter_sequence = Repetition(shared.letter, min=1, max=32, name='letter_sequence') from repeatt import RepeatRule # def executeLetter(letter): # letter.execute() # # # def executeLetterSequence(letter_sequence): # for letter in letter_sequence: # letter.execute() # --------------------------------------------------------------------------- # NormalMode # class IntellijEnabler(CompoundRule): # spec = "intelijey" # def _process_recognition(self, node, extras):