TextViewer.py
changeset 543 2f660878c2a7
parent 523 99ba2e3949ed
child 546 f28df922efbe
equal deleted inserted replaced
542:cce4903be769 543:2f660878c2a7
    38 LETTERS = ['_']
    38 LETTERS = ['_']
    39 for i in xrange(26):
    39 for i in xrange(26):
    40     LETTERS.append(chr(ord('a') + i))
    40     LETTERS.append(chr(ord('a') + i))
    41     LETTERS.append(chr(ord('A') + i))
    41     LETTERS.append(chr(ord('A') + i))
    42 
    42 
    43 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_VARIABLE, 
    43 [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, 
    44  STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(7)
    44  STC_PLC_VARIABLE, STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(8)
    45 [SPACE, WORD, NUMBER, COMMENT] = range(4)
    45 [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT] = range(6)
    46 
    46 
    47 [ID_TEXTVIEWER,
    47 [ID_TEXTVIEWER,
    48 ] = [wx.NewId() for _init_ctrls in range(1)]
    48 ] = [wx.NewId() for _init_ctrls in range(1)]
    49 
    49 
    50 if wx.Platform == '__WXMSW__':
    50 if wx.Platform == '__WXMSW__':
    65 re_texts["letter"] = "[A-Za-z]"
    65 re_texts["letter"] = "[A-Za-z]"
    66 re_texts["digit"] = "[0-9]"
    66 re_texts["digit"] = "[0-9]"
    67 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
    67 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
    68 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
    68 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
    69 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
    69 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
       
    70 EXTENSIBLE_PARAMETER = re.compile("IN[1-9][0-9]*$")
    70 
    71 
    71 def GetCursorPos(old, new):
    72 def GetCursorPos(old, new):
    72     old_length = len(old)
    73     old_length = len(old)
    73     new_length = len(new)
    74     new_length = len(new)
    74     common_length = min(old_length, new_length)
    75     common_length = min(old_length, new_length)
   120         self.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
   121         self.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
   121         self.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
   122         self.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
   122         self.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
   123         self.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
   123         self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
   124         self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
   124         self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
   125         self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
       
   126         self.StyleSetSpec(STC_PLC_STRING, "fore:#7F007F,size:%(size)d" % faces)
   125         self.StyleSetSpec(STC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces)
   127         self.StyleSetSpec(STC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces)
   126         self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   128         self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces)
   127         
   129         
   128         # Indicators styles
   130         # Indicators styles
   129         self.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
   131         self.IndicatorSetStyle(0, wx.stc.STC_INDIC_SQUIGGLE)
   140         self.SetTabWidth(2)
   142         self.SetTabWidth(2)
   141         self.SetUseTabs(0)
   143         self.SetUseTabs(0)
   142         
   144         
   143         self.Keywords = []
   145         self.Keywords = []
   144         self.Variables = {}
   146         self.Variables = {}
   145         self.Functions = []
   147         self.Functions = {}
       
   148         self.TypeNames = []
   146         self.Jumps = []
   149         self.Jumps = []
   147         self.EnumeratedValues = []
   150         self.EnumeratedValues = []
   148         self.DisableEvents = True
   151         self.DisableEvents = True
   149         self.TextSyntax = "ST"
   152         self.TextSyntax = "ST"
   150         self.CurrentAction = None
   153         self.CurrentAction = None
   151         self.TagName = tagname
   154         self.TagName = tagname
   152         self.Errors = []
   155         self.Errors = []
   153         self.Debug = debug
   156         self.Debug = debug
   154         self.InstancePath = instancepath
   157         self.InstancePath = instancepath
   155         self.StructElementsStack = []
   158         self.StructElementsStack = []
       
   159         self.FunctionCallStack = []
   156         
   160         
   157         self.ParentWindow = window
   161         self.ParentWindow = window
   158         self.Controler = controler
   162         self.Controler = controler
   159 
   163 
   160         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
   164         self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|
   284     def SetKeywords(self, keywords):
   288     def SetKeywords(self, keywords):
   285         self.Keywords = [keyword.upper() for keyword in keywords]
   289         self.Keywords = [keyword.upper() for keyword in keywords]
   286         self.Colourise(0, -1)
   290         self.Colourise(0, -1)
   287     
   291     
   288     def RefreshJumpList(self):
   292     def RefreshJumpList(self):
   289         self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
   293         if self.TextSyntax != "IL":
   290         self.Colourise(0, -1)
   294             self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
       
   295             self.Colourise(0, -1)
   291     
   296     
   292     # Buffer the last model state
   297     # Buffer the last model state
   293     def RefreshBuffer(self):
   298     def RefreshBuffer(self):
   294         self.Controler.BufferProject()
   299         self.Controler.BufferProject()
   295         if self.ParentWindow:
   300         if self.ParentWindow:
   326         self.EmptyUndoBuffer()
   331         self.EmptyUndoBuffer()
   327         self.DisableEvents = False
   332         self.DisableEvents = False
   328         
   333         
   329         self.RefreshVariableTree()
   334         self.RefreshVariableTree()
   330         
   335         
   331         self.Functions = []
   336         self.TypeNames = [typename.upper() for typename in self.Controler.GetDataTypes(self.TagName, True, self.Debug)]
       
   337         self.EnumeratedValues = [value.upper() for value in self.Controler.GetEnumeratedDataValues()]
       
   338         
       
   339         self.Functions = {}
   332         for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
   340         for category in self.Controler.GetBlockTypes(self.TagName, self.Debug):
   333             for blocktype in category["list"]:
   341             for blocktype in category["list"]:
   334                 if blocktype["type"] == "function" and blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables.keys():
   342                 if blocktype["type"] == "function" and blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables.keys():
   335                     self.Functions.append(blocktype["name"].upper())
   343                     if self.Functions.has_key(blocktype["name"]):
   336         
   344                         for name, type, modifier in blocktype["inputs"]:
   337         self.EnumeratedValues = []
   345                             if name not in self.Functions[blocktype["name"]]["inputs"]:
   338         for value in self.Controler.GetEnumeratedDataValues():
   346                                 self.Functions[blocktype["name"]]["inputs"].append(name)
   339             self.EnumeratedValues.append(value.upper())
   347                         for name, type, modifier in blocktype["outputs"]:
       
   348                             if name not in self.Functions[blocktype["name"]]["outputs"]:
       
   349                                 self.Functions[blocktype["name"]]["outputs"].append(name)
       
   350                         self.Functions[blocktype["name"]]["extensible"] |= blocktype["extensible"]
       
   351                     else:
       
   352                         self.Functions[blocktype["name"]] = {"inputs": [name for name, type, modifier in blocktype["inputs"]],
       
   353                                                              "outputs": [name for name, type, modifier in blocktype["outputs"]],
       
   354                                                              "extensible": blocktype["extensible"]}
   340         
   355         
   341         self.Colourise(0, -1)
   356         self.Colourise(0, -1)
   342     
   357     
   343     def RefreshVariableTree(self):
   358     def RefreshVariableTree(self):
   344         words = self.TagName.split("::")
   359         words = self.TagName.split("::")
   362             sub_tree = var_tree.get(name_list[0].upper(), None)
   377             sub_tree = var_tree.get(name_list[0].upper(), None)
   363             if sub_tree is not None:
   378             if sub_tree is not None:
   364                 return self.IsValidVariable(name_list[1:], sub_tree)
   379                 return self.IsValidVariable(name_list[1:], sub_tree)
   365         return False
   380         return False
   366     
   381     
       
   382     def IsFunctionParameter(self, param_name, func_name):
       
   383         if func_name is not None:
       
   384             func_decl = self.Functions.get(func_name, None)
       
   385             if func_decl is not None:
       
   386                 return (param_name.upper() in func_decl["inputs"] or 
       
   387                         param_name.upper() in func_decl["outputs"] or
       
   388                         func_decl["extensible"] and EXTENSIBLE_PARAMETER.match(param_name.upper()) is not None)
       
   389         return False
       
   390         
   367     def OnStyleNeeded(self, event):
   391     def OnStyleNeeded(self, event):
   368         self.TextChanged = True
   392         self.TextChanged = True
   369         line = self.LineFromPosition(self.GetEndStyled())
   393         line = self.LineFromPosition(self.GetEndStyled())
   370         if line == 0:
   394         if line == 0:
   371             start_pos = last_styled_pos = 0
   395             start_pos = last_styled_pos = 0
   373             start_pos = last_styled_pos = self.GetLineEndPosition(line - 1) + 1
   397             start_pos = last_styled_pos = self.GetLineEndPosition(line - 1) + 1
   374         end_pos = event.GetPosition()
   398         end_pos = event.GetPosition()
   375         self.StartStyling(start_pos, 0xff)
   399         self.StartStyling(start_pos, 0xff)
   376         
   400         
   377         struct_elements = []
   401         struct_elements = []
       
   402         current_function = None
   378         
   403         
   379         current_pos = last_styled_pos
   404         current_pos = last_styled_pos
   380         state = SPACE
   405         state = SPACE
   381         line = ""
   406         line = ""
   382         word = ""
   407         word = ""
   383         while current_pos < end_pos:
   408         while current_pos < end_pos:
   384             char = chr(self.GetCharAt(current_pos)).upper()
   409             char = chr(self.GetCharAt(current_pos)).upper()
   385             line += char
   410             line += char
   386             if char == NEWLINE:
   411             if char == NEWLINE:
       
   412                 self.StructElementsStack = []
   387                 if state == COMMENT:
   413                 if state == COMMENT:
   388                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT)
   414                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT)
   389                 elif state == NUMBER:
   415                 elif state == NUMBER:
   390                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   416                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   391                 elif state == WORD:
   417                 elif state == WORD:
   392                     if word in self.Keywords:
   418                     if word in self.Keywords or word in self.TypeNames:
   393                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   419                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   394                     elif self.IsValidVariable(struct_elements + [word], self.Variables):
   420                     elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
   395                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   421                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   396                     elif word in self.Functions:
   422                     elif word in self.Functions:
   397                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   423                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   398                     elif word in self.Jumps:
   424                     elif self.TextSyntax == "IL" and word in self.Jumps:
   399                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   425                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   400                     elif word in self.EnumeratedValues:
   426                     elif word in self.EnumeratedValues:
   401                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   427                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   402                     else:
   428                     else:
   403                         self.SetStyling(current_pos - last_styled_pos, 31)
   429                         self.SetStyling(current_pos - last_styled_pos, 31)
   420             elif state == COMMENT:
   446             elif state == COMMENT:
   421                 if line.endswith("*)"):
   447                 if line.endswith("*)"):
   422                     self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   448                     self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   423                     last_styled_pos = current_pos + 1
   449                     last_styled_pos = current_pos + 1
   424                     state = SPACE
   450                     state = SPACE
       
   451             elif (line.endswith("'") or line.endswith('"')) and state not in [COMMENT, STRING, WSTRING]:
       
   452                 self.SetStyling(current_pos - last_styled_pos, 31)
       
   453                 last_styled_pos = current_pos
       
   454                 if state == WORD:
       
   455                     struct_elements = []
       
   456                 if line.endswith("'"):
       
   457                     state = STRING
       
   458                 else:
       
   459                     state = WSTRING
       
   460             elif state == STRING:
       
   461                 if line.endswith("'") and not line.endswith("$'"):
       
   462                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
       
   463                     last_styled_pos = current_pos + 1
       
   464                     state = SPACE
       
   465             elif state == WSTRING:
       
   466                 if line.endswith('"') and not line.endswith('$"'):
       
   467                     self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_STRING)
       
   468                     last_styled_pos = current_pos + 1
       
   469                     state = SPACE
   425             elif char in LETTERS:
   470             elif char in LETTERS:
   426                 if state == NUMBER:
   471                 if state == NUMBER:
   427                     word = "#"
   472                     word = "#"
   428                     state = WORD
   473                     state = WORD
   429                 elif state == SPACE:
   474                 elif state == SPACE:
   438                     self.SetStyling(current_pos - last_styled_pos, 31)
   483                     self.SetStyling(current_pos - last_styled_pos, 31)
   439                     last_styled_pos = current_pos
   484                     last_styled_pos = current_pos
   440                     state = NUMBER
   485                     state = NUMBER
   441                 if state == WORD and char != '.':
   486                 if state == WORD and char != '.':
   442                     word += char
   487                     word += char
       
   488             elif char == '(' and state == SPACE:
       
   489                 self.FunctionCallStack.append(current_function)
       
   490                 current_function = None
   443             else:
   491             else:
   444                 if state == WORD:
   492                 if state == WORD:
   445                     if word in self.Keywords:
   493                     if word in self.Keywords or word in self.TypeNames:
   446                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   494                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   447                     elif self.IsValidVariable(struct_elements + [word], self.Variables):
   495                     elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
   448                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   496                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   449                     elif word in self.Functions:
   497                     elif word in self.Functions:
   450                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   498                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)    
   451                     elif word in self.Jumps:
   499                     elif self.TextSyntax == "IL" and word in self.Jumps:
   452                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   500                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   453                     elif word in self.EnumeratedValues:
   501                     elif word in self.EnumeratedValues:
   454                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   502                         self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   455                     else:
   503                     else:
   456                         self.SetStyling(current_pos - last_styled_pos, 31)
   504                         self.SetStyling(current_pos - last_styled_pos, 31)
   459                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   507                             self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK)
   460                             self.StartStyling(current_pos, 0xff)
   508                             self.StartStyling(current_pos, 0xff)
   461                     if char == '.':
   509                     if char == '.':
   462                         if word != "]":
   510                         if word != "]":
   463                             struct_elements.append(word)
   511                             struct_elements.append(word)
       
   512                     elif char == '(':
       
   513                         self.FunctionCallStack.append(current_function)
       
   514                         if word in self.Functions:
       
   515                             current_function = word
       
   516                             struct_elements = []
       
   517                         else:    
       
   518                             if self.IsValidVariable(struct_elements + [word], self.Variables):
       
   519                                 struct_elements.append(word)
       
   520                             current_function = None
   464                     else:
   521                     else:
   465                         if char == '[':
   522                         if char == '[':
   466                             self.StructElementsStack.append(struct_elements + [word])
   523                             self.StructElementsStack.append(struct_elements + [word])
   467                         struct_elements = []
   524                         struct_elements = []
       
   525                     
   468                     word = ""
   526                     word = ""
   469                     last_styled_pos = current_pos
   527                     last_styled_pos = current_pos
   470                     state = SPACE
   528                     state = SPACE
   471                 elif state == NUMBER:
   529                 elif state == NUMBER:
   472                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   530                     self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   473                     last_styled_pos = current_pos
   531                     last_styled_pos = current_pos
   474                     state = SPACE
   532                     state = SPACE
   475                 if char == ']':
   533                 if char == ']':
   476                     if len(self.StructElementsStack) > 0:
   534                     if len(self.StructElementsStack) > 0:
   477                         struct_elements = self.StructElementsStack.pop()
   535                         struct_elements = self.StructElementsStack.pop()
       
   536                     else:
       
   537                         struct_elements = []
   478                     word = char
   538                     word = char
   479                     state = WORD
   539                     state = WORD
       
   540                 elif char == ')':
       
   541                     struct_elements = []
       
   542                     if len(self.FunctionCallStack) > 0:
       
   543                         current_function = self.FunctionCallStack.pop()
       
   544                     else:
       
   545                         current_function = None
   480             current_pos += 1
   546             current_pos += 1
   481         if state == COMMENT:
   547         if state == COMMENT:
   482             self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   548             self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT)
   483         elif state == NUMBER:
   549         elif state == NUMBER:
   484             self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   550             self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   485         elif state == WORD:
   551         elif state == WORD:
   486             if word in self.Keywords:
   552             if word in self.Keywords or word in self.TypeNames:
   487                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   553                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD)
   488             elif self.IsValidVariable(struct_elements + [word], self.Variables):
   554             elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function):
   489                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   555                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE)
   490             elif word in self.Functions:
   556             elif self.TextSyntax == "IL" and word in self.Functions:
   491                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   557                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION)
   492             elif word in self.Jumps:
   558             elif word in self.Jumps:
   493                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   559                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_JUMP)
   494             elif word in self.EnumeratedValues:
   560             elif word in self.EnumeratedValues:
   495                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)
   561                 self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER)