예제 #1
0
 def __init__(self):
     self.language = unimacroutils.getLanguage()
     # here the grammar is not loaded yet, but the ini file is present
     self.startInifile()
     #print 'requireTimes: %s, simpleOrExtended: %s'% (self.requireTimes, self.doKeystrokesExtended)
     self.constructGramSpec(inInit=1)
     ancestor.__init__(self)
예제 #2
0
 def test_Something_in_unimacro(self):
     self.log('testing something')
     actions.doAction("W")
     lang = unimacroutils.getLanguage()
     self.assert_equal(
         "enx", lang,
         "testing should be done from an English speech profile, not: %s" %
         lang)
예제 #3
0
    def test_Something_in_unimacro(self):
        print('testing something')
        lang = unimacroutils.getLanguage()
        self.assert_equal(
            "enx", lang,
            "testing should be done from an English speech profile, not: %s" %
            lang)


# no main statement, run from command in _unimacrotest.py.
예제 #4
0
moveRateChange = 2.0
fastSlowChange = 3.0
veryChange = 3.0

Counts = [
    '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14',
    '15', '16', '17', '18', '19', '20', '25', '30', '35', '40'
]

# flag for displaying all results through the DisplayMessage function
# gives an error in the English version when saying "wait", change therefore
# in "hold on"
showAll = 1

language = unimacroutils.getLanguage()
normalSet = ['startMoving', 'startMousing', 'startRepeating', 'startSearching']
############################################################################
#
# Here are some of our instisnce variables
#
#   self.inTimer   set when the timer callback in installed
#   self.curSpeed       current movement speed (milliseconds for timer)
#

ancestor = natbj.IniGrammar


class ThisGrammar(ancestor):
    # when we unload the grammar, we must make sure we clear the timer
    # callback so we keep a variable which is set when we currently own
class ThisGrammar(ancestor):

    language = unimacroutils.getLanguage()
    #Step 1, choose one of next three grammar rules:
    # the <integer> rule comes from these grammar rules
    try:
        number_rules = natbj.numberGrammarTill999[language]
    except KeyError:
        print('take number grammar from "enx"')
        number_rules = natbj.numberGrammarTill999['enx']

    #number_rules = natbj.numberGrammarTill999999[language] # including thousands
    #number_rules = natbj.numberGrammar[language] #  including millions
    name = "number extended"
    # do not use "To" instead of "Through", because "To" sounds the same as "2"
    gramSpec = [
        """
<testnumber1> exported = [<spacing>] (number <number>)+;
<testnumber2> exported = number <integer> Through <integer>;
<pagenumber> exported = page <integer> [Through <integer>];
<filenamelastpage> exported = filename last page;
<pair> exported = Pair <number> And <number>;
<number> = <integer> | Minus <integer> | <float> | Minus <float>;
<spacingnumber> exported = number (<spacing>|<number>)+;
<spacing> = {spacing};
"""
    ]
    gramSpec.append(
        "<banknumber> exported = IBAN {n00-99} {bankheader} <integer>;")
    gramSpec.append(number_rules)
    try:
        integer999 = natbj.numberGrammarTill999[language]
    except KeyError:
        print('take number grammar from "enx"')
        integer999 = natbj.numberGrammarTill999['enx']
    ##  345567;345567
    ## these are special rules for making numbers of specific length.
    ## when they appear to be usefull, I will try to make them available in other languages
    ## and other cases too:

    amsterdamZuidRule = """<numberaztotal> exported =  <numberazone> | <numberaztwo> | <numberazone><numberaztwo>;
    <numberazone>  = zesentachtig <numberthreedigits><numberthreedigits>;
    <numberaztwo> = point (<__thousandslimited>  | <numbertwodigits><numbertwodigits>);
<numbertwodigits> = {n0-9}{n0-9} | {n10-99};
<numberthreedigits> = {n0-9}{n0-9}{n0-9} | <__hundredslimited> | {n0-9} <numbertwodigits>;
<__hundredslimited> = hundred | <__2to9before> hundred | hundred <__1to99after> ;
<__thousandslimited> = thousand | <__2to9before> thousand | thousand <__1to99after> |
                        <__2to9before> thousand <__1to9after>;

<numberfourdigits> = <__thousandslimited>  | <numbertwodigits> <numbertwodigits> ;
<numbersixdigits> = {n0-9}+ | {n0-9} <numbertwodigits>  {n0-9} <numbertwodigits> ;
<__thousands> = duizend | (<__1to99>|<__hundreds>) duizend | duizend (<__1to99>|<__hundreds>) |
                   (<__1to99>|<__hundreds>) duizend  (<__1to99>|<__hundreds>);
<__2to9before> = {n2-9};
<__1to99after> = {n1-99};
<__1to9after> = {n1-9};

"""

    ##8600 8650 86 2008
    def gotResults___hundredslimited(self, words, fullResults):
        """will return only three digits as _sofar
        goes together with <__2to9before> and <__1to99after>
        
        """
        didBeforeRules = ['__2to9before']
        doInAfterRules = ['__1to99after', '__1to9after']

        print('__hundredslimited, prevRule: %s, nextRule: %s, words: %s' %
              (self.prevRule, self.nextRule, words))
        lenw = len(words)
        for i in range(lenw):
            if i == 0 and self.prevRule in didBeforeRules:
                pass
            else:
                self._hundreds = 100
            if self.nextRule in doInAfterRules and i == lenw - 1:
                # leave the "adding" action to nextRule
                pass
            else:
                self._sofar += str(self._hundreds)
                self._hundreds = 0

    def gotResults___thousandslimited(self, words, fullResults):
        """will return only four digits as _sofar
        
        goes together with <__2to9before> and <__1to99after> and possibly <__1to9after>
        
        """
        didBeforeRules = ['__2to9before']
        doInAfterRules = ['__1to99after', '__1to9after']

        # print '__hundredslimited, prevRule: %s, nextRule: %s, words: %s'% (self.prevRule, self.nextRule, words)
        lenw = len(words)
        for i in range(lenw):
            if i == 0 and self.prevRule in didBeforeRules:
                pass
            else:
                self._thousands = 1000
            if self.nextRule in doInAfterRules and i == lenw - 1:
                # leave the "adding" action to nextRule
                pass
            else:
                self._sofar += str(self._thousands)
                self._thousands = 0

    def gotResults___1to99after(self, words, fullResults):
        """should be after __hundredslimited or __thousandslimited
        
        must be defined in doInAfterRules ofter the corresponding rule
        """
        didBeforeRules = ['__hundredslimited', '__thousandslimited']

        print('__1to99after, prevRule: %s, nextRule: %s, words: %s' %
              (self.prevRule, self.nextRule, words))
        if len(words) > 1:
            raise ValueError(
                "rule __1to99after, expect only one word, got %s: %s" %
                (len(words), words))
        numWords = self.getNumbersFromSpoken(words)
        num = numWords[0]
        if self.prevRule == '__hundredslimited':
            self._hundreds += num
            self._sofar += str(self._hundreds)
            self._hundreds = 0
        elif self.prevRule == '__thousandslimited':
            self._thousands += num
            self._sofar += str(self._thousands)
            self._thousands = 0
        else:
            print('__1to99after, no valid rule, got: %s, expected one of: %s' %
                  (self.prevRule, didBeforeRules))
            self._sofar += str(num)
            print('_sofar: %s' % self._sofar)

    def gotResults___1to9after(self, words, fullResults):
        """should be after __hundredslimited or __thousandslimited
        
        must be defined in doInAfterRules ofter the corresponding rule
        
        Identical with gotResults___1to99after
        """
        didBeforeRules = ['__hundredslimited', '__thousandslimited']

        print('__1to99after, prevRule: %s, nextRule: %s, words: %s' %
              (self.prevRule, self.nextRule, words))
        if len(words) > 1:
            raise ValueError(
                "rule __1to99after, expect only one word, got %s: %s" %
                (len(words), words))
        numWords = self.getNumbersFromSpoken(words)
        num = numWords[0]
        if self.prevRule == '__hundredslimited':
            self._hundreds += num
            self._sofar += str(self._hundreds)
            self._hundreds = 0
        elif self.prevRule == '__thousandslimited':
            self._thousands += num
            self._sofar += str(self._thousands)
            self._thousands = 0
        else:
            print('__1to99after, no valid rule, got: %s, expected one of: %s' %
                  (self.prevRule, didBeforeRules))
            self._sofar += str(num)
            print('_sofar: %s' % self._sofar)

    def gotResults___2to9before(self, words, fullResults):
        """together with __hundredslimited or __thousandslimited
        
        expect one word only, and treat with respect to the next rule
        should be defined in didBeforeRules of the corresponding rule
        """
        # print '__2to9before, prevRule: %s, nextRule: %s, words: %s'% (self.prevRule, self.nextRule, words)

        if len(words) > 1:
            raise ValueError(
                "rule __2to9before, expect only one word, got %s: %s" %
                (len(words), words))
        numWords = self.getNumbersFromSpoken(words, asStr=1)
        numStr = numWords[0]
        num = int(numStr)
        if self.nextRule == '__hundredslimited':
            self._hundreds = num * 100
        if self.nextRule == '__thousandslimited':
            self._thousands = num * 1000
        else:
            print(
                '__2to9before, nextRule is NOT __hundredslimited of __thousandslimited'
            )
            self._sofar += numStr
            print('_sofar: %s' % self._sofar)

##8640  8600

