Created
April 10, 2012 17:12
-
-
Save danielSanchezQ/2352928 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Python (QSyntaxHighlighter): | |
"""Syntax highlighter for the Python language. | |
""" | |
# Python keywords | |
keywords = [ | |
'and', 'as', 'assert', 'break', 'class', | |
'continue', 'def', 'del', 'elif', 'else', | |
'except', 'exec', 'finally', 'for', 'from', | |
'global', 'if', 'import', 'in', 'is', | |
'lambda', 'not', 'or', 'pass', 'print', 'raise', | |
'return', 'try', 'while', 'with', 'yield', 'True', | |
'False', 'None' ] | |
# Python operators | |
operators = [ | |
'=', | |
# Comparison | |
'==', '!=', '<', '<=', '>', '>=', | |
# Arithmetic | |
'\+', '-', '\*', '/', '//', '\%', '\*\*', | |
# In-place | |
'\+=', '-=', '\*=', '/=', '\%=', | |
# Bitwise | |
'\^', '\|', '\&', '\~', '>>', '<<' ] | |
# Python braces | |
braces = [ | |
'\{', '\}', '\(', '\)', '\[', '\]' ] | |
def __init__(self, document): | |
QSyntaxHighlighter.__init__(self, document) | |
# Multi-line strings (expression, flag, style) | |
# FIXME: The triple-quotes in these two lines will mess up the | |
# syntax highlighting from this point onward | |
self.tri_single = (QRegExp("'''"), 1, STYLES['string2']) | |
self.tri_double = (QRegExp('"""'), 2, STYLES['string2']) | |
rules = [] | |
rules += [(r'\b%s\b' % w, 0, STYLES['keyword']) | |
for w in Python.keywords] | |
rules += [(r'%s' % o, 0, STYLES['operator']) | |
for o in Python.operators] | |
rules += [(r'%s' % b, 0, STYLES['brace']) | |
for b in Python.braces] | |
rules += [ | |
# Double-quoted string, possibly containing escape sequences | |
(r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']), | |
# Single-quoted string, possibly containing escape sequences | |
(r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES['string']), | |
# 'def' followed by an identifier | |
(r'\bdef\b\s*(\w+)', 1, STYLES['defclass']), | |
# 'class' followed by an identifier | |
(r'\bclass\b\s*(\w+)', 1, STYLES['defclass']), | |
# From '#' until a newline | |
(r'#[^\n]*', 0, STYLES['comment']), | |
# From #! to new line | |
(r'#![^\n]*', 0, STYLES['pybang']) ] | |
# Build a QRegExp for each pattern | |
self.rules = [(QRegExp(pat), index, fmt) | |
for (pat, index, fmt) in rules] | |
def highlightBlock(self, text): | |
"""Apply syntax highlighting to the given block of text. | |
""" | |
# Do other syntax formatting | |
for expression, nth, format in self.rules: | |
index = expression.indexIn(text, 0) | |
while index >= 0: | |
# We actually want the index of the nth match | |
index = expression.pos(nth) | |
length = expression.cap(nth).length() | |
self.setFormat(index, length, format) | |
index = expression.indexIn(text, index + length) | |
self.setCurrentBlockState(0) | |
# Do multi-line strings | |
in_multiline = self.match_multiline(text, *self.tri_single) | |
if not in_multiline: | |
in_multiline = self.match_multiline(text, *self.tri_double) | |
def match_multiline(self, text, delimiter, in_state, style): | |
"""Do highlighting of multi-line strings. ``delimiter`` should be a | |
``QRegExp`` for triple-single-quotes or triple-double-quotes, and | |
``in_state`` should be a unique integer to represent the corresponding | |
state changes when inside those strings. Returns True if we're still | |
inside a multi-line string when this function is finished. """ | |
# If inside triple-single quotes, start at 0 | |
if self.previousBlockState() == in_state: | |
start = 0 | |
add = 0 | |
# Otherwise, look for the delimiter on this line | |
else: | |
start = delimiter.indexIn(text) | |
# Move past this match | |
add = delimiter.matchedLength() | |
# As long as there's a delimiter match on this line... | |
while start >= 0: | |
# Look for the ending delimiter | |
end = delimiter.indexIn(text, start + add) | |
# Ending delimiter on this line? | |
if end >= add: | |
length = end - start + add + delimiter.matchedLength() | |
self.setCurrentBlockState(0) | |
# No; multi-line string | |
else: | |
self.setCurrentBlockState(in_state) | |
length = text.length() - start + add | |
# Apply formatting | |
self.setFormat(start, length, style) | |
# Look for the next match | |
start = delimiter.indexIn(text, start + length) | |
# Return True if still inside a multi-line string, False otherwise | |
if self.currentBlockState() == in_state: | |
return True | |
else: | |
return False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment