pilas.ejemplos.syntax

Package pilas :: Package ejemplos :: Module syntax |
[hide private]
[frames] | no frames]

# Source Code for Module pilas.ejemplos.syntax

      1  # Ejemplo tomado desde la siguiente web:
      2  #     http://diotavelli.net/PyQtWiki/Python%20syntax%20highlighting
      3  import sys
      4
      5  from PyQt4.QtCore import QRegExp
      6  from PyQt4.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter
      7
      8 -def format(color, style=''):
      9      """Return a QTextCharFormat with the given attributes.
     10      """
     11      _color = QColor()
     12      _color.setNamedColor(color)
     13
     14      _format = QTextCharFormat()
     15      _format.setForeground(_color)
     16      if 'bold' in style:
     17          _format.setFontWeight(QFont.Bold)
     18      if 'italic' in style:
     19          _format.setFontItalic(True)
     20
     21      return _format
     22
     23
     24  # Syntax styles that can be shared by all languages
     25  STYLES = {
     26      'keyword': format('blue'),
     27      'operator': format('red'),
     28      'brace': format('darkGray'),
     29      'defclass': format('black', 'bold'),
     30      'string': format('magenta'),
     31      'string2': format('darkMagenta'),
     32      'comment': format('darkGreen', 'italic'),
     33      'self': format('black', 'italic'),
     34      'numbers': format('brown'),
     35  }
     36
     37
     38 -class PythonHighlighter (QSyntaxHighlighter):
     39      """Syntax highlighter for the Python language.
     40      """
     41      # Python keywords
     42      keywords = [
     43          'and', 'assert', 'break', 'class', 'continue', 'def',
     44          'del', 'elif', 'else', 'except', 'exec', 'finally',
     45          'for', 'from', 'global', 'if', 'import', 'in',
     46          'is', 'lambda', 'not', 'or', 'pass', 'print',
     47          'raise', 'return', 'try', 'while', 'yield',
     48          'None', 'True', 'False',
     49      ]
     50
     51      # Python operators
     52      operators = [
     53          '=',
     54          # Comparison
     55          '==', '!=', '<', '<=', '>', '>=',
     56          # Arithmetic
     57          '\+', '-', '\*', '/', '//', '\%', '\*\*',
     58          # In-place
     59          '\+=', '-=', '\*=', '/=', '\%=',
     60          # Bitwise
     61          '\^', '\|', '\&', '\~', '>>', '<<',
     62      ]
     63
     64      # Python braces
     65      braces = [
     66          '\{', '\}', '\(', '\)', '\[', '\]',
     67      ]
     68 -    def __init__(self, document):
     69          QSyntaxHighlighter.__init__(self, document)
     70
     71          # Multi-line strings (expression, flag, style)
     72          # FIXME: The triple-quotes in these two lines will mess up the
     73          # syntax highlighting from this point onward
     74          self.tri_single = (QRegExp("'''"), 1, STYLES['string2'])
     75          self.tri_double = (QRegExp('"""'), 2, STYLES['string2'])
     76
     77          rules = []
     78
     79          # Keyword, operator, and brace rules
     80          rules += [(r'\b%s\b' % w, 0, STYLES['keyword'])
     81              for w in PythonHighlighter.keywords]
     82          rules += [(r'%s' % o, 0, STYLES['operator'])
     83              for o in PythonHighlighter.operators]
     84          rules += [(r'%s' % b, 0, STYLES['brace'])
     85              for b in PythonHighlighter.braces]
     86
     87          # All other rules
     88          rules += [
     89              # 'self'
     90              (r'\bself\b', 0, STYLES['self']),
     91
     92              # Double-quoted string, possibly containing escape sequences
     93              (r'"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
     94              # Single-quoted string, possibly containing escape sequences
     95              (r"'[^'\\]*(\\.[^'\\]*)*'", 0, STYLES['string']),
     96
     97              # 'def' followed by an identifier
     98              (r'\bdef\b\s*(\w+)', 1, STYLES['defclass']),
     99              # 'class' followed by an identifier
    100              (r'\bclass\b\s*(\w+)', 1, STYLES['defclass']),
    101
    102              # From '#' until a newline
    103              (r'#[^\n]*', 0, STYLES['comment']),
    104
    105              # Numeric literals
    106              (r'\b[+-]?[0-9]+[lL]?\b', 0, STYLES['numbers']),
    107              (r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
    108              (r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, STYLES['numbers']),
    109          ]
    110
    111          # Build a QRegExp for each pattern
    112          self.rules = [(QRegExp(pat), index, fmt)
    113              for (pat, index, fmt) in rules]
    114
    115
    116 -    def highlightBlock(self, text):
    117          """Apply syntax highlighting to the given block of text.
    118          """
    119          # Do other syntax formatting
    120          for expression, nth, format in self.rules:
    121              index = expression.indexIn(text, 0)
    122
    123              while index >= 0:
    124                  # We actually want the index of the nth match
    125                  index = expression.pos(nth)
    126                  length = expression.cap(nth).length()
    127                  self.setFormat(index, length, format)
    128                  index = expression.indexIn(text, index + length)
    129
    130          self.setCurrentBlockState(0)
    131
    132          # Do multi-line strings
    133          in_multiline = self.match_multiline(text, *self.tri_single)
    134          if not in_multiline:
    135              in_multiline = self.match_multiline(text, *self.tri_double)
    136
    137
    138 -    def match_multiline(self, text, delimiter, in_state, style):
    139          """Do highlighting of multi-line strings. ``delimiter`` should be a
    140          ``QRegExp`` for triple-single-quotes or triple-double-quotes, and
    141          ``in_state`` should be a unique integer to represent the corresponding
    142          state changes when inside those strings. Returns True if we're still
    143          inside a multi-line string when this function is finished.
    144          """
    145          # If inside triple-single quotes, start at 0
    146          if self.previousBlockState() == in_state:
    147              start = 0
    148              add = 0
    149          # Otherwise, look for the delimiter on this line
    150          else:
    151              start = delimiter.indexIn(text)
    152              # Move past this match
    153              add = delimiter.matchedLength()
    154
    155          # As long as there's a delimiter match on this line...
    156          while start >= 0:
    157              # Look for the ending delimiter
    158              end = delimiter.indexIn(text, start + add)
    159              # Ending delimiter on this line?
    160              if end >= add:
    161                  length = end - start + add + delimiter.matchedLength()
    162                  self.setCurrentBlockState(0)
    163              # No; multi-line string
    164              else:
    165                  self.setCurrentBlockState(in_state)
    166                  length = text.length() - start + add
    167              # Apply formatting
    168              self.setFormat(start, length, style)
    169              # Look for the next match
    170              start = delimiter.indexIn(text, start + length)
    171
    172          # Return True if still inside a multi-line string, False otherwise
    173          if self.currentBlockState() == in_state:
    174              return True
    175          else:
    176              return False
    177