# HG changeset patch # User laurent # Date 1308066002 -7200 # Node ID f28df922efbe75c7255c8fe35f12b497b6c03b4a # Parent 2f60f3d3c9ad13973c31d2c88ab35ad9a0c826e5 Improve syntax highlighting in TextViewer diff -r 2f60f3d3c9ad -r f28df922efbe TextViewer.py --- a/TextViewer.py Tue Jun 14 17:38:59 2011 +0200 +++ b/TextViewer.py Tue Jun 14 17:40:02 2011 +0200 @@ -41,7 +41,8 @@ LETTERS.append(chr(ord('A') + i)) [STC_PLC_WORD, STC_PLC_COMMENT, STC_PLC_NUMBER, STC_PLC_STRING, - STC_PLC_VARIABLE, STC_PLC_FUNCTION, STC_PLC_JUMP, STC_PLC_ERROR] = range(8) + STC_PLC_VARIABLE, STC_PLC_PARAMETER, STC_PLC_FUNCTION, STC_PLC_JUMP, + STC_PLC_ERROR] = range(9) [SPACE, WORD, NUMBER, STRING, WSTRING, COMMENT] = range(6) [ID_TEXTVIEWER, @@ -120,11 +121,12 @@ # Highlighting styles self.StyleSetSpec(STC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces) self.StyleSetSpec(STC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces) + self.StyleSetSpec(STC_PLC_PARAMETER, "fore:#7F007F,size:%(size)d" % faces) self.StyleSetSpec(STC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces) self.StyleSetSpec(STC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces) self.StyleSetSpec(STC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces) - self.StyleSetSpec(STC_PLC_STRING, "fore:#7F007F,size:%(size)d" % faces) - self.StyleSetSpec(STC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces) + self.StyleSetSpec(STC_PLC_STRING, "fore:#007F00,size:%(size)d" % faces) + self.StyleSetSpec(STC_PLC_JUMP, "fore:#FF7FFF,size:%(size)d" % faces) self.StyleSetSpec(STC_PLC_ERROR, "fore:#FF0000,back:#FFFF00,size:%(size)d" % faces) # Indicators styles @@ -155,8 +157,8 @@ self.Errors = [] self.Debug = debug self.InstancePath = instancepath - self.StructElementsStack = [] - self.FunctionCallStack = [] + self.ContextStack = [] + self.CallStack = [] self.ParentWindow = window self.Controler = controler @@ -339,27 +341,27 @@ self.Functions = {} for category in self.Controler.GetBlockTypes(self.TagName, self.Debug): for blocktype in category["list"]: - if blocktype["type"] == "function" and blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables.keys(): - if self.Functions.has_key(blocktype["name"]): - for name, type, modifier in blocktype["inputs"]: - if name not in self.Functions[blocktype["name"]]["inputs"]: - self.Functions[blocktype["name"]]["inputs"].append(name) - for name, type, modifier in blocktype["outputs"]: - if name not in self.Functions[blocktype["name"]]["outputs"]: - self.Functions[blocktype["name"]]["outputs"].append(name) - self.Functions[blocktype["name"]]["extensible"] |= blocktype["extensible"] - else: - self.Functions[blocktype["name"]] = {"inputs": [name for name, type, modifier in blocktype["inputs"]], - "outputs": [name for name, type, modifier in blocktype["outputs"]], - "extensible": blocktype["extensible"]} - + blockname = blocktype["name"].upper() + if blocktype["type"] == "function" and blockname not in self.Keywords and blockname not in self.Variables.keys(): + interface = dict([(name, {}) for name, type, modifier in blocktype["inputs"] + blocktype["outputs"] if name != '']) + if self.Functions.has_key(blockname): + self.Functions[blockname]["interface"].update(interface) + self.Functions[blockname]["extensible"] |= blocktype["extensible"] + else: + self.Functions[blockname] = {"interface": interface, + "extensible": blocktype["extensible"]} self.Colourise(0, -1) def RefreshVariableTree(self): words = self.TagName.split("::") self.Variables = self.GenerateVariableTree([(variable["Name"], variable["Type"], variable["Tree"]) for variable in self.Controler.GetEditedElementInterfaceVars(self.TagName, self.Debug)]) if self.Controler.GetEditedElementType(self.TagName, self.Debug)[1] == "function" or words[0] == "T" and self.TextSyntax == "IL": - self.Variables[words[-1].upper()] = {} + return_type = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, self.Debug) + if return_type is not None: + var_tree, var_dimension = self.Controler.GenerateVarTree(return_type, self.Debug) + self.Variables[words[-1].upper()] = self.GenerateVariableTree(var_tree) + else: + self.Variables[words[-1].upper()] = {} def GenerateVariableTree(self, list): tree = {} @@ -370,22 +372,13 @@ def RefreshScaling(self, refresh=True): pass - def IsValidVariable(self, name_list, var_tree): - if len(name_list) == 0: - return True - else: - sub_tree = var_tree.get(name_list[0].upper(), None) - if sub_tree is not None: - return self.IsValidVariable(name_list[1:], sub_tree) - return False - - def IsFunctionParameter(self, param_name, func_name): - if func_name is not None: - func_decl = self.Functions.get(func_name, None) - if func_decl is not None: - return (param_name.upper() in func_decl["inputs"] or - param_name.upper() in func_decl["outputs"] or - func_decl["extensible"] and EXTENSIBLE_PARAMETER.match(param_name.upper()) is not None) + def IsValidVariable(self, name, context): + return context is not None and context.get(name, None) is not None + + def IsCallParameter(self, name, call): + if call is not None: + return (call["interface"].get(name.upper(), None) is not None or + call["extensible"] and EXTENSIBLE_PARAMETER.match(name.upper()) is not None) return False def OnStyleNeeded(self, event): @@ -398,8 +391,8 @@ end_pos = event.GetPosition() self.StartStyling(start_pos, 0xff) - struct_elements = [] - current_function = None + current_context = self.Variables + current_call = None current_pos = last_styled_pos state = SPACE @@ -409,7 +402,8 @@ char = chr(self.GetCharAt(current_pos)).upper() line += char if char == NEWLINE: - self.StructElementsStack = [] + self.ContextStack = [] + current_context = self.Variables if state == COMMENT: self.SetStyling(current_pos - last_styled_pos + 1, STC_PLC_COMMENT) elif state == NUMBER: @@ -417,8 +411,10 @@ elif state == WORD: if word in self.Keywords or word in self.TypeNames: self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD) - elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function): + elif self.IsValidVariable(word, current_context): self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE) + elif self.IsCallParameter(word, current_call): + self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER) elif word in self.Functions: self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION) elif self.TextSyntax == "IL" and word in self.Jumps: @@ -427,11 +423,10 @@ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER) else: self.SetStyling(current_pos - last_styled_pos, 31) - if word != "]" and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos): + if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos): self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK) self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK) self.StartStyling(current_pos, 0xff) - struct_elements = [] else: self.SetStyling(current_pos - last_styled_pos, 31) last_styled_pos = current_pos @@ -441,7 +436,7 @@ self.SetStyling(current_pos - last_styled_pos - 1, 31) last_styled_pos = current_pos if state == WORD: - struct_elements = [] + current_context = self.Variables state = COMMENT elif state == COMMENT: if line.endswith("*)"): @@ -452,7 +447,7 @@ self.SetStyling(current_pos - last_styled_pos, 31) last_styled_pos = current_pos if state == WORD: - struct_elements = [] + current_context = self.Variables if line.endswith("'"): state = STRING else: @@ -486,14 +481,16 @@ if state == WORD and char != '.': word += char elif char == '(' and state == SPACE: - self.FunctionCallStack.append(current_function) - current_function = None + self.CallStack.append(current_call) + current_call = None else: if state == WORD: if word in self.Keywords or word in self.TypeNames: self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD) - elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function): + elif self.IsValidVariable(word, current_context): self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE) + elif self.IsCallParameter(word, current_call): + self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER) elif word in self.Functions: self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION) elif self.TextSyntax == "IL" and word in self.Jumps: @@ -502,26 +499,27 @@ self.SetStyling(current_pos - last_styled_pos, STC_PLC_NUMBER) else: self.SetStyling(current_pos - last_styled_pos, 31) - if word != "]" and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos): + if word not in ["]", ")"] and (self.GetCurrentPos() < last_styled_pos or self.GetCurrentPos() > current_pos): self.StartStyling(last_styled_pos, wx.stc.STC_INDICS_MASK) self.SetStyling(current_pos - last_styled_pos, wx.stc.STC_INDIC0_MASK) self.StartStyling(current_pos, 0xff) if char == '.': if word != "]": - struct_elements.append(word) + if current_context is not None: + current_context = current_context.get(word, None) + else: + current_context = None elif char == '(': - self.FunctionCallStack.append(current_function) - if word in self.Functions: - current_function = word - struct_elements = [] - else: - if self.IsValidVariable(struct_elements + [word], self.Variables): - struct_elements.append(word) - current_function = None + self.CallStack.append(current_call) + current_call = self.Functions.get(word, None) + if current_call is None and self.IsValidVariable(word, current_context): + current_call = {"interface": current_context.get(word, {}), + "extensible": False} + current_context = self.Variables else: if char == '[': - self.StructElementsStack.append(struct_elements + [word]) - struct_elements = [] + self.ContextStack.append(current_context.get(word, None)) + current_context = self.Variables word = "" last_styled_pos = current_pos @@ -531,18 +529,20 @@ last_styled_pos = current_pos state = SPACE if char == ']': - if len(self.StructElementsStack) > 0: - struct_elements = self.StructElementsStack.pop() - else: - struct_elements = [] + if len(self.ContextStack) > 0: + current_context = self.ContextStack.pop() + else: + current_context = self.Variables word = char state = WORD elif char == ')': - struct_elements = [] - if len(self.FunctionCallStack) > 0: - current_function = self.FunctionCallStack.pop() - else: - current_function = None + current_context = self.Variables + if len(self.CallStack) > 0: + current_call = self.CallStack.pop() + else: + current_call = None + word = char + state = WORD current_pos += 1 if state == COMMENT: self.SetStyling(current_pos - last_styled_pos + 2, STC_PLC_COMMENT) @@ -551,8 +551,10 @@ elif state == WORD: if word in self.Keywords or word in self.TypeNames: self.SetStyling(current_pos - last_styled_pos, STC_PLC_WORD) - elif self.IsValidVariable(struct_elements + [word], self.Variables) or self.IsFunctionParameter(word, current_function): + elif self.IsValidVariable(word, current_context): self.SetStyling(current_pos - last_styled_pos, STC_PLC_VARIABLE) + elif self.IsCallParameter(word, current_call): + self.SetStyling(current_pos - last_styled_pos, STC_PLC_PARAMETER) elif self.TextSyntax == "IL" and word in self.Functions: self.SetStyling(current_pos - last_styled_pos, STC_PLC_FUNCTION) elif word in self.Jumps: