def StyleText(self, event): """Handle the EVT_STC_STYLENEEDED event""" stc = event.GetEventObject() # Last correctly styled character last_styled_pos = stc.GetEndStyled() # Get styling range for this call line = stc.LineFromPosition(last_styled_pos) start_pos = stc.PositionFromLine(line) end_pos = event.GetPosition() # Walk the line and find all the symbols to style # Note: little inefficient doing one char at a time # but just to illustrate the process. while start_pos < end_pos: stc.StartStyling(start_pos, 0x1f) char = stc.GetCharAt(start_pos) if char in self.ortho_symbols: # Set Symbol Keyword style style = OrthoEventsLexer.STC_STYLE_ORTHO_KW else: # Set Default style style = OrthoEventsLexer.STC_STYLE_ORTHO_DEFAULT # Set the styling byte information for 1 char from # current styling position (start_pos) with the # given style. stc.SetStyling(1, style) start_pos += 1
def StyleText(stc, start, end): """Style the text @param stc: Styled text control instance @param start: Start position @param end: end position """ # First, figure out the line based on the position. line = stc.LineFromPosition(start) # Find the start of the line that's been styled before this one. while line > 0 and stc.GetLineState(line) == 0: line -= 1 eline = stc.LineFromPosition(end) state = stc.GetLineState(line) - 1 if state < 0: state = 0 for ln in range(line, eline + 1): text = stc.GetLine(ln).encode('utf-8') len_text = len(text) text = text.strip() if len(text) == 0: state = 0 else: if len(text) > 0: ch = text[0] ix = issl_table.find(ch) if ix >= 0: state = ix + 1 stc.StartStyling(stc.PositionFromLine(ln), 0xFF) stc.SetStyling(len_text, state) stc.SetLineState(ln, state + 1)
def action(self, index=-1, multiplier=1): stc = self.mode start = stc.GetCurrentPos() end = 0 while True: pos = stc.FindText(start, end, "--- ", 0) if pos < 0: self.dprint("not found") break if stc.GetColumn(pos) == 0 and pos != start: line = stc.LineFromPosition(pos) stc.showLine(line) break start = pos - 1
def StyleText(self, evt): """Handle the EVT_STC_STYLENEEDED event.""" stc = evt.GetEventObject() last_styled_pos = stc.GetEndStyled() line = stc.LineFromPosition(last_styled_pos) start_pos = stc.PositionFromLine(line) end_pos = evt.GetPosition() while start_pos < end_pos: stc.StartStyling(start_pos, 0x1f) curchar = chr(stc.GetCharAt(start_pos)) if curchar in self.alpha: start = stc.WordStartPosition(start_pos, True) end = start + 1 while chr(stc.GetCharAt(end)) != " " and end < stc.GetLength(): end += 1 word = stc.GetTextRange(start, end) if word in self.keywords: style = self.STC_EXPR_KEYWORD stc.SetStyling(len(word), style) elif word in self.keywords2: style = self.STC_EXPR_KEYWORD2 stc.SetStyling(len(word), style) else: style = self.STC_EXPR_DEFAULT stc.SetStyling(len(word), style) start_pos += len(word) elif curchar == ";": eol = stc.GetLineEndPosition(stc.LineFromPosition(start_pos)) style = self.STC_EXPR_COMMENT stc.SetStyling(eol - start_pos, style) start_pos = eol else: style = self.STC_EXPR_DEFAULT stc.SetStyling(1, style) start_pos += 1
def isInsideStatement(self, stc, pos): """Find out if the position is inside a statement Being inside a statement means that the position is after an opening paren and the matching close paran either doesn't exist yet or is after the position. @return: True if pos is after an unbalanced amount of opening parens """ linenum = stc.LineFromPosition(pos) start = self.getFoldSectionStart(stc, linenum) self.dprint("fold start=%d, linenum=%d" % (start, linenum)) text = self.getCodeChars(stc, start, pos) parens = self.getBraceMatch(text) self.dprint("text=%s, parens=%d" % (text, parens)) return parens != 0
def electricChar(self, stc, uchar): i = ord(uchar) if i >= ord('0') and i <= ord('9'): pos = stc.GetCurrentPos() s = stc.GetStyleAt(pos) col = stc.GetColumn(pos) if not stc.isStyleComment(s) and col < 5: ln = stc.LineFromPosition(pos) fc = stc.PositionFromLine(ln) lc = stc.GetLineEndPosition(ln) text = stc.GetTextRange(fc, lc) #dprint("pos=%d col=%d ln=%d fc=%d lc=%d len=%d" % (pos, col, ln, fc, lc, len(text))) #dprint("1234567") #dprint(text) if len(text) > 5: numbers = text[0:5] continuation = text[5] remainder = text[6:] else: numbers = text + " "*(5 - len(text)) continuation = " " remainder = "" numbers = numbers[0:col] + uchar + numbers[col:] before = len(numbers) numbers = numbers.lstrip() if before > len(numbers): col -= before - len(numbers) numbers = numbers.strip() #dprint("pos=%d col=%d ln=%d fc=%d lc=%d len=%d" % (pos, col, ln, fc, lc, len(text))) line = "%-5s%s%s" % (numbers, continuation, remainder) #dprint("1234567") #dprint(line) stc.SetTargetStart(fc) stc.SetTargetEnd(lc) stc.ReplaceTarget(line) stc.GotoPos(fc + col + 1) return True return False
def on_EVT_STC_STYLENEEDED(self, event): stc = event.GetEventObject() # Last correctly styled character last_styled_pos = stc.GetEndStyled() # Get styling range for this call lino = stc.LineFromPosition(last_styled_pos) start_pos = stc.PositionFromLine(lino) end_pos = event.GetPosition() text = self.GetTextRange(start_pos, end_pos) kw_positions = [] #find any keywords to color them differently i = 0 for kw in self.keywords: try: l = len(kw) while True: j = text[i:].index(kw) kw_positions.append((start_pos + i + j, l, kw)) i += j + l except: i = 0 #find any comments in the pbs commands #we start looking for '#" at position 5 as text should begin with '#PBS ' anyway i = 5 len_text = len(text) while i < len_text: if text[i] == '#' and not text[i - 1] == '\n': #found a '#' in the middle of a line (at position i), find the end of the line. j = i + text[i:].index('\n') + 1 kw_positions.append((start_pos + i, j - i, text[i:j])) i = j else: i += 1 kw_positions.sort(key=lambda tpl: tpl[0] + float(tpl[1]) * 0.01) #pprint.pprint( kw_positions ) if not kw_positions: self.StartStyling(start_pos, 31) self.SetStyling(end_pos - start_pos, PbsLexer.STC_PBS_DEFAULT) return i = kw_positions[0][0] if i != start_pos: self.StartStyling(start_pos, 31) self.SetStyling(kw_positions[0][0] - start_pos, PbsLexer.STC_PBS_DEFAULT) last = len(kw_positions) - 1 for t, tpl in enumerate(kw_positions): self.StartStyling(tpl[0], 31) if tpl[2].startswith('#'): style = PbsLexer.STC_PBS_COMMENT else: style = PbsLexer.STC_PBS_KEYWORD self.SetStyling(tpl[0], style) if t < last: i1 = tpl[0] + tpl[1] i0n = kw_positions[t + 1][0] else: i1 = tpl[0] + tpl[1] i0n = end_pos if i1 < i0n: self.StartStyling(i1, 31) self.SetStyling(i0n - i1, PbsLexer.STC_PBS_DEFAULT)
def AutoIndenter(stc, current_pos, indent_char): """ Determines the indentation rule. 0) If the line is empty except for whitespace, indent to the current column. 1) If all strings and parenthesis are closed, then indent based on how this line has been styled. 2) If we're in a string, indent to one more than the position at which the string started. 3) If we've opened more parenthesis then we closed on the current line, indent by 1. 4) If we've closed more parenthesis than we opened on the current line, dedent by 1. 5) Otherwise, keep the current indentation. """ line = stc.LineFromPosition(current_pos) while line >= 0: line_state = stc.GetLineState(line) if line_state: break line -= 1 start = stc.PositionFromLine(line) text = stc.GetTextRangeUTF8(start, current_pos) pos = -1 len_text = len(text) # States for the indenting state machine. ISTATE_INDENT = 0 # Line indentation. ISTATE_CODE = 1 # Normal code. ISTATE_COMMENT = 2 # Comment. ISTATE_COMMENT_LINE = 3 # Full-line comment. ISTATE_STRING = 4 # In a string. ISTATE_EOL = 5 # At the end of the line. state = ISTATE_EOL # The indentation of the last non-blank, non-comment line. prior_indent = 0 # The number of parens that are open in the statement. open_parens = 0 # The net change in parens on the current line. net_parens = 0 # Where the current line started. line_start = 0 # The quote characters used to close the current string. quote_chars = None # The indentation to use if we're in a quote. quote_indent = 0 while pos + 1 < len_text: pos += 1 c = text[pos] if state == ISTATE_EOL: line_start = pos net_parens = 0 state = ISTATE_INDENT if state == ISTATE_INDENT: if c == " ": continue elif c == "\n": state = ISTATE_EOL continue elif c == "#": state = ISTATE_COMMENT_LINE continue state = ISTATE_CODE prior_indent = pos - line_start # Intentionally fall through. if state == ISTATE_COMMENT or state == ISTATE_COMMENT_LINE: if c == "\n": state = ISTATE_EOL continue continue elif state == ISTATE_CODE: if c == "\n": state = ISTATE_EOL continue if c in "\"'`": start = text[pos:pos + 3] if start == "'''" or start == '"""': quote_chars = start quote_indent = pos - line_start pos += 2 state = ISTATE_STRING continue quote_chars = c quote_indent = 1 + pos - line_start state = ISTATE_STRING continue if c in "([{": net_parens += 1 open_parens += 1 continue if c in ")]}": net_parens -= 1 open_parens -= 1 continue if c == "#": state = ISTATE_COMMENT continue continue elif state == ISTATE_STRING: if c == "\n": line_start = pos + 1 continue if c == "\\": pos += 1 continue if c == quote_chars: state = ISTATE_CODE continue if text[pos:pos + 3] == quote_chars: pos += 2 state = ISTATE_CODE continue continue # Compute the indent of the line itself. INDENTWIDTH = profiler.Profile_Get("INDENTWIDTH") line_indent = line_state & INDENT_MASK if state == ISTATE_STRING: indent = quote_indent elif state == ISTATE_COMMENT_LINE: l = stc.GetCurrentLine() indent = stc.GetLineIndentation(l) elif open_parens <= 0: if state == ISTATE_INDENT or state == ISTATE_EOL: l = stc.GetCurrentLine() if stc.GetLineIndentPosition(l) == stc.GetLineEndPosition(l): indent = stc.GetColumn(current_pos) else: indent = line_indent elif line_state & INDENTS: indent = line_indent + INDENTWIDTH else: indent = line_indent elif net_parens > 0: indent = prior_indent + INDENTWIDTH elif net_parens < 0: indent = max(line_indent + INDENTWIDTH, prior_indent - INDENTWIDTH) else: indent = prior_indent # Implement the indent. eolch = stc.GetEOLChar() stc.AddText(eolch) l = stc.GetCurrentLine() stc.SetLineIndentation(l, indent) stc.GotoPos(stc.GetLineIndentPosition(l))
def StyleText(stc, start, end): """Style the text @param stc: Styled text control instance @param start: Start position @param end: end position """ max_styled_line = max_line_cache.get(id(stc), 0) # Set up the bad indentation indicator style. if stc.IndicatorGetStyle(1) != wx.stc.STC_INDIC_SQUIGGLE: stc.IndicatorSetStyle(1, wx.stc.STC_INDIC_SQUIGGLE) stc.IndicatorSetForeground(1, "#FF0000") # A change to one line can change others below it. So we restyle all # visible text with any change. (We restyle a bit more so we don't get # caught in things like triple-quoted strings.) try: vis_end_line = stc.GetLastVisibleLine() + 20 except: # Fails if we're in the preview. vis_end_line = stc.GetLineCount() vis_end_pos = stc.GetLineEndPosition(vis_end_line) end = max(end, vis_end_pos) # First, figure out the line based on the position. line = stc.LineFromPosition(start) # Jump back a bunch of lines, so that we always restyle the entire # screen. line = min(line - 60, max_styled_line) if line < 0: line = 0 # Find the start of the line that's been styled before this one. while line and stc.GetLineState(line) == 0: line -= 1 # The indentation starting the current block. (None to indicate # it hasn't been set yet.) block_indent = 0 # The type of block we're dealing with. block_type = BLOCK_RPY # Is this block's indentation optional? block_maybe_indents = False # A stack of outer blocks, giving the indent and type of those # blocks. block_stack = [] # Find the last line before line with a 0 indent. (Or the first # line if we don't have one line that.) base_line = line while base_line > 0: base_line -= 1 state = stc.GetLineState(base_line) if not state: continue indent = state & INDENT_MASK if indent == 0: break if base_line < 0: base_line = 0 # Figure out what sort of block we're in, and build up the stack # of non-closed blocks. for i in range(base_line, line): state = stc.GetLineState(i) if not state: continue indent = state & INDENT_MASK if block_indent is None: block_indent = indent if state & INDENTS: block_stack.append((block_indent, block_type)) block_indent = None block_type = state & BLOCK_MASK if state & MAYBE_INDENTS: block_maybe_indents = True else: block_maybe_indents = False while indent < block_indent: block_indent, block_type = block_stack.pop() # Clean out the old (no longer relevant) line states. for i in range(line, max_styled_line + 1): stc.SetLineState(i, 0) new_start = stc.PositionFromLine(line) text = stc.GetTextRangeUTF8(new_start, end) # End open strings. text += "\n\"\"\"'''" len_text = len(text) pos = 0 # stc.StartStyling(new_start, 0xff & (~wx.stc.STC_INDIC2_MASK)) sb = StyleBuffer(stc, new_start, 0xff & (~wx.stc.STC_INDIC2_MASK)) while pos < len_text: # The line and pos this statement begins on. statement_line = line m = line_start_re.match(text, pos) pos = m.end() indent = len(m.group('indent')) comment = m.group('comment') eol = m.group('eol') if eol: sb.style(indent, STC_RENPY_DEFAULT) # Style a line-long comment. if comment: sb.style(len(comment), STC_RENPY_COMMENT) # If the line is empty, continue. if eol: sb.style(len(eol), STC_RENPY_DEFAULT) line += 1 continue # Otherwise, we have a real line. Figure out the indentation of it. indent_indicator = 0 # If we're indented from the previous line and starting a new block, # deal with that. if block_indent is None and indent > block_stack[-1][0]: block_indent = indent # Deal with empty blocks. Not an error, because of label. if block_indent is None: if INDENT_ERRORS and not block_maybe_indents: indent_indicator = wx.stc.STC_INDIC1_MASK block_indent, block_type = block_stack.pop() # We outdented, go out a block or more. while block_indent > indent: block_indent, block_type = block_stack.pop() # Now check that we match the current block. if INDENT_ERRORS and indent != block_indent: # Indentation error. indent_indicator = wx.stc.STC_INDIC1_MASK # Style the indentation. sb.style(indent, STC_RENPY_DEFAULT | indent_indicator) # Store the line type. line_type = block_type >> 4 line_text = "" paren_depth = 0 while True: m = regex.match(text, pos) if not m: break pos = m.end() if pos > len_text: pos = len_text # Rules for applying styling. string = m.group("string") if string: line_text += string line += string.count("\n") i = 0 while string[i] in 'ur': i += 1 sb.style(i + 1, STC_RENPY_DEFAULT) sb.style(len(string) - 2 - i, STC_RENPY_STRING) sb.style(1, STC_RENPY_DEFAULT) continue word = m.group("word") if word: line_text += word style = STC_RENPY_DEFAULT if line_type == LINE_RPY: if word in RENPY_KEYWORDS: style = STC_RENPY_KEYWORD elif word in RENPY_PROPERTIES: style = STC_RENPY_KEYWORD2 elif line_type == LINE_PY: if word in PYTHON_KEYWORDS: style = STC_RENPY_KEYWORD sb.style(len(word), style) continue comment = m.group("comment") if comment: # Don't include comment text in line_text. sb.style(len(comment), STC_RENPY_COMMENT) continue # Style everything else. line_text += m.group(0) sb.style(len(m.group(0)), STC_RENPY_DEFAULT) # Rules for everything else. if m.group("open_paren"): paren_depth += 1 elif m.group("close_paren"): paren_depth -= 1 elif m.group("eol"): line += 1 if not paren_depth: break # End a runaway line, eventually. if len(line_text) > 8000: break line_text = line_text.strip() block_maybe_indents = False if line_text and line_text[-1] == ':': block_stack.append((block_indent, block_type)) block_indent = None indents = INDENTS if line_text.startswith("label"): indents |= MAYBE_INDENTS block_maybe_indents = True if line_type == LINE_RPY: block_type = BLOCK_RPY if renpy_python.match(line_text): block_type = BLOCK_PY else: block_type = BLOCK_PY else: indents = 0 new_state = indent | line_type | block_type | indents stc.SetLineState(statement_line, new_state) sb.apply() max_line_cache[id(stc)] = line
def adjustStart(self, stc, start): col = stc.GetColumn(start) if col != 0: start = stc.PositionFromLine(stc.LineFromPosition(start)) return start