#failed to get this working:
#<listtupleargument> exported = (Tuple|List|Argument) (Number <number> | (Variable|String) <dgndictation> | None)+;

    def __init__(self):
        """start the inifile and add to grammar if needed a special rule
        """
        self.startInifile()
        #print 'enableSearchCommands: %s'% self.enableSearchCommands
        if self.specialAmsterdamZuid:
            self.gramSpec.append(self.amsterdamZuidRule)
        ancestor.__init__(self)

    def gotBegin(self, moduleInfo):
        if self.checkForChanges:
            self.checkInifile()
        self.progInfo = unimacroutils.getProgInfo(moduleInfo)

    def initialize(self):
        if not self.language:
            print("no valid language in grammar " + __name__ +
                  " grammar not initialized")
            return
        self.load(self.gramSpec)
        # if switching on fillInstanceVariables also fill numbers lists like {n1-9} or {number1to99}
        self.switchOnOrOff()

    def gotResultsInit(self, words, fullResults):
        # Step 2:
        # initialise the variables you want to collect the numbers in:
        # defining them here makes testing in gotResults easier
        self.number = ''  # for most rules
        self.page = ''  # for page rule
        self.through = ''  # only for testnumber2 and pagenumber
        self.pair = ''  # only for the pair rule...
        self.minus = False
        self.ibanHeader = None  # for banknumber
        self.ibanCheck = None  # for banknumber
        self.totalNumber = ''  # for multiple parts (Amsterdam Zuid, spacingnumber)

        #self.listtupleargument = ''
        #self.Items = [] # for listtupleargumenthallo
        # this line can be used to get the correct fullResults to be used in testIniGrammar.py for
        # for debugging the rules!
        # print 'fullResults of number extended: %s'% fullResults

    def fillInstanceVariables(self):
        """fills the necessary instance variables

        in this grammar a special rule for Loes Wijers, Amsterdam Zuid.        
        """
        # search commands (for Arnoud):
        self.specialAmsterdamZuid = self.ini.getBool('general',
                                                     'special amsterdam zuid')
        self.filenamePagenumbersPrefix = self.ini.get(
            'general', 'filename page numbers prefix')
        self.filenamePagenumbersPostfix = self.ini.get(
            'general', 'filename page numbers postfix')
        self.lastPage, self.lastThroug = None, None  # filename page numbers

    def gotResults_testnumber1(self, words, fullResults):
        # step 3: setting the number to wait for
        # because more numbers can be collected, the previous ones be collected first
        # if you expect only one number, this function can be skipped (but it is safe to call):
        self.collectNumber()
        result = self.hasCommon(words, 'number')
        if self.hasCommon(words, 'number'):
            if self.number:
                # flush previous number
                self.number = self.doMinus('number', 'minus')  # convert to int
                self.outputNumber(self.number)
            self.waitForNumber('number')
        else:
            raise ValueError('invalid user input in grammar %s: %s' %
                             (__name__, words))

    def gotResults_testnumber2(self, words, fullResults):
        # step 4 also: if more numbers are expected,
        # you have to collect the previous number before asking for the new
        self.collectNumber()
        # self.minus is not relevant here, as this rule is about integers only...
        # can ask for 'number' or for 'through':
        if self.hasCommon(words, 'number'):
            self.waitForNumber('number')
        elif self.hasCommon(words, 'through'):
            self.waitForNumber('through')
        else:
            raise NumberError('invalid user input in grammar %s: %s' %
                              (__name__, words))

    def gotResults_spacingnumber(self, words, fullResults):
        self.collectNumber()
        self.totalNumber += self.number
        self.waitForNumber('number')

    def gotResults_spacing(self, words, fullResults):
        self.collectNumber()
        self.totalNumber += self.number
        self.waitForNumber('number')
        for w in words:
            spacingchar = self.getFromInifile(w, 'spacing')
            self.totalNumber += spacingchar

    def gotResults_pagenumber(self, words, fullResults):
        # step 4 also: if more numbers are expected,
        # you have to collect the previous number before asking for the new
        self.collectNumber()
        # self.minus is not relevant here, as this rule is about integers only...
        # can ask for 'number' or for 'through':
        if self.hasCommon(words, 'page'):
            self.waitForNumber('page')
        elif self.hasCommon(words, 'through'):
            self.waitForNumber('through')
        else:
            raise NumberError(
                'invalid words in pagenumber rule in grammar %s: %s' %
                (__name__, words))

    def gotResults_filenamelastpage(self, words, fullResults):
        # additional command, compose filename with the last called page number(s).
        # need variables in inifile section [general]: filename pagenumber prefix and filename pagenumber postfix
        # if these are not set, of if no page numbers are "remembered", do nothing
        if self.lastPage:
            if self.lastThroug:
                lp, lt = int(self.lastPage), int(self.lastThroug)
                if lt > lp:
                    pagePart = '%s-%s' % (lp, lt)
                else:
                    pagePart = self.lastPage
            else:
                pagePart = self.lastPage
        else:
            print(
                'numbers extended: no page numbers command issued yet, skip command'
            )
            return
        if not self.filenamePagenumbersPrefix:
            print(
                '%s: command "%s", please specify "filename page numbers prefix" in section [general] of inifile'
                % (' '.join(words), self.name))
        if not self.filenamePagenumbersPostfix:
            print(
                '%s: command "%s", please specify "filename page numbers postfix" in section [general] of inifile'
                % (' '.join(words), self.name))
        if self.filenamePagenumbersPrefix and self.filenamePagenumbersPostfix:
            fName = self.filenamePagenumbersPrefix + pagePart + self.filenamePagenumbersPostfix
            action("SCLIP %s" % fName)

    def gotResults_pair(self, words, fullResults):
        # here a bit different logic for the place to collect the previous number.
        #
        self.pair = 'pair'
        if self.hasCommon(words, 'and'):
            self.collectNumber()
            self.number = self.doMinus('number', 'minus')
            self.waitForNumber('pair')
        else:
            self.waitForNumber('number')

    def gotResults_banknumber(self, words, fullResults):
        """get first 8 characters from bank name (list), rest from numbers grammar
        """
        self.ibanHeader = self.getFromInifile(words[-1], 'bankheader')
        self.ibanCheck = "%.2d" % self.getNumberFromSpoken(words[-2])
        self.waitForNumber('number')

    def gotResults_number(self, words, fullResults):
        # step: when in this rule, the word Minus (or synonym or translation) has been spoken..
        self.minus = True

    def gotResults_numberazone(self, words, fullResults):
        """first part of the number"""
        if not self.totalNumber:
            self.totalNumber = '86'
            # print 'totalNumber: ', self.totalNumber
        self.collectNumber()
        self.totalNumber += self.number
        self.number = ''
        # wait for a number of 6 digits, if not, do NOT output!!
        self.waitForNumber('number', 6)

    def gotResults_numberaztwo(self, words, fullResults):
        """second part of the number"""
        self.collectNumber()
        self.totalNumber += self.number
        self.number = ''
        self.totalNumber += '.'
        # wait for a number of 6 digits, if not, do NOT output!!
        self.waitForNumber('number', 4)

# # # # <numbertwodigits> = {n0-9}{n0-9} | {n10-99};
# # # # <numberthreedigits> = {n0-9}+ | <__hundreds> | {n0-9} <numbertwodigits>;

    def gotResults_numbertwodigits(self, words, fullResults):
        numWords = self.getNumbersFromSpoken(words, asStr=1)
        numberString = ''.join(numWords)
        self._sofar += numberString

    def gotResults_numberthreedigits(self, words, fullResults):
        numWords = self.getNumbersFromSpoken(words, asStr=1)
        numberString = ''.join(numWords)
        self._sofar += numberString

    def gotResults_numberfourdigits(self, words, fullResults):
        numWords = self.getNumbersFromSpoken(words, asStr=1)
        numberString = ''.join(numWords)
        self._sofar += numberString

    def gotResults_numbersixdigits(self, words, fullResults):
        numWords = self.getNumbersFromSpoken(words, asStr=1)
        numberString = ''.join(numWords)
        self._sofar += numberString

    def gotResults(self, words, fullResults):
        # step 5, in got results collect the number:
        self.collectNumber()

        if self.totalNumber:
            # multiple numbers, AmsterdamZuid
            self.totalNumber += self.number
            print('gotResults totalNumber: ', self.totalNumber)
            if self.message:
                print(
                    'Error collecting the number, do NOT output the number...')
                print(self.message)
            else:
                self.outputNumber(self.totalNumber)
            if len(self.totalNumber) == 13 and self.totalNumber[-5] == '.':
                keystroke("{tab}")
            elif len(self.totalNumber) == 5 and self.totalNumber[0] == '.':
                keystroke("{tab}")

            return

        if self.page:
            ## page numbers rule (for child windows, adobe [acrord32] of pdf24.)
            self.lastPage, self.lastThroug = self.page, self.through
            print('setting lastPage and lastThroug: %s, %s' %
                  (self.lastPage, self.lastThroug))
            isTop = (self.progInfo[2] == 'top')
            ma = getMetaAction('pagestart', progInfo=self.progInfo)
            if not ma:
                print('no metaactions defined for pagestart, stop command %s' %
                      self.progInfo.prog)
                if isTop:
                    if self.through:
                        keystroke(" page %s-%s" % (self.page, self.through))
                    else:
                        keystroke(" page %s" % self.page)
                else:
                    print("cannot finish page command for child window: %s" %
                          repr(self.progInfo))
                return

            action("<<pagestart>>")
            keystroke(self.page)
            if self.progInfo.prog == 'pdf24-creator' and self.through == '':
                self.through = self.page

            if self.through:
                ## only child window here:
                action("<<pagethrough>>")
                keystroke(self.through)
            action("<<pagefinish>>")
            return  # page command

        elif self.pair:
            self.pair = self.doMinus('pair', 'minus')
            print("(%s, %s) " % (self.number, self.pair))

        #elif self.listtupleargument:
        #    print 'self.listtupleargument in gotResults: %s'% self.listtupleargument
        #    if self.number:
        #        self.number = self.doMinus('number', 'minus')
        #        self.Items.append(self.number)
        #
        #    if self.dictated:
        #        self.Items.append(''.join(self.dictated))
        #        self.dictated = None
        #
        #    result = repr(self.Items)
        #    print 'result: %s'% self.Items
        #    if self.listtupleargument == 'list':
        #        print 'list: %s'% result
        #    elif self.listtupleargument == 'tuple':
        #        result = repr(tuple(self.Items))
        #        print 'tuple: %s'% result
        #    else:
        #        result = repr(tuple(self.Items)).replace(', ', ',')
        #        result = result.replace(', ',',')
        #        print 'argument: %s'% result
        #
        elif self.ibanCheck and self.ibanHeader:
            try:
                # print 'ibanheader: %s, number: %s'% (self.ibanHeader, self.number)
                result = Iban = iban.create_iban(self.ibanHeader[:2],
                                                 self.ibanHeader[2:],
                                                 self.number)
            except iban.IBANError as err:
                print('invalid iban %s, %s (%s)' %
                      (self.ibanHeader, self.number, err))
                return
            if result[2:4] == str(self.ibanCheck):
                keystroke(result)
            else:
                print('invalid check: %s (%s) ' % (self.ibanCheck, result))

        elif self.number:
            # last part if all others failed:
            self.number = self.doMinus('number', 'minus')
            self.outputNumber(self.number)

    def outputNumber(self, number):
        if type(number) in [int, float]:
            number = str(number)

        keystroke(number)
        prog = unimacroutils.getProgName()
        if prog in ['iexplore', 'firefox', 'chrome', 'safari']:
            keystroke('{tab}')
        elif prog in ['natspeak']:
            keystroke('{enter}')
        elif prog in ['excel', 'winword', 'soffice']:
            keystroke('{tab}')

    def doMinus(self, number, minus):
        """return  the minus version of number, is self.minus is set

        pass in the names of the number variable and the name of the minus variable.
        return the wanted number.        
        """
        Nstring = getattr(self, number)
        Nstring = Nstring.strip()
        Minus = getattr(self, minus)
        if not Nstring:
            setattr(self, minus, False)
            return ''

        if Minus:
            if Nstring.startswith('-'):
                Nstring = Nstring[1:]
            else:
                Nstring = '-' + Nstring
            setattr(self, minus, False)
        return Nstring
예제 #6
0
class ThisGrammar(ancestor):
    language = unimacroutils.getLanguage()
    iniIgnoreGrammarLists = ['count', 'taskcount',
                             'taskapplication']  # are set in this module
    # taskcount and taskapplication only in very special
    # case, see Arnoud...
    if language == "nld":
        name = "regels"
        numGram = natbj.numberGrammarTill999['nld']
    else:
        name = "lines"
        numGram = natbj.numberGrammarTill999['enx']
    gramSpec = """
<before> = Here;
<linesthat> exported = (THAT | <lines> | <paras>) <action>;
<linesnum> exported = <linenum> | <linenum> <action>;
<lines> = line | this line | <before> line | 
           {count} lines| <before> {count} lines |
           these {count} lines|
           (previous|next) (line | {count} lines);
<paras> = para | this para | <before> para | <before> this para |
           {count} paras | <before> {count} paras |
           these {count} paras|
           (previous|next) (para | {count} paras);
<linenum> = line (<integer> | <integer>(through<integer> | plus {count}) | back);
<action> = <column> | {simpleaction} | <movecopyaction>;
<column> = column <integer>;
<movecopyaction> = (move | copy) (((down|up) {count})|(to <integer>));
""" + numGram + """
<base> exported = 'line base' (<integer>|off);
    """

    def initialize(self):
        if not self.language:
            return

        self.load(self.gramSpec)
        self.setNumbersList('count', counts)

        # only for coupling with tasks search (Arnoud)
        if self.enableSearchCommands:
            self.setNumbersList('taskcount', self.tasksGrammar.taskCounts)
            self.setList('taskapplication',
                         self.tasksGrammar.ini.get('application'))

        self.switchOnOrOff()
        self.mode = 'inactive'
        self.lastDirection = 'down'

    def gotBegin(self, moduleInfo):
        if self.checkForChanges:
            self.checkInifile()
        if self.prevModInfo == moduleInfo:
            return
        # changing sets, as moduleInfo changed
##        if not moduleInfo[0]: # no valid module info, do nothing
##            print 'no module info, skipping'
##            return
# if window changes reset base:
        self.maxBase = 0
        self.base = 0

        progInfo = unimacroutils.getProgInfo(modInfo=moduleInfo)
        if unimacroutils.matchWindow(self.ignore, progInfo=progInfo):
            ##            print 'progInfo in ignore, skipping: %s'% self.ignore
            return
        if self.windowPolicy(moduleInfo, progInfo):
            if self.mode != 'active':
                self.activateAll()
                self.mode = 'active'
            else:
                pass
##                print '%s, remains active'% self.getName()
        else:
            if self.mode != 'inactive':
                ##                print '%s: non matching window deactivate: %s'% \
                ##                      (self.getName(), moduleInfo[1])
                self.deactivateAll()
                self.mode = 'inactive'
            else:
                pass
##                print '%s, remains inactive'% self.getName()
        self.prevModInfo = moduleInfo
        self.progInfo = progInfo

    def gotResultsInit(self, words, fullResults):
        self.currentLine = None

        if self.lineNumbersModuloHundred:
            self.app = actions.get_instance_from_progInfo(self.progInfo)
            prog = self.progInfo.prog
            if self.app:
                self.currentLine = self.app.getCurrentLineNumber()
                #if self.currentLine:
                #    print 'current line number for prog: %s: %s'% (prog, self.currentLine)
                #else:
                #    print 'currentLine not found in app: %s'% prog
        self.previousLines = self.nextLines = 0
        self.firstPart = ''
        self.line = 0
        self.through = 0
        self.newbase = 0  # for collecting a new base number
        self.numlines = 1  # for selecting line number plus count
        self.movecopyto = 0  # line number or number of lines to move or copy to
        self.action = None  # for simple actions the action string or list
        # for movecopy actions set to ['move','to'], ['copy', 'up'] etc
        self.paras = False  # normally lines
        self.column = 0
        self.resetWordVariables()

    def resetWordVariables(self):
        """for the processing of the word copy paste commands
        """
        # self.count is set in the wordspec rule and
        # self.wordAction is set in the rules wordspecifyaction and afterwordoptional.
        # self.direction is default 'right', but can be adapted to 'left' in wordspec rule.
        # in doWordAction, the action is only performed if variable have been set.
        # special case: self.count = 0, only click, in afterwordoptional.
        self.wordAction = None
        self.searchAction = None
        self.count = None
        self.direction = 'right'

    ## words:
    # word-action handling:
    def rule_words(self, words):
        """# rules to manage words (copy/paste etc)
           # optional part after a cut/copy action, to move mouse
           # to a new location and do a paste there:
           <wordspecifyaction> | <before> <wordspecifyaction> |
           <wordspecifyaction> <afterwordoptional> | <before> <wordspecifyaction> <afterwordoptional>
        """
        print("never comes here! %s" % words)

    def subrule_wordspec(self, words):
        """word | {n2-20} words | word (left|right) | {n2-20} words (left|right)
        """
        lenwords = len(words)
        print("wordspec, got: %s (%s)" % (words, lenwords))
        for i, w in enumerate(words):
            if self.hasCommon(w, 'word'):
                self.count = 1
                if i < lenwords - 1:
                    if self.hasCommon(words[i + 1], 'left'):
                        direction = 'left'
            elif self.hasCommon(w, 'words'):
                if not self.count:
                    print('error in grammar lines, wordspec, count should have a value by now: %s\nprocessing word: %s (words: %s)'% \
                          (self.count, w, words))
                if i < lenwords - 1:
                    if self.hasCommon(words[i + 1], 'left'):
                        self.direction = 'left'
            elif self.hasCommon(w, ['left', 'right']):
                continue  # should have been processed already
            else:
                self.count = self.getNumberFromSpoken(w)
                if not self.count:
                    print('error in grammar lines, wordspec, count been caught here: %s\nprocessing word: %s (words: %s)'% \
                          (self.count, w, words))
                continue
            # process the count:
            if self.wordAction:
                self.doWordAction()  # and flush
            if self.searchAction:
                self.doSearchAction()  # and flush

    def subrule_wordspecifyaction(self, words):
        """<wordspec> <wordaction> |
               <wordaction> <wordspec>
        """
        print("should never come in subrule_wordspecifyaction %s" % words)

    def subrule_wordaction(self, words):
        """{wordaction}| (search ({taskcount}|{taskapplication}))"""

        # wordactions, simple actions from inifile
        # search, coupling with tasks grammar for search command after a word
        # was selected, for Arnoud van den Eerenbeemt, QH august 2011

        self.wordAction = self.getFromInifile(words, 'wordaction')
        if self.wordAction:
            if self.count:
                self.doWordAction()  # only if data
        else:
            if self.hasCommon(words, 'search'):
                self.searchAction = ['search', words[-1]]
                if self.count:
                    self.doSearchAction()

    def subrule_afterwordoptional(self, words):
        """{afterwordaction} | {afterwordaction} <wordspec> | <wordspec> {afterwordaction}
        """
        print("afterwordoptional, got: %s" % words)
        self.wordAction = self.getFromInifile(words, 'afterwordaction')
        if not self.doMouseMoveStopClick():
            self.count = None
            self.wordAction = 0
            print('aborted doMouseMoveStop action, stop this rule')
            return
        # because <wordspec> is optional, test here if it is yet to come (nextRule)
        if self.count:
            # had wordspec rule:
            self.doWordAction()
        elif self.count is None and self.nextRule != 'wordspec':
            print('no word specification in afterwordoptional')
            self.count = 0  # go with a single click if no wordspec has been given
            self.doWordAction()

    def doMouseMoveStopClick(self):
        """wait for mouse starting to move, stopping and then click
        """
        action("ALERT")
        if not action("WAITMOUSEMOVE"):
            action("ALERT 2")
            return
        if not action("WAITMOUSESTOP"):
            return
        action("ButtonClick")
        action("ALERT")
        return 1

    def doWordAction(self):
        """process count, direction and action
        
        if done, reset variables,
        if variables missing, do nothing
        """
        if self.count is None or self.wordAction is None:
            print('not ready for word action: %s, %s, %s' %
                  (self.count, self.direction, self.wordAction))
            return
        if self.count == 0:
            #print 'doWordAction, single click: %s, %s, %s'% (self.count, self.direction, self.wordAction)
            pass
        else:
            #print 'doWordAction (select words): %s, %s, %s'% (self.count, self.direction, self.wordAction)
            wordSelect = "SELECTWORD %s, %s" % (self.count, self.direction)
            action(wordSelect)
        if self.wordAction:
            action(self.wordAction)
        self.resetWordVariables()

    def doSearchAction(self):
        """process count, direction and action, in this case a search into another window
        
        (coupling with tasks grammar)
        
        if done, reset variables,
        if variables missing, do nothing
        """
        if self.count is None or self.searchAction is None:
            print('not ready for word action: %s, %s, %s' %
                  (self.count, self.direction, self.wordAction))
            return
        if self.count == 0:
            #print 'doWordAction, single click: %s, %s, %s'% (self.count, self.direction, self.wordAction)
            pass
        else:
            #print 'doWordAction (select words): %s, %s, %s'% (self.count, self.direction, self.wordAction)
            wordSelect = "SELECTWORD %s, %s" % (self.count, self.direction)
            action(wordSelect)
        if self.searchAction:
            print('now the search action in the tasks grammar: %s' %
                  self.searchAction)
            self.tasksGrammar.rule_searchinothertask(self.searchAction)
        self.resetWordVariables()

    def gotResults_linenum(self, words, fullResults):
        """starting a linenum rule
        
        when the command is line back, this is intercepted immediately
        otherwise the waiting for a number is started
        """
        if self.hasCommon(words, 'back'):
            self.firstPart = 'lineback'
            return
        self.firstPart = 'linesnum'
        self.lastDirection = 'down'
        self.collectNumber()
        if self.hasCommon(words, ['line']):
            self.waitForNumber('line')
        elif self.hasCommon(words, ['through']):
            self.waitForNumber('through')
        elif self.hasCommon(words, ['plus']):
            gotCounts = self.getNumbersFromSpoken(words, counts)
            if gotCounts:
                self.numlines = gotCounts[-1] + 1

    def gotResults_that(self, words, fullResults):
        self.firstPart = 'that'

    def gotResults_lines(self, words, fullResults):
        self.lastDirection = 'down'
        self.firstPart = 'lines'
        if self.hasCommon(words, ['previous']):
            self.previousLines = 1
            self.lastDirection = 'up'
        if self.hasCommon(words, ['next']):
            self.nextLines = 1
        if self.hasCommon(words, ['line']):
            self.numlines = 1
        if self.hasCommon(words, ['lines']):
            getCounts = self.getNumbersFromSpoken(words, counts)
            if getCounts:
                if len(getCounts) > 1:
                    print('warning, more counts found: %s (take the first)' %
                          getCounts)
                self.numlines = getCounts[0]
            else:
                print('should collect a count, nothing found, take 1')

    def gotResults_paras(self, words, fullResults):
        self.lastDirection = 'down'
        self.firstPart = 'paras'
        if self.hasCommon(words, ['previous']):
            self.previousLines = 1
            self.lastDirection = 'up'
        if self.hasCommon(words, ['next']):
            self.nextLines = 1
        if self.hasCommon(words, ['para']):
            self.numparas = 1
        if self.hasCommon(words, ['paras']):
            getCounts = self.getNumbersFromSpoken(words, counts)
            if getCounts:
                if len(getCounts) > 1:
                    print('warning, more counts found: %s (take the first)' %
                          getCounts)
                self.numlines = getCounts[0]
            else:
                print('should collect a count, nothing found, take 1')

    def gotResults_action(self, words, fullResults):
        self.action = self.getFromInifile(words, 'simpleaction')

    def gotResults_column(self, words, fullResults):
        """wait for integer, action in gotResults
        """
        self.collectNumber()
        self.waitForNumber('column')

    def gotResults_movecopyaction(self, words, fullResults):
        self.collectNumber()
        self.action = [None, None]
        if self.hasCommon(words, ['move']):
            self.action[0] = 'move'
        elif self.hasCommon(words, ['copy']):
            self.action[0] = 'copy'

        if self.hasCommon(words, ['down']):
            self.action[1] = 'down'
            self.movecopyto = self.getNumberFromSpoken(words[-1], counts)
        elif self.hasCommon(words, ['up']):
            self.action[1] = 'up'
            self.movecopyto = self.getNumberFromSpoken(words[-1], counts)
        elif self.hasCommon(words, ['to']):
            self.action[1] = 'to'
            self.waitForNumber('movecopyto')
        print('movecopyto: %s (%s)' % (self.movecopyto, type(self.movecopyto)))

    def gotResults_before(self, words, fullResults):
        if self.hasCommon(words, 'here'):
            natlinkutils.buttonClick('left', 1)

    def gotResults_base(self, words, fullResults):
        if self.hasCommon(words, ['off']):
            self.base = 0
            self.DisplayMessage('resetting line base to 0')
        else:
            self.waitForNumber('newbase')

    def gotResults(self, words, fullResults):
        comment = 'command: %s' % ' '.join(words)
        self.prog = self.progInfo.prog
        self.collectNumber()
        #print 'lines command: %s (direction: %s)'% (comment, self.lastDirection)
        #print 'type line: %s'% type(self.line)
        #print 'base: %(base)s, line: %(line)s, through: %(through)s, ' \
        #      'movecopyto: %(movecopyto)s, action: %(action)s'% self.__dict__
        if self.movecopyto and self.action[1] == 'to':
            intLine = int(self.movecopyto)
            if intLine >= 100 or self.movecopyto.startswith('0'):
                self.movecopyto = intLine  # always absolute
            elif self.currentLine:
                intLine = getLineRelativeTo(intLine, self.currentLine)
                self.movecopyto = intLine
            else:
                self.movecopyto = intLine
        if self.line:
            intLine = int(self.line)
            #print 'intLine: %s, currentLine: %s'% (intLine, self.currentLine)
            if len(self.line) > 2:
                self.line = intLine  # always absolute
            elif self.currentLine:
                intLine = getLineRelativeTo(intLine, self.currentLine)
                print('getLineRelativeTo, old: %s new: %s (currentline: %s)' %
                      (self.line, intLine, self.currentLine))
                self.line = intLine
            else:
                self.line = intLine

        if self.through:
            intThrough = int(self.through)
            if intThrough > self.line:
                self.through = intThrough  # always absolute
            else:
                if len(self.through) == 2:
                    modulo = 100
                else:
                    modulo = 10
                print('modulo for through: %s' % modulo)
                intThrough = getLineRelativeTo(intThrough,
                                               self.line,
                                               modulo=modulo,
                                               minLine=self.line)
                self.through = intThrough

            ## should not happen often:
            if self.line > self.through:
                # calculate the next higher number respective to self.line
                ndigits = len(repr(self.through))
                steps = 10**ndigits
                leftPart = self.line // steps
                newThrough = leftPart * steps + self.through
                while newThrough < self.line:
                    leftPart += 1
                    newThrough = leftPart * steps + self.through
                self.through = newThrough

            self.numlines = self.through - self.line + 1
        #print 'line: "%(line)s", to: "%(through)s", movecopyto: "%(movecopyto)s"' \
        #     ', numlines "%(numlines)s", action: "%(action)s"'%  self.__dict__

        # doing the selection part:
        T = []
        self.goingUp = 0
        if self.previousLines:
            self.goingUp = 1
        if self.nextLines:
            T.append('{extdown}')
        if self.firstPart == 'that':
            pass
        elif self.firstPart == 'lineback':
            T.append('<<lineback>>')
        elif self.firstPart == 'lines':
            if self.goingUp:
                T.append('<<selectpreviousline>>')
                if self.numlines > 1:
                    T.append('<<selectup %s>>' % (self.numlines - 1, ))
            else:
                T.append('<<selectline>>')
                if self.numlines > 1:
                    T.append('<<selectdown %s>>' % (self.numlines - 1, ))
        elif self.firstPart == 'paras':
            print('paragraphs!')
            if self.goingUp:
                print('vorige alinea')
                T.append('<<selectpreviouspara>>')
                if self.numlines > 1:
                    T.append('<<selectparaup %s>>' % (self.numlines - 1, ))
            else:
                print('deze of volgende alinea')
                T.append('<<selectpara>>')
                if self.numlines > 1:
                    T.append('<<selectparadown %s>>' % (self.numlines - 1, ))

        elif self.firstPart == 'linesnum':
            T.append('<<gotoline %s>>' % self.line)
            if self.numlines > 1:
                T.append('<<selectline>>')
                T.append('<<selectdown %s>>' % (self.numlines - 1, ))
            elif self.action != None:
                # only when you call for a single line without action, NO
                # selection is done
                T.append('<<selectline>>')

        t1 = time.time()
        action(''.join(T), comment=comment)
        t2 = time.time()
        ##        print 'line select action: %s'% (t2-t1)
        T = []

        # doing the action part:
        if self.column:
            keystroke("{right %s}" % self.column)
            return
        if not self.action:
            return
        if isinstance(self.action, str):
            action(self.action, comment=comment)
        elif type(self.action) == list:
            if self.action[0] == 'move':
                T.append('<<cut>>')
            elif self.action[0] == 'copy':
                T.append('<<copy>>')
                if not self.prog in ['excel']:
                    if self.lastDirection == 'up':
                        T.append('{extleft}')
                    elif self.lastDirection == 'down':
                        T.append('{extright}')
            else:
                raise LinesError('invalid movecopy action (first word): %s' %
                                 self.action)

            print('gotResult: movecopyto: %s (%s)' %
                  (self.movecopyto, type(self.movecopyto)))
            print('gotResult: numlines: %s' % self.numlines)

            if self.action[1] == 'up':
                if self.prog in ['excel']:
                    T.append("<<movetotopofselection>>")
                if self.prog in ['pycharm64', 'pycharm32']:
                    print('pycharm, %s' % repr(T))
                    if self.action[0] == 'copy':
                        T.append("{ctrl+d}")  # duplicate
                    T.append("{shift+ctrl+up %s}" % self.numlines)
                else:
                    # all other applications
                    T.append('{up %s}' % self.movecopyto)

            elif self.action[1] == 'down':
                if self.prog in ['excel']:
                    T.append("<<movetobottomofselection>>")
                    self.movecopyto += 1
                if self.prog in ['pycharm64', 'pycharm32']:
                    print('pycharm, %s' % repr(T))
                    if T and T[0] == "<<copy>>":
                        T = ["{ctrl+d}"]  ## duplicate
                    else:
                        T = []
                    T.append("{shift+ctrl+down %s}" % self.numlines)
                else:
                    # all other applications:
                    T.append('{down %s}' % self.movecopyto)
            elif self.action[1] == 'to':
                if self.action[0] == 'move' and not self.prog in ['excel']:
                    # if new line below the current line, the cut lines have to be accounted for (not in excel though)
                    currentLine = self.line or self.currentLine
                    if currentLine:
                        if self.movecopyto > currentLine + self.numlines:
                            self.movecopyto -= self.numlines
                    else:
                        print(
                            '_lines: movecopyaction: current line not known, move can be wrong if target is below current line'
                        )

                T.append('<<gotoline %s>>' % self.movecopyto)
            else:
                raise LinesError('invalid movecopy action (second word): %s' %
                                 self.action)
            T.append('<<movecopypaste>>')
            if self.numlines and not self.prog in ['excel']:
                T.append('{extup %s}{exthome}' % self.numlines)
##            action('<<upafterpaste>>', comment=comment)
            T.append('<<afterlines>>')
        if T:
            t1 = time.time()
            action(''.join(T), comment=comment)
            t2 = time.time()
##            print 'line action action: %s'% (t2-t1)

    def fillDefaultInifile(self, ini=None):
        """initialize as a starting example the ini file

        """
        ini = ini or self.ini
        ancestor.fillDefaultInifile(self, ini)
        if self.language == 'nld':
            self.ini.set('simpleaction', 'selecteren', '')
            self.ini.set('simpleaction', 'verwijderen', '{del}')
            self.ini.set('simpleaction', 'knippen', '{ctrl+x}')
            self.ini.set('simpleaction', 'kopiejeren', '{ctrl+c}')
            self.ini.set('simpleaction', 'dupliceren',
                         '{ctrl+c}{right}{ctrl+v}')
            self.ini.set('simpleaction', 'wissen', '{del}')
            self.ini.set('simpleaction', 'einde', '<<endafterselection>>')
            self.ini.set('simpleaction', 'over plakken', '{ctrl+v}')
            self.ini.set('simpleaction', 'plakken', '<<realhome>>{ctrl+v}')
            self.ini.set('simpleaction', 'over plakken', '{ctrl+v}')
            self.ini.set('simpleaction', 'over plakken', '{ctrl+v}')
            self.ini.set('general', 'deactivate', 'sol')
            self.ini.set('general', 'ignore', 'empty')

        elif self.language == 'enx':
            self.ini.set('simpleaction', 'select', '')
            self.ini.set('simpleaction', 'delete', '{del}')
            self.ini.set('simpleaction', 'cut', '{ctrl+x}')
            self.ini.set('simpleaction', 'copy', '{ctrl+c}')
            self.ini.set('simpleaction', 'duplicate',
                         '{ctrl+c}{right}{ctrl+v}')
            self.ini.set('simpleaction', 'end', '<<endafterselection>>')
            self.ini.set('simpleaction', 'paste', '<<realhome>>{ctrl+v}')
            self.ini.set('simpleaction', 'paste over', '{ctrl+v}')
            self.ini.set('general', 'deactivate', 'sol')
            self.ini.set('general', 'ignore', 'empty')
        else:
            self.ini.set('simpleaction', 'select', '')
            self.ini.set('general', 'ignore', 'empty')

    def fillInstanceVariables(self, ini=None):
        """fills instance variables with data from inifile

        overload for grammar lines: get activate/deactivate windows

        """
        try:
            #print 'fillInstantVariables for %s'% self
            ini = ini or self.ini
            self.lineNumbersModuloHundred = self.ini.getBool(
                'general', 'line numbers modulo hundred')
            if self.lineNumbersModuloHundred:
                print(
                    '_lines: do "line numbers modulo hundred" if the application allows this'
                )

            self.activateRules = ini.getDict('general', 'activate')
            if not self.activateRules:
                self.activateRules = {'all': None}
            if '*' in self.activateRules:
                del self.activateRules['*']
                self.activateRules['all'] = None
            for prog in self.activateRules:
                if self.activateRules[prog] == '*':
                    self.activateRules[prog] = None
    ##        print 'self.activateRules: %s'% self.activateRules

            self.deactivateRules = ini.getDict('general', 'deactivate')
            if not self.deactivateRules:
                self.deactivateRules = {'none': None}
            if '*' in self.deactivateRules:
                del self.deactivateRules['*']
                self.deactivateRules['all'] = None
            for prog in self.deactivateRules:
                if self.deactivateRules[prog] == '*':
                    self.deactivateRules[prog] = None
    ##        print 'self.deactivateRules: %s'% self.deactivateRules

            self.ignore = ini.getDict('general', 'ignore')
            if not self.ignore:
                try:
                    mgwn = {'nld': 'muisraster'}[self.language]
                except KeyError:
                    mgwn = 'mouse grid'
                self.ignore = {'empty': None, 'natspeak': mgwn}
            for prog in self.ignore:
                if self.ignore[prog] == '*':
                    self.ignore[prog] = None

    ##        print 'self.ignore: %s'% self.ignore

    # Arnoud, same option needs to be set in _tasks
            self.tasksGrammarName = self.ini.get('general',
                                                 'enable search commands')
            self.tasksGrammar = self.enableSearchCommands = None
            # after a wordspec you can call "search number or task", numbers and tasks
            # corresponding with the _tasks grammar
            if self.tasksGrammarName:
                self.tasksGrammar = natbj.GetGrammarObject(
                    self.tasksGrammarName)
                if self.tasksGrammar:
                    self.enableSearchCommands = 1
                    print(
                        '_lines, enable search commands, coupling grammar %s with %s'
                        % (self.name, self.tasksGrammarName))
                else:
                    print(
                        '_lines, enable search commands failed, invalid name: %s'
                        % self.tasksGrammarName)
                    self.enableSearchCommands = 0

        except inivars.IniError:
            print('IniError while initialising ini variables in _lines')

    def windowPolicy(self, modInfo, progInfo=None):
        progInfo = progInfo or unimacroutils.getProgInfo(modInfo)
        ##        print 'window policy------progInfo: ', `progInfo`
        if unimacroutils.matchWindow(self.activateRules, progInfo=progInfo):
            ##            print 'matching activate: %s'% self.activateRules
            if not unimacroutils.matchWindow(self.deactivateRules,
                                             progInfo=progInfo):
                return 1
예제 #7
0
class ThisGrammar(ancestor):
    """grammar that makes html tags, as defined in an inifile
    """

    language = unimacroutils.getLanguage()        
    iniIgnoreGrammarLists = ['character']

    name = "tags"
    gramSpec = """
<tags> exported = (Tag | HTML Tag | <prefix> Tag | <prefix> HTML Tag )({tagname}|{character}+);
<prefix> = Open | Close | Begin | End | Empty;
    """

    def initialize(self):
        if not self.language:
            print("no valid language in grammar "+__name__+" grammar not initialized")
            return

        self.load(self.gramSpec)
        self.setCharactersList('character')        
        self.switchOnOrOff()

    def gotBegin(self,moduleInfo):
        if self.checkForChanges:
            self.checkInifile()

    def gotResultsInit(self,words,fullResults):
        self.letters = ''
        self.pleft = ''
        self.pright = ''
        self.dictated = ''
        self.onlyOpen = self.onlyClose = self.empty = 0
        
    def gotResults_tags(self,words,fullResults):
        self.letters = self.getFromInifile(words, 'tagname', noWarning=1)
        if not self.letters:
            print('_tags, no valid tagname found: %s'% words)
            return
        for w in words:
            char = self.getCharacterFromSpoken(w)
            if char:
                self.letters += char

    #def gotResults_dgndictation(self,words,fullResults):
    #    """return dictated text, put in between (or before or after the tags)
    #    """
    #    self.dictated, dummy = nsformat.formatWords(words, state=-1)  # no capping, no spacing
    #    #print '-result of nsformat: |%s|'% repr(self.dictated)
    

    def gotResults_prefix(self,words,fullResults):
        self.empty = self.hasCommon(words, ['Empty', 'Lege'])
        self.onlyOpen = self.hasCommon(words, ['Begin', 'Open'])
        self.onlyClose = self.hasCommon(words, ['Sluit', 'Close', 'End', 'Eind'])


    def gotResults(self,words,fullResults):
        tag = self.letters.strip()
##        print 'rule gotResults: %s'% tag
        pleft = pright = ""
        if not tag:
            return
        pleft = '<%s>' % tag
        if tag.find(' ') >= 0:
            endTag  = ' '.split(tag)[0]
        else:
            endTag = tag
        pright = '</%s>' % endTag

        # see of something selected, leave clipboard intact 
        cb =  Clipboard(save_clear=True)
        keystroke('{ctrl+x}')  # try to cut the selection
        contents = cb.Get_text()   #.replace('\r','').strip()
        
        keystroke(pleft)
        if contents:
            #print 'contents: |%s|'% repr(contents)
            keystroke(contents)
        keystroke(pright)

        if not contents:
            # go back so you stand inside the brackets:
            nLeft = len(pright)
            keystroke('{left %s}'% nLeft)

    def fillDefaultInifile(self, ini):
        """filling entries for default ini file

        """
        ancestor.fillDefaultInifile(self, ini)
        if self.language == 'nld':
            tagNames = {
                'Hedder 1':  'h1',
                'Hedder 2':  'h2',
                'Hedder 3':  'h3',
                'tabel':  'table',
                'tabel honderd procent':  'table border="0" cellpadding="0" cellspacing="0" width="100%"',
                'tabel data':  'td',
                'tabel roo':  'tr',
                'Java script':  'script language="JavaScript"', 
                'script':  'script'
            }
            
        elif self.language == 'enx':
            tagNames = {
                'Header 1':  'h1',
                'Header 2':  'h2',
                'Header 3':  'h3',
                'table':  'table',
                'table data':  'td',
                'table row':  'tr',
                'Java script':  'script language="JavaScript"', 
                'script':  'script'
            }
        else:
            print('-----filling ini file %s , invalid language: "%s"! '% \
                  (self.__module__, self.language))
            ini.set('general', 'error', 'invalid language')
            return
        for k, v in list(tagNames.items()):
            ini.set('tagname', k, v)
        # by default switch off initially:
        ini.set('general', 'initial on', '0')
예제 #8
0
class UnittestGrammar(natbj.IniGrammar):
    language = unimacroutils.getLanguage()
    name = 'unimacro test'
    iniIgnoreGrammarLists = ['tests']  # are set in this module
    gramSpec = """
<onetest> exported = unimacro test {tests};
<alltests> exported = unimacro test (all);
    """

    def initialize(self):
        self.load(self.gramSpec)
        self.activateAll()
        self.switchOnOrOff()
        self.setList(
            'tests',
            self.getTestNames())  # also fill self.testNames, self.allTests
        self.filesToSkipInResult = ["unittest.py", "TestCaseWithHelpers.py"]

    def gotBegin(self, moduleInfo):
        if self.checkForChanges:
            self.checkInifile()
            self.setList('tests', self.getTestNames())

    def gotResults_onetest(self, words, fullResults):
        """do one of the unittests"""
        test = words[-1]
        self.doAll = 0
        print("---------------------------------do unimacro unittest for: %s" %
              test)
        self.doUnitTests([test])

    def gotResults_alltests(self, words, fullResults):
        """do all the unittests"""
        print("---------------------------------do all unimacro unittests")
        tests = list(self.allTests.keys())
        tests.sort()
        self.doAll = 1
        self.doUnitTests(tests)

    def getTestNames(self):
        """get the test names, with side effect builds a dict of all the tests

        the result (the testNames) can then be filled in the list {tests}
        self.allTests (dict) contains the names: files entries
        """
        self.testFolder = os.path.join(unimacroutils.getUnimacroDirectory(),
                                       "unimacro_test")
        testFiles = glob.glob(os.path.join(self.testFolder, "*test.py"))
        ##        print 'testFiles: %s'% testFiles
        testNames = list(map(self.extractTestName, testFiles))
        print('testNames: %s' % testNames)
        self.allTests = dict(list(zip(testNames, testFiles)))
        return testNames

    def extractTestName(self, fullPath):
        """remove path, .py and "Test" from filename to get pronouncable test"""
        name = os.path.basename(fullPath).lower()
        name = utilsqh.removeFromEnd(name, ".py", ignoreCase=1)
        name = utilsqh.removeFromEnd(name, "test", ignoreCase=1)
        return name

    def showInifile(self):
        commandExplanation = "Names of tests: \n%s\n---------------" % '\n'.join(
            self.testNames)
        super(UnittestGrammar,
              self).showInifile(commandExplanation=commandExplanation)

    def doUnitTests(self, tests):
        # self.checkSysPath(self.testFolder)  # append unimacro_test if needed
        suiteAll = None
        self.activeTests = []

        for test in tests:
            print('do test %s (%s)' % (test, self.allTests[test]))
            suite = self.addUnitTest(test, self.allTests[test])
            if suite:
                self.activeTests.append(test)
                if suiteAll:
                    suiteAll.addTest(suite)
                else:
                    suiteAll = suite
        if suiteAll:
            natlink.setMicState('off')
            result = unittest.TextTestRunner().run(suiteAll)
            print('after testing------------------------------------')
            self.dumpResult(result, filesToSkip=self.filesToSkipInResult)
            natlink.setMicState('on')

        else:
            print("nothing valid to test")

    def addUnitTest(self, test, fileName):
        """do one of the unittests"""
        ##        actions.Message("starting test %s"% fileName)
        modName = os.path.basename(fileName)
        modName = utilsqh.removeFromEnd(modName, ".py", ignoreCase=1)

        testMod = __import__(modName)
        testClassName = modName
        try:
            testClass = getattr(testMod, testClassName)
        except AttributeError:
            print(
                '****cannot find test class in test module, skipping test: %s'
                % testClassName)
            return
        suite = unittest.makeSuite(testClass, 'test')
        return suite

    def checkSysPath(self, folder):
        """add to sys.path if not present yet"""
        if folder in sys.path:
            return
        print('adding to path: %s' % folder)
        sys.path.append(folder)

    def dumpResult(self, testResult, filesToSkip=None):
        """dump into txt file "testresult" in unimacro_test folder

        slightly different version in voice coder (test_defs.py)
        """
        alert = len(self.activeTests) > 0
        testResultFile = os.path.join(self.testFolder, "testresult.txt")
        f = open(testResultFile, 'w')
        if testResult.wasSuccessful():
            if alert:
                mes = "all succesful: %s" % self.activeTests
                actions.Message(mes, "Unimacro Tests succesful")
            else:
                mes = "test passed: %s" % self.activeTests[0]
                self.DisplayMessage(mes)
            f.write(mes + '\n' * 2)
            f.close()
            return
        f.write("results of tests: %s\n" % self.activeTests)
        f.write('\n--------------- errors -----------------\n')
        for case, tb in testResult.errors:
            f.write('\n---------- %s --------\n' % case)
            cleanTb = utilsqh.cleanTraceback(tb, filesToSkip)
            f.write(cleanTb)
        f.write('\n--------------- failures -----------------\n')
        for case, tb in testResult.failures:
            f.write('\n---------- %s --------\n' % case)
            cleanTb = utilsqh.cleanTraceback(tb, filesToSkip)
            f.write(cleanTb)

        f.close()
        mes = "there were errors with testing unimacro: %s\n\nPlease consult the outputfile: %s"% \
              (self.activeTests, testResultFile)
        actions.Message(mes, "Unimacro Tests failure", alert=alert)
        self.openFileDefault(testResultFile, mode="edit", name='test result')
예제 #9
0
class ThisGrammar(ancestor):

    language = unimacroutils.getLanguage()

    #Step 1, choose one of next three grammar rules:
    # the <integer> rule comes from these grammar rules
    number_rules = natbj.numberGrammarTill999[
        language]  # hundreds, including a long string of digits
    #number_rules = natbj.numberGrammarTill999999[language] # including thousands
    #number_rules = natbj.numberGrammar[language] #  including millions
    # the rules <integer> and <float> are already defined.
    name = "number simple"

    gramSpec = """
<testnumber> exported = Number <number>;
<number> = <integer> | Minus <integer> | <float> | Minus <float>;
""" + number_rules + """
    """

    def __init__(self):
        self.minus = False
        self.number = False
        super().__init__()

    def initialize(self):
        if not self.language:
            print("no valid language in grammar " + __name__ +
                  " grammar not initialized")
            return
        self.load(self.gramSpec)
        # if switching on fillInstanceVariables also fill numbers lists like {n1-9} or {number1to99}
        self.switchOnOrOff()

    def gotResultsInit(self, words, fullResults):
        # Step 2:
        # you can initialise variables here, eg self.minus = None, self.number = ''. Not necessary, but
        # in some grammars more appropriate than in the next function.
        pass

    def gotResults_testnumber(self, words, fullResults):
        # step 3: specify the number you are waiting for
        # check if the word Minus is present, and then wait for the number named "number"
        # note in this example self.number is non existent until collectNumber has been visited.
        # self.minus will only be set if the rule number is visited.
        self.waitForNumber('number')
        self.minus = False

    def gotResults_number(self, words, fullResults):
        # step 3a: when in this rule, the word Minus (or synonym or translation) has been spoken..
        self.minus = True

    def gotResults(self, words, fullResults):
        # step 4, in gotResults collect the number (as a string):
        self.collectNumber(
        )  # setting self.number, see self.waitForNumber above
        print('number from the _number simple grammar: %s' % self.number)
        if self.minus:
            self.number = '-' + self.number
        # disable when testing through unittestIniGrammar.py (in unimacro_test directory):
        self.outputNumber(self.number)

    def outputNumber(self, number):
        #pylint:disable=R0201
        keystroke(number)
        #Step 5:
        # Here some extra postprocessing for different programs:
        prog = unimacroutils.getProgName()
        if prog in ['iexplore', 'firefox', 'chrome', 'safari']:
            keystroke('{tab}')
        elif prog in ['natspeak']:  # DragonPad
            keystroke('{enter}')
        elif prog in ['excel']:
            keystroke('{tab}')
예제 #10
0
class BracketsGrammar(ancestor):
    language = unimacroutils.getLanguage()
    name = "brackets"

    def initialize(self):
        if not self.language:
            print("no valid language in grammar "+__name__+" grammar not initialized")
            return
        self.load(self.gramSpec)
        self.switchOnOrOff()

    def gotBegin(self,moduleInfo):
        if self.checkForChanges:
            self.checkInifile()
        if self.mayBeSwitchedOn == 'exclusive':
            self.switchOnOrOff()

    def gotResultsInit(self, words, fullResults):
        self.dictated = ''  # analysis of dgndictation or dgnletters
        self.pleft = self.pright = '' # the left and right parts of the brackets

        if self.mayBeSwitchedOn == 'exclusive':
            print('recog brackets, switch off mic: %s'% words)
            natbj.SetMic('off')

    def importedrule_dgndictation(self, words):
        #do with nsformat functions:
        self.dictated, dummy = nsformat.formatWords(words, state=-1)  # no capping, no spacing
        #print '-result of nsformat: |%s|'% repr(self.dictated)

    def rule_brackets(self, words):
        "<before> {brackets}+ [<dgndictation>]"
        for w in words:

            p = self.getFromInifile(w, 'brackets')
            if not p:
                print('no valid brackets found for word: "%s"'% w)
                continue
            #print 'brackets, found: %s, %s'% (w, p)
            if len(p) > 2 and p.find("|") > 0:
                pList = p.split("|")
                newpleft = pList[0]
                newpright = pList[1]
            else:
                lenph = int(len(p)/2)
                newpleft, newpright = p[:lenph], p[lenph:]
            # make more brackets together, from outer to inner:
            self.pleft = self.pleft + newpleft
            self.pright = newpright + self.pright
        #print 'pleft: "%s", pright: "%s"'% (repr(self.pleft), repr(self.pright))

    def subrule_before(self, words):
        "(here|between|empty)+"
        self.here, self.between = False, False
        for w in words:
            if self.hasCommon(w, 'between'):   # this is the trigger word, ignore
                self.between = True
            if self.hasCommon(w, 'here'):   # this is the trigger word, ignore
                self.here = True
            if self.hasCommon(w, 'empty'):   # this is the trigger word, ignore
                self.between = False


    def gotResults(self, words, fullResults):

        #  see if something selected, leaving the clipboard intact
        #  keystroke('{ctrl+x}')  # try to cut the selection
        if self.between:
            cb = Clipboard(save_clear=True)
            action('<<cut>>')
            text = cb.get_text(waiting_interval=0.1, waiting_iterations=3)
        else:
            text = ""

        if self.here:
            unimacroutils.buttonClick('left', 1)
            unimacroutils.visibleWait()

        leftText = rightText = leftTextDict = rightTextDict = ""
        if text:
            # strip from clipboard text:
            text, leftText, rightText = stripFromBothSides((text))

        if self.dictated.strip():
            text, leftTextDict, rightTextDict = stripFromBothSides(self.dictated)
        elif self.dictated:
            # the case of only a space-bar:
            leftTextDict = self.dictated


        lSpacing = leftText + leftTextDict
        rSpacing = rightTextDict + rightText

        if lSpacing:
            keystroke(lSpacing)

        action(self.pleft)
        unimacroutils.visibleWait()
        if text:
            #print 'text: |%s|'% repr(text)
            keystroke(text)
        unimacroutils.visibleWait()
        action(self.pright)
        unimacroutils.visibleWait()

        if rSpacing:
            keystroke(rSpacing)

        if not text:
            # go back so you stand inside the (brackets):
            nLeft = len(self.pright) + len(rSpacing)
            keystroke('{left %s}'% nLeft)
# [(hello)]
    def fillDefaultInifile(self, ini):
        """filling entries for default ini file

complex


        """
        if self.language == 'nld':
            ini.set('brackets', 'aanhalingstekens', '""')
            ini.set('brackets', 'kwoots', "''")
            ini.set('brackets', 'brekkits', '[]')
            ini.set('brackets', 'haakjes', '()')
            ini.set('brackets', 'punt haakjes', '<>')
            ini.set('brackets', 'driedubbele aanhalingstekens', '""""""')
            ini.set('brackets', 'accolades', '{}')
            ini.set('brackets', 'html punt haakjes', "&lt;|>")
            ini.set('brackets', 'html brekkits', "&#091;|]")
        else:
            ini.set('brackets', 'double quotes', '""')
            ini.set('brackets', 'quotes', "''")
            ini.set('brackets', 'single quotes', "''")
            ini.set('brackets', 'square brackets', '[]')
            ini.set('brackets', 'brackets', '()')
            ini.set('brackets', 'parenthesis', '()')
            ini.set('brackets', 'backticks', '``')
            ini.set('brackets', 'parens', '()')
            ini.set('brackets', 'angle brackets', '<>')
            ini.set('brackets', 'triple quotes', '""""""')
            ini.set('brackets', 'html angle brackets', "&lt;|>")
            ini.set('brackets', 'html square brackets', "&#091;|]")
            ini.set('brackets', 'braces', '{}')
예제 #11
0
class ThisGrammar(ancestor):
    language = unimacroutils.getLanguage()

    name = "latex"
    gramSpec = """
<dgndictation> imported;
<structure> exported =  begin {floating} [<dgndictation>];
<reference> exported =  reference ({floating} | {label}) <dgndictation>;
<namereference> exported =  name reference ({floating} | {label}) <dgndictation>;
<label> exported =  label ({floating} | {label}) <dgndictation>;
<command> exported =  {commands} [with] [ (arguments [{arguments}]) | (that | ([this] line)) ] [(and | with) label];
<options> exported =  add option [{options}];
<replace> exported = replace {placeholders} [with <dgndictation>]; 
    """

    def initialize(self):
        if not self.language:
            print("no valid language in grammar " + __name__ +
                  " grammar not initialized")
            return

        self.load(self.gramSpec)
        self.switchOnOrOff()

    def gotBegin(self, moduleInfo):
        if self.checkForChanges:
            self.checkInifile()

    def gotResultsInit(self, words, fullResults):
        self.dictation = ''
        self.floating = ''
        self.label = 0
        self.reference = ''
        self.namereference = ''
        self.label_text = ''
        self.Cmd = ''
        self.replace_text = 0

    def gotResults_replace(self, words, fullResults):
        place = self.getFromInifile(words, 'placeholders', noWarning=1)
        action('<<startsearch>>')
        keystroke(place)
        action('<<searchgo>>')
        action('<<cancel>>')
        if self.hasCommon(words, ['with']):
            self.replace_text = 1

    def gotResults_command(self, words, fullResults):
        initial = self.getFromInifile(words, 'commands', noWarning=1)
        pos = initial.find('{')
        print(pos)
        contents = ''
        if self.hasCommon(words, ['arguments']):
            if pos > 0:
                Cmd = initial[:pos + 1]
            else:
                Cmd = initial + '{'
            args = self.getFromInifile(words, 'arguments', noWarning=1)
            Cmd = Cmd + args + '}'
            print(Cmd)
        else:
            Cmd = initial
        if self.hasCommon(words, ['that']):
            contents = self.get_selection_that(line=0)
        if self.hasCommon(words, ['line']):
            contents = self.get_selection_that(line=1)

        stringpaste(Cmd)
        if pos > 0 or self.hasCommon(words, ['arguments']):
            keystroke('{left}')
        if contents:
            if pos == -1:
                stringpaste('{')
            stringpaste(contents)
            if pos == -1:
                stringpaste('}')
            else:
                keystroke('{right}')
        if self.hasCommon(words, ['label']):
            label = self.getFromInifile(words, 'label', noWarning=1)
            if label:
                ## workaround for keystrokes: {{}
                keystroke('{enter}')
                stringpaste(r'\label{}%s}' %
                            (self.makes_label(label, contents)))
                keystroke('{enter}')

    def gotResults_options(self, words, fullResults):
        selection = self.view_selection_current_line()
        options = self.getFromInifile(words, 'options', noWarning=1)
        present = 1
        squared = selection.find(']')
        only = 1
        if squared == -1:
            squared = selection.find('{')
            present = 0
        else:
            squared = squared + 1
            start = selection.find('[')
            if start != squared - 2:
                only = 0
        if squared == -1:
            keystroke('{end}')
        else:
            keystroke('{home}')
            for i in range(0, squared):
                keystroke('{right}')
            if present == 0:
                keystroke('[')
            if options:
                if present == 1:
                    keystroke('{left}')
                if only == 0:
                    keystroke(',')
                keystroke(options)
            if present == 0:
                keystroke(']')
            if not options:
                keystroke('{left}')

    def gotResults_reference(self, words, fullResults):
        self.reference = self.getFromInifile(words, 'floating', noWarning=1) or \
                         self.getFromInifile(words, 'label', noWarning = 1)

    def gotResults_namereference(self, words, fullResults):
        self.namereference = self.getFromInifile(words, 'floating', noWarning=1) or \
                         self.getFromInifile(words, 'label', noWarning = 1)

    def gotResults_label(self, words, fullResults):
        self.label_text = self.getFromInifile(words, 'floating', noWarning=1) or \
                         self.getFromInifile(words, 'label', noWarning = 1)

    def gotResults_structure(self, words, fullResults):
        self.floating = self.getFromInifile(words, 'floating', noWarning=1)

    def gotResults(self, words, fullResults):
        if self.floating:
            floatingString = r'\begin{%s}' % self.floating
            stringpaste(floatingString)
            keystroke('{enter}')
            if self.dictation:
                labelString = self.makes_label(self.floating, self.dictation)
                dictationString = r'\label{%s}' % labelString
                stringpaste(dictationString)
            keystroke('{enter}')
            floatingString = '\\end{%s}' % self.floating
            stringpaste(floatingString)
            keystroke('{up}')
            print('floating: %s' % self.floating)
        if self.reference:
            stringpaste('\\ref{%s}' %
                        (self.makes_label(self.reference, self.dictation)))
        if self.namereference:
            stringpaste('\\nameref{%s}' %
                        (self.makes_label(self.namereference, self.dictation)))
        if self.label_text:
            stringpaste('\\label{%s}' %
                        (self.makes_label(self.label_text, self.dictation)))
        if self.replace_text:
            stringpaste(self.dictation)

    def gotResults_dgndictation(self, words, fullResults):
        """do with nsformat functions"""
        print('got dgndictation: %s' % words)
        self.dictation, dummy = nsformat.formatWords(
            words)  # state not needed in call
        print('   result of nsformat:  %s' % repr(self.dictation))

    def get_selection_that(self, line=0):
        unimacroutils.saveClipboard()

        if line:
            action('<<selectline>><<cut>>')
        else:
            action('<<cut>>')
        contents = natlink.getClipboard().strip().replace('\r', '')
        if len(contents) == 0:
            if line:
                print('_latex, empty line')
                return ""
            action('HW select that')
            action('<<cut>>')
            contents = natlink.getClipboard().strip().replace('\r', '')
            if len(contents) == 0:
                print(
                    '_latex, empty contents, no last dicatate utterance available'
                )

        unimacroutils.restoreClipboard()
        return contents

    def view_selection_current_line(self):
        unimacroutils.saveClipboard()
        keystroke('{ctrl+c}')
        contents = natlink.getClipboard()
        if len(contents) == 0:
            print('no_space_by_existing selection')
            keystroke('{end}{shift+home}')
            keystroke('{ctrl+c}')
            contents = natlink.getClipboard()
        unimacroutils.restoreClipboard()
        return contents

    def makes_label(self, type, text):
        return type + ':' + ''.join(text.split()).lower()
예제 #12
0
class ThisGrammar(ancestor):
    """grammar recent folder dialog
    
    only to be switched on if dialog is there, if dialog is gone, the grammar rules set is deactivated
    """
    language = unimacroutils.getLanguage()
    name = "natspeak dialog"

    setRecentFolderDialog = ["chooserfd", "okcancelrfd"]

    gramSpec = """
<chooserfd> exported = choose {number};
<okcancelrfd> exported = OK | Cancel;
    """

    def initialize(self):
        if not self.language:
            print("no valid language in grammar " + __name__ +
                  " grammar not initialized")
            return
        self.load(self.gramSpec)
        print('loaded: %s' % self.gramSpec)
        self.prevHndle = None

    def gotBegin(self, moduleInfo):
        """switch rfd (recent folders dialog) on
        
        if title matches what is provided in _folders grammar.
        """
        hndle = moduleInfo[2]
        if hndle == self.prevHndle:
            return
        self.prevHndle = hndle
        if unimacroutils.matchModule('natspeak'):
            # try to reach data from _folders grammar:
            self.foldersGram = natbj.GetGrammarObject('folders')
            #print 'self.foldersGram: %s'% self.foldersGram
            if self.foldersGram is None:
                return
            dTitle = self.foldersGram.dialogWindowTitle
            dRange = self.foldersGram.dialogNumberRange
            if dTitle and unimacroutils.matchModule(
                    'natspeak', wantedTitle=dTitle, titleExact=1, caseExact=1):
                self.activateSet(self.setRecentFolderDialog)
                self.setNumbersList('number', dRange)
                return
        # other situations:
        self.deactivateAll()

    def gotResults_chooserfd(self, words, fullResults):
        """result from the recent folders dialog
        
        extract the number, then close the dialog and
        then call the relevant function from the folders grammar
        """
        wNumList = self.getNumbersFromSpoken(words)  # returns a string or None
        if len(wNumList) != 1:
            print('natspeak dialog: error in command, no number found: %s' %
                  wNumList)
            return
        chooseNum = wNumList[0]
        self.exitDialog()
        self.foldersGram.gotoRecentFolder(
            chooseNum - 1)  # remember choose is 1 based, the list is 0 based

    def gotResults_okcancelrfd(self, words, fullResults):
        print('dialog ok cancel: %s, just close the dialog' % words)
        self.exitDialog()

    def exitDialog(self):
        """finish the open dialog, normally by pressing enter"""
        dTitle = self.foldersGram.dialogWindowTitle
        if dTitle and unimacroutils.matchModule(
                'natspeak', wantedTitle=dTitle, titleExact=1, caseExact=1):
            unimacroutils.rememberWindow()
            keystroke("{enter}")  # exit dialog.
        unimacroutils.waitForNewWindow()
예제 #13
0
class UtilGrammar(ancestor):
    language = unimacroutils.getLanguage()
    iniIgnoreGrammarLists = ['gramnames', 'tracecount',
                             'message']  # are set in this module

    name = 'control'
    ##    normalSet = ['show', 'edit', 'trace', 'switch', 'message']
    ##    exclusiveSet = ['showexclusive', 'message']
    # commands for controlling module actions
    if actions:
        actionName = "| actions"
    else:
        actionName = ""

    gramSpec = """
<show> exported = show ('all grammars' | 
                        ([grammar|inifile] {gramnames}) 
                         """ + actionName + """);
<edit> exported = edit ([grammar|inifile] {gramnames}""" + actionName + """);
<trace> exported = trace [on|off| {tracecount}]
              ('all grammars' | [grammar] {gramnames}""" + actionName + """) [on|off| {tracecount}] ;
<switch> exported = switch [on|off]
              ('all grammars' | [grammar] {gramnames})[on|off];
<voicecode> exported = 'switch on voicecode';
<showexclusive> exported = show exclusive [grammars];
<resetexclusive> exported = reset exclusive [grammars];
<message> exported = {message};
    """

    Mode = Normal
    LastMode = Normal
    CurrentWord = 0
    Repeat = 0

    def initialize(self):
        global loadedNames
        if not self.load(self.gramSpec, allResults=1):
            return None
        natbj.RegisterControlObject(self)
        self.emptyList('message')
        self.emptyList('gramnames')
        self.setList('tracecount', tracecount)
        self.activateAll()
        self.setMode(Normal)
        self.doMessages = None
        self.startExclusive = self.exclusive  # exclusive state at start of recognition!
##        if unimacroutils.getUser() == 'martijn':
##            print 'martijn, set exclusive %s'% self.name
##            self.setExclusive(1)

    def unload(self):
        natbj.UnRegisterControlObject(self)
        ancestor.unload(self)

    def gotBegin(self, moduleInfo):
        #Now is the time to get the names of the grammar objects and
        # activate the list for the <ShowTrainGrammar> rule
        if natbj.grammarsChanged:
            ##            print 'new list for control: %s'% natbj.loadedGrammars.keys()
            self.setList('gramnames', list(natbj.loadedGrammars.keys()))
            natbj.ClearGrammarsChangedFlag()
        if self.checkForChanges:
            self.checkInifile()

        self.startExclusive = self.exclusive  # exclusive state at start of recognition!

    def gotResultsInit(self, words, fullResults):
        if self.mayBeSwitchedOn == 'exclusive':
            print('recog controle, switch off mic: %s' % words)
            natbj.SetMic('off')
        if self.exclusive and self.doMessages:
            self.DisplayMessage('<%s>' % ' '.join(words))

    def resetExclusiveMode(self):
        """no activateAll, do nothing, this grammar follows the last unexclusive grammar
        """
        pass

    def setExclusiveMode(self):
        """no nothing, control follows other exclusive grammars
        """
        pass

    def gotResultsObject(self, recogType, resObj):
        if natbj.IsDisplayingMessage:
            return
        if self.doMessages:
            mes = natbj.GetPendingMessage()
            if mes:
                mes = '\n\n'.join(mes)
                natbj.ClearPendingMessage()
                self.DisplayMessage(mes)
                return
            unimacroutils.doPendingBringUps()  # if there were

        if self.startExclusive and self.exclusive and showAll:
            # display recognition results for exclusive grammars
            # with showAll = None (in top of this file), you can disable this feature
            if recogType == 'reject':
                URName = ''
                exclGram = natbj.exclusiveGrammars
                exclGramKeys = list(exclGram.keys())
                if len(exclGramKeys) > 1 and self.name in exclGramKeys:
                    exclGramKeys.remove(self.name)
                if len(exclGramKeys) > 1:
                    URName = ', '.join(exclGramKeys)
                k = exclGramKeys[0]
                v = exclGram[k]
                # UE stands for unrecognised exclusive:
                # if more exclusive grammars,
                # the last one is taken
                URName = URName or v[
                    2]  # combined name or last rule of excl grammar
                if self.doMessages:
                    self.DisplayMessage('<' + URName + ': ???>', alsoPrint=0)

    #Utilities for Filter Modes and other special modes
    def setMode(self, NewMode):
        self.LastMode = self.Mode
        self.Mode = NewMode

    def restoreMode(self):
        self.Mode = self.LastMode

    def gotResults_trace(self, words, fullResults):
        print('control, trace: %s' % words)
        if self.hasCommon(words, 'actions'):
            if self.hasCommon(words, 'show'):
                actions.debugActionsShow()
            elif self.hasCommon(words, 'off'):
                actions.debugActions(0)
            elif self.hasCommon(words, 'on'):
                actions.debugActions(1)
            elif words[-1] in tracecount:
                actions.debugActions(int(words[-1]))
            else:
                actions.debugActions(1)

    def gotResults_voicecode(self, words, fullResults):
        """switch on if requirements are fulfilled

        voicecodeHome must exist
        emacs must be in foreground
        """
        wxmed = os.path.join(voicecodeHome, 'mediator', 'wxmediator.py')
        if os.path.isfile(wxmed):
            commandLine = r"%spython.exe %s > D:\foo1.txt >> D:\foo2.txt" % (
                sys.prefix, wxmed)
            os.system(commandLine)
        else:
            print('not a file: %s' % wxmed)

    def gotResults_switch(self, words, fullResults):
        print('control, switch: %s' % words)
        if self.hasCommon(words, 'on'):
            func = 'switchOn'
        elif self.hasCommon(words, 'off'):
            func = 'switchOff'
        else:
            try:
                t = {
                    'nld': '<%s: ongeldig schakel-commando>' % self.GetName()
                }[self.language]
            except:
                t = '<%s: invalid switch command>' % self.GetName()
            if self.doMessages:
                self.DisplayMessage(t)
            return
        if self.hasCommon(words, 'all grammars'):
            print('%s all grammars:' % func)
            natbj.CallAllGrammarObjects(func, ())
            print("-" * 10)
        else:
            gramname = self.hasCommon(words, list(natbj.loadedGrammars.keys()))
            if gramname:
                gram = natbj.loadedGrammars[gramname]
                gram.callIfExists(func, ())
            else:
                print('no grammar name found: %s' % gramname)

    def gotResults_showexclusive(self, words, fullResults):
        if natbj.exclusiveGrammars:
            T = ['exclusive grammars:']
            for e in natbj.exclusiveGrammars:
                T.append(e)
            T.append(self.name)
            if self.doMessages:
                self.DisplayMessage(' '.join(T))
        else:
            if self.doMessages:
                self.DisplayMessage('no exclusive grammars')

    def gotResults_resetexclusive(self, words, fullResults):
        print('reset exclusive')
        if natbj.exclusiveGrammars:
            T = ['exclusive grammars:']
            for e in natbj.exclusiveGrammars:
                T.append(e)
            T.append(self.name)
            T.append('... reset exclusive mode')
            if self.doMessages:
                self.DisplayMessage(' '.join(T))
            natbj.GlobalResetExclusiveMode()
            unimacroutils.Wait(1)
            if self.doMessages:
                self.DisplayMessage('reset exclusive mode OK')
        else:
            if self.doMessages:
                self.DisplayMessage('no exclusive grammars')


