def StyleText(stc, start, end): """Style the text @param stc: Styled text control instance @param start: Start position @param end: end position """ cpos = 0 stc.StartStyling(cpos, 0x1f) lexer = get_lexer_by_name("html+django") doctxt = stc.GetTextRange(0, end) wineol = stc.GetEOLChar() == "\r\n" for token, txt in lexer.get_tokens(doctxt): # print token, txt style = TOKEN_MAP.get(token, STC_DJANGO_DEFAULT) if style == STC_DJANGO_PREPROCESSOR and txt.startswith(u'#'): style = STC_DJANGO_COMMENT # elif style == STC_DJANGO_STRING and txt[-1] not in '"\'': # style = STC_DJANGO_STRINGEOL tlen = len(txt) if wineol and "\n" in txt: tlen += txt.count("\n") if tlen: stc.SetStyling(tlen, style) cpos += tlen stc.StartStyling(cpos, 0x1f)
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))