def coupleBalance(self, stc, ln, open, close): """Search the line to see if there are unmatched braces Search the line for unmatched braces given the open and close matching pair. This takes into account the style of the document to make sure that the brace isn't in a comment or string. @param stc: the StyledTextCtrl instance @param ln: line number @param open: the opening brace character, e.g. "(" @param close: the complimentary closing brace character, e.g. ")" @return: brace mismatch count: 0 for matching braces, positive for a surplus of opening braces, and negative for a surplus of closing braces """ if ln < 0: return 0 r = 0 fc = stc.GetLineIndentPosition(ln) lc = stc.GetLineEndPosition(ln) line = stc.GetStyledText(fc, lc) self.dprint(repr(line)) i = len(line) while i > 0: i -= 1 s = line[i] i -= 1 c = line[i] if c == open and not (stc.isStyleComment(s) and stc.isStyleString(s)): self.dprint("found %s at column %d" % (open, i/2)) r += 1 elif c == close and not (stc.isStyleComment(s) and stc.isStyleString(s)): self.dprint("found %s at column %d" % (close, i/2)) r -= 1 return r
def electricChar(self, stc, uchar): """Reindent the line and insert a newline when special chars are typed. For python mode, a colon should reindent the line (for example, after an else statement, it should dedent it one level) """ if uchar == u':': pos = stc.GetCurrentPos() s = stc.GetStyleAt(pos) if stc.isStyleComment(s) or stc.isStyleString(s): # These will report true if the cursor is before the first # character of a comment or string, meaning that: # # else#blah # # where the cursor is between the 'e' and the '#' will fail. # So, we have to check for this as a special case and allow it if pos > 0: s = stc.GetStyleAt(pos-1) allow = not stc.isStyleComment(s) and not stc.isStyleString(s) else: allow = False else: allow = True if allow: stc.BeginUndoAction() start, end = stc.GetSelection() if start == end: stc.AddText(uchar) else: stc.ReplaceSelection(uchar) self.reindentLine(stc, dedent_only=True) stc.EndUndoAction() return True return False
def electricBackspace(self, stc): """Delete all whitespace before the cursor unless in a string or comment """ start, end = stc.GetSelection() if start != end: stc.ReplaceSelection("") return pos = stc.GetCurrentPos() if pos <= 0: return s = stc.GetStyleAt(pos - 1) if stc.isStyleComment(s) or stc.isStyleString(s): stc.CmdKeyExecute(wx.stc.STC_CMD_DELETEBACK) else: self.dprint("backspace from pos %d" % pos) start = pos while start > 0: c = stc.GetCharAt(start - 1) if c == ord(' ') or c == ord('\t') or c == 10 or c == 13: start -= 1 else: break if start < pos: stc.SetTargetStart(start) stc.SetTargetEnd(pos) stc.ReplaceTarget('') else: stc.CmdKeyExecute(wx.stc.STC_CMD_DELETEBACK)
def electricDelete(self, stc): """Delete all whitespace after the cursor unless in a string or comment """ start, end = stc.GetSelection() if start != end: stc.ReplaceSelection("") return pos = stc.GetCurrentPos() s = stc.GetStyleAt(pos) if stc.isStyleComment(s) or stc.isStyleString(s): stc.CmdKeyExecute(wx.stc.STC_CMD_CLEAR) else: self.dprint("deleting from pos %d" % pos) end = pos while end < stc.GetLength(): c = stc.GetCharAt(end) if c == ord(' ') or c == ord('\t') or c == 10 or c == 13: end += 1 else: break if end > pos: stc.SetTargetStart(pos) stc.SetTargetEnd(end) stc.ReplaceTarget('') else: stc.CmdKeyExecute(wx.stc.STC_CMD_CLEAR)
def electricChar(self, stc, uchar): """Reindent the line and insert a newline when special chars are typed. Like emacs, a semicolon or curly brace causes the line to be reindented and the next line to be indented to the correct column. @param stc: stc instance @param uchar: unicode character that was just typed by the user (note that it hasn't been inserted into the document yet.) @return: True if this method handled the character and the text was modified; False if the calling event handler should handle the character. """ implicit_return = True if uchar == u';' or uchar == u':' or uchar == '{' or uchar == '}': pos = stc.GetCurrentPos() s = stc.GetStyleAt(pos) if not stc.isStyleComment(s) and not stc.isStyleString(s): if uchar == u':': # FIXME: currently only process the : if the current # line is a case statement. Emacs also indents labels # and namespace operators with a :: by checking if the # last character on the previous line is a : and if so # collapses the current line with the previous line and # reindents the new line linenum = stc.GetCurrentLine() line = self.getCodeChars(stc, linenum, pos) + ":" if not self.reCase.match(line) and not self.reClassAttrScope.match(line): c, prev = self.getLastNonWhitespaceChar(stc, pos) if c == u':': # Found previous ':', so make it a double colon stc.SetSelection(prev + 1, pos) #dprint("selection: %d - %d" % (prev + 1, pos)) implicit_return = False elif uchar == u';': # Don't process the semicolon if we're in the middle of an # open statement if self.isInsideStatement(stc, pos): return False stc.BeginUndoAction() start, end = stc.GetSelection() if start == end: stc.AddText(uchar) else: stc.ReplaceSelection(uchar) # Always reindent the line, but only process a return if needed self.processTab(stc) if implicit_return: self.processReturn(stc) stc.EndUndoAction() return True return False
def electricChar(self, stc, uchar): """Reindent the line and insert a newline when special chars are typed. For python mode, a colon should reindent the line (for example, after an else statement, it should dedent it one level) """ if uchar == u':': pos = stc.GetCurrentPos() s = stc.GetStyleAt(pos) if stc.isStyleComment(s) or stc.isStyleString(s): # These will report true if the cursor is before the first # character of a comment or string, meaning that: # # else#blah # # where the cursor is between the 'e' and the '#' will fail. # So, we have to check for this as a special case and allow it if pos > 0: s = stc.GetStyleAt(pos - 1) allow = not stc.isStyleComment( s) and not stc.isStyleString(s) else: allow = False else: allow = True if allow: stc.BeginUndoAction() start, end = stc.GetSelection() if start == end: stc.AddText(uchar) else: stc.ReplaceSelection(uchar) self.reindentLine(stc, dedent_only=True) stc.EndUndoAction() return True return False