##    def setExclusive(self, state):
##        """control grammar, do NOT register, set and maintain state
##
##        special position because of ControlGrammar
##        """
##        print 'control set exclusive: %s'% state
##        if state == None:
##            return
##        if state == self.exclusive:
##            return
##        print 'control, (re)set exclusive: %s'% state
##        self.gramObj.setExclusive(state)
##        self.exclusive = state

    def gotResults_show(self, words, fullResults):
        # special case for actions:
        if self.hasCommon(words, 'actions'):
            actions.showActions()
            return

        if natbj.exclusiveGrammars:
            print('exclusive (+ control) are: %s' %
                  ' '.join(list(natbj.exclusiveGrammars.keys())))

        grammars = natbj.loadedGrammars
        gramNames = list(grammars.keys())
        gramName = self.hasCommon(words, gramNames)
        if gramName:
            grammar = grammars[gramName]
            if not grammar.onOrOff:
                # off, show message:
                self.offInfo(grammar)
                return
            if not self.hasCommon(words, 'grammar'):
                try:
                    grammar.showInifile()
                    return
                except AttributeError:
                    try:
                        grammar.showGrammar()
                        return
                    except AttributeError:
                        pass

        # now show the grammar in the browser application:
        if gramName:
            name = [gramName]
        else:
            name = words[1:-1]

        if (len(name) > 0) and (
                name[0]
                == 'previous'):  #shortcut: show previously assembled grammar
            pypath = '.'
            for x in sys.path:
                pypath = pypath + ';' + x
            os.environ['PYTHONPATH'] = pypath
            AppBringUp('Browser',
                       Exec=PythonwinExe,
                       Args='/app BrowseGrammarApp.py')
        else:
            All = 1
            if len(name) > 0:
                All = self.hasCommon(words, 'all grammars')
                if self.hasCommon(words, ['all', 'active']):
                    name = name[1:]
            if len(name) > 0:
                Start = (' '.join(name), [])
            else:
                Start = ()
            print('start browsing with: %s' % All)
            self.Browse(Start, All)

    def gotResults_edit(self, words, fullResults):
        # special case for actions:
        if self.hasCommon(words, 'actions'):
            actions.editActions()
            return

        grammars = natbj.loadedGrammars
        gramNames = list(grammars.keys())
        gramName = self.hasCommon(words[-1:], gramNames)
        if gramName:
            grammar = grammars[gramName]
            if self.hasCommon(words, 'grammar'):
                module = grammar.__module__
                filename = unimacroutils.getModuleFilename(module)
                #print 'open for edit file: %s'% filename
                self.openFileDefault(filename,
                                     mode="edit",
                                     name='edit grammar %s' % gramName)
                unimacroutils.setCheckForGrammarChanges(1)
            else:
                # edit the inifile
                try:
                    grammar.switchOn()
                    grammar.editInifile()
                except AttributeError:
                    if self.doMessages:
                        self.DisplayMessage(
                            'grammar "%s" has no method "editInifile"' %
                            gramName)
                    return
        else:
            print('no grammar name found')

    def switchOff(self, **kw):
        """overload, this grammar never switches off

        """
        print('remains switched on: %s' % self)

    def switchOn(self, **kw):
        """overload, just switch on

        """
        self.activateAll()

    def offInfo(self, grammar):
        """gives a nice message that the grammar is switched off

        Gives also information on how to switch on.

        """
        name = grammar.getName()
        try:
            t = {
                'nld': [
                    'Grammatica "%s" is uitgeschakeld' % name, '',
                    '"Schakel grammatica %s in" om te activeren' % name
                ]
            }[self.language]
            title = {'nld': 'Grammatica %s' % name}[self.language]
        except KeyError:
            t = [
                'Grammar "%s" is switched off' % name,
                '"Switch On Grammar %s" to activate' % name
            ]
            title = 'Grammar %s' % name
        if natbj.loadedMessageGrammar:
            t = ';  '.join(t)
            if self.doMessages:
                self.DisplayMessage(t)
        else:
            actions.Message(t)
예제 #14
0
class ThisGrammar(ancestor):

    language = unimacroutils.getLanguage()
    normalRules = ['calcnormal', 'cancel']
    calcRules = ['calccalc', 'cancel']  # exclusive
    continueRules = ['calccontinue', 'cancel']  # exclusive

    #see grammar _numbers.py (or _numbers_simple.py or _numbers_extended.py)
    #for instructions on the (quite complicated) number rules
    number_rules = natbj.numberGrammarTill999[
        language]  # hundreds, including a long string of digits

    name = "calculator"

    gramSpec = """
<calcnormal> exported = calculate (<number>|<operator>)+ [equals];
<calccalc> exported = [calculate] (<number>|<operator>)+ [equals];
<calccontinue> exported = equals | (<number>|<operator>)+;
<number> = <integer> | <float>;
<operator> = {operator};
<cancel> exported = Cancel [Calculator] | Calculator Cancel;
""" + number_rules + """
    """

    def initialize(self):
        if not self.language:
            print("no valid language in grammar " + __name__ +
                  " grammar not initialized")
            return
        self.load(self.gramSpec)
        # if switching on fillInstanceVariables also fill numbers lists like {n1-9} or {number1to99}
        self.switchOnOrOff()
        self.inCalculation = False
        self.activeSet = None
        self.minus = ''
        self.number = ''
        self.prevModInfo = None
        self.prog = None
        self.exclusive = 0
        self.lastResult = None
        self.startwithLastResult = False

    def gotBegin(self, moduleInfo):
        if self.checkForChanges:
            self.checkInifile()
        if self.prevModInfo != moduleInfo:
            progInfo = unimacroutils.getProgInfo(modInfo=moduleInfo)
            self.prevModInfo = moduleInfo
            self.cancelMode()
            self.prog = progInfo.prog
            if self.prog == 'calc':
                self.activeSet = None
            else:
                if self.exclusive:
                    self.activeSet = None  # reinitialize non exclusive

        if self.inCalculation:
            if self.prog != 'calc':
                if not self.activeSet == self.continueRules:
                    self.activeSet = copy.copy(self.continueRules)
                    self.exclusive = 1
                    self.activateSet(self.activeSet, exclusive=self.exclusive)
                    print("calculation, exclusiveRules activated")
        else:
            if self.prog == 'calc':
                if not self.activeSet == self.calcRules:
                    self.activeSet = copy.copy(self.calcRules)
                    self.exclusive = 1
                    self.activateSet(self.activeSet, exclusive=self.exclusive)
                    print("calc, exclusive rules activated")
            else:
                if not self.activeSet == self.normalRules:
                    if self.activeSet:
                        print("calculation, activate normalRules again")
                    self.activeSet = copy.copy(self.normalRules)
                    self.exclusive = 0
                    self.activateSet(self.activeSet, exclusive=self.exclusive)

    def gotResultsInit(self, words, fullResults):
        # Step 2:
        # you can initialise variables here, eg self.minus = None, self.number = ''. Not necessary, but
        # in some grammars more appropriate than in the next function.
        if self.inCalculation:
            pass
            # print 'continue calculation %s'% words
        else:
            ## reset, to be sure:
            self.calculation = []
            self.hadNumber = self.hadOperator = False

        if self.exclusive:
            print('calculation exclusive, wait for number')
            self.waitForNumber('number')
        # starting with no lastresult:
        self.startwithLastResult = False

    def fillInstanceVariables(self):
        """fills the necessary instance variables
        records the unary or possibly unary operators
        
        """
        self.unaryLeftOperators = self.ini.getList('general',
                                                   'unary left operators')
        self.unaryRightOperators = self.ini.getList('general',
                                                    'unary right operators')
        self.dualOperators = self.ini.getList(
            'general', 'dual operators'
        )  ## may be incomplete, but for double functions, like minus

    def reset(self):
        pass

    def gotResults_calcnormal(self, words, fullResults):
        # step 3: specify the number you are waiting for
        # check if the word Minus is present, and then wait for the number named "number"
        # note in this example self.number is non existent until collectNumber has been visited.
        # self.minus will only be set if the rule number is visited.
        # print 'calcnormal or calccalc'
        if self.hasCommon(words, 'calculate'):
            if self.prog == 'calc':
                print('calculate, clear previous calculation')
                keystroke("{esc}")
            self.waitForNumber('number')
            self.minus = False
            self.inCalculation = True

        elif self.hasCommon(words, 'equals'):
            self.collectNumberAddToCalculation()
            self.calculation.append("=")
            self.doCalculation()
            return

    gotResults_calccalc = gotResults_calcnormal

    def gotResults_calccontinue(self, words, fullResults):
        # step 3: specify the number you are waiting for
        # check if the word Minus is present, and then wait for the number named "number"
        # note in this example self.number is non existent until collectNumber has been visited.
        # self.minus will only be set if the rule number is visited.
        if not self.inCalculation:
            raise Exception("_calculator, shoud be in a calculation right now")

        if self.hasCommon(words, 'equals'):
            self.collectNumberAddToCalculation()
            self.calculation.append("=")
            self.doCalculation()
            self.inCalculation = False

    def gotResults_number(self, words, fullResults):
        # this rule only catches with the word "minus"
        print('calculator: rule number, %s' % words)
        # self.waitForNumber('number')
        self.minus = not self.minus

    def gotResults_operator(self, words, fullResults):
        # step 3: specify the number you are waiting for
        # check if the word Minus is present, and then wait for the number named "number"
        # note in this example self.number is non existent until collectNumber has been visited.
        # self.minus will only be set if the rule number is visited.

        for w in words:
            self.collectNumberAddToCalculation()
            print('rule operator, hadOperator: %s, hadNumber %s' %
                  (self.hadOperator, self.hadNumber))
            operator = self.getFromInifile(w, 'operator')
            operatorStripped = operator.strip()

            unaryLeft = w in self.unaryLeftOperators
            unaryRight = w in self.unaryRightOperators
            possiblyDual = w in self.dualOperators

            if self.hadNumber:
                if unaryRight:
                    pass
                elif possiblyDual or not unaryLeft:
                    self.hadNumber = False  # just set now
                else:
                    print('no unaryLeft operator expected: %s' % w)
                    continue
            else:
                if unaryLeft and not possiblyDual:
                    pass
                elif w == words[0]:
                    self.startwithLastResult = True

            if self.hadOperator:
                operator = operator.strip()

            self.calculation.append(operator)
            if not unaryRight:
                self.hadOperator = True

    def gotResults_cancel(self, words, fullResults):
        self.cancelMode()

    def gotResults(self, words, fullResults):
        # step 4, in gotResults collect the number (as a string):
        self.collectNumberAddToCalculation(
        )  # setting self.number, see self.waitForNumber above
        if self.calculation:
            if self.prog == 'calc':
                print('calculation sofar (calc): %s' %
                      ''.join(self.calculation))
                self.doCalculation()
            else:
                print(
                    'continue calculation or finish with "equals" (or "cancel")'
                )
                print('calculation sofar: %s' % ''.join(self.calculation))

    def collectNumberAddToCalculation(self):
        """collect the number, and add to self.calculation
        
        also wait again for new number...
        """
        self.collectNumber()
        self.hadNumber = False
        if self.number:
            # if not self.hadOperator:
            #     print 'no operator found, for new number: %s'% self.number
            self.hadNumber = True
            self.hadOperator = False
            if self.minus:
                self.number = '-' + self.number
            self.calculation.append(self.number)
            self.number = ''
            self.waitForNumber('number')

    def doCalculation(self):
        if not self.calculation:
            print('doCalculation, no calculation ready')
            return
        if not self.inCalculation and self.prog != 'calc':
            print('not in a calculation')
            return

        if self.startwithLastResult:
            self.calculation.insert(0, str(self.lastResult))

        calculationpython = ''.join([c for c in self.calculation if c != "="])
        # place for python specific tricks:
        if calculationpython.find(',') >= 0:
            calculationpython = calculationpython.replace(',', '.')
        result = eval(calculationpython)
        self.lastResult = result

        if self.prog in ['calc']:
            if self.startwithLastResult:
                del self.calculation[
                    0]  # take memory from calculator, not from this list...
                print(
                    'in calc, continuation of calculation, expect lastResult: %s'
                    % self.lastResult)
            for c in self.calculation:
                keystroke(c.strip())

        elif self.prog in ['natspeak']:  # DragonPad
            print('%s = %s' % (calculationpython, result))
        elif self.prog in ['excel']:
            calculationExcel = [
                c.strip() for c in self.calculation if c != "="
            ]
            calculationExcel = '=' + ''.join(calculationExcel) + "{tab}"
            keystroke(calculationExcel)
        else:
            print("calc: %s = %s" % (calculationpython, result))
            keystroke('%s' % result)

        self.inCalculation = False
        self.calculation = []

    def cancelMode(self):
        #print "end of oops exclusive mode", also called when microphone is toggled.
        ##        print 'resetting oops grammar'
        if self.inCalculation:
            print('%s, cancel exclusive mode' % self.name)
            self.activeSet = None
            self.deactivateAll()
            self.inCalculation = False
            self.lastResult = None
        self.calculation = []