| 1 | import sys |
|---|
| 2 | from PyQt4 import QtCore, QtGui, Qsci |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | class MainWindow(QtGui.QMainWindow): |
|---|
| 6 | def __init__(self): |
|---|
| 7 | QtGui.QMainWindow.__init__(self) |
|---|
| 8 | self.setWindowTitle('Custom Lexer Example') |
|---|
| 9 | self.setGeometry(QtCore.QRect(50,200,400,400)) |
|---|
| 10 | self.editor = Qsci.QsciScintilla(self) |
|---|
| 11 | self.editor.setUtf8(True) |
|---|
| 12 | self.editor.setMarginWidth(2, 15) |
|---|
| 13 | self.editor.setFolding(True) |
|---|
| 14 | self.setCentralWidget(self.editor) |
|---|
| 15 | self.lexer = CustomLexer(self.editor) |
|---|
| 16 | self.editor.setLexer(self.lexer) |
|---|
| 17 | self.editor.setText('\n# sample source\n\nfoo = 1\nbar = 2\n') |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | class CustomLexer(Qsci.QsciLexerCustom): |
|---|
| 21 | def __init__(self, parent): |
|---|
| 22 | Qsci.QsciLexerCustom.__init__(self, parent) |
|---|
| 23 | self._styles = { |
|---|
| 24 | 0: 'Default', |
|---|
| 25 | 1: 'Comment', |
|---|
| 26 | 2: 'Key', |
|---|
| 27 | 3: 'Assignment', |
|---|
| 28 | 4: 'Value', |
|---|
| 29 | } |
|---|
| 30 | for key,value in self._styles.iteritems(): |
|---|
| 31 | setattr(self, value, key) |
|---|
| 32 | |
|---|
| 33 | def description(self, style): |
|---|
| 34 | return self._styles.get(style, '') |
|---|
| 35 | |
|---|
| 36 | def defaultColor(self, style): |
|---|
| 37 | if style == self.Default: |
|---|
| 38 | return QtGui.QColor('#000000') |
|---|
| 39 | elif style == self.Comment: |
|---|
| 40 | return QtGui.QColor('#C0C0C0') |
|---|
| 41 | elif style == self.Key: |
|---|
| 42 | return QtGui.QColor('#0000CC') |
|---|
| 43 | elif style == self.Assignment: |
|---|
| 44 | return QtGui.QColor('#CC0000') |
|---|
| 45 | elif style == self.Value: |
|---|
| 46 | return QtGui.QColor('#00CC00') |
|---|
| 47 | return Qsci.QsciLexerCustom.defaultColor(self, style) |
|---|
| 48 | |
|---|
| 49 | def styleText(self, start, end): |
|---|
| 50 | editor = self.editor() |
|---|
| 51 | if editor is None: |
|---|
| 52 | return |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | |
|---|
| 56 | |
|---|
| 57 | source = '' |
|---|
| 58 | if end > editor.length(): |
|---|
| 59 | end = editor.length() |
|---|
| 60 | if end > start: |
|---|
| 61 | if sys.hexversion >= 0x02060000: |
|---|
| 62 | |
|---|
| 63 | source = bytearray(end - start) |
|---|
| 64 | editor.SendScintilla( |
|---|
| 65 | editor.SCI_GETTEXTRANGE, start, end, source) |
|---|
| 66 | else: |
|---|
| 67 | source = unicode(editor.text() |
|---|
| 68 | ).encode('utf-8')[start:end] |
|---|
| 69 | if not source: |
|---|
| 70 | return |
|---|
| 71 | |
|---|
| 72 | |
|---|
| 73 | index = editor.SendScintilla(editor.SCI_LINEFROMPOSITION, start) |
|---|
| 74 | if index > 0: |
|---|
| 75 | |
|---|
| 76 | pos = editor.SendScintilla( |
|---|
| 77 | editor.SCI_GETLINEENDPOSITION, index - 1) |
|---|
| 78 | state = editor.SendScintilla(editor.SCI_GETSTYLEAT, pos) |
|---|
| 79 | else: |
|---|
| 80 | state = self.Default |
|---|
| 81 | |
|---|
| 82 | set_style = self.setStyling |
|---|
| 83 | self.startStyling(start, 0x1f) |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | for line in source.splitlines(True): |
|---|
| 87 | length = len(line) |
|---|
| 88 | if line.startswith('#'): |
|---|
| 89 | state = self.Comment |
|---|
| 90 | else: |
|---|
| 91 | |
|---|
| 92 | pos = line.find('=') |
|---|
| 93 | if pos > 0: |
|---|
| 94 | set_style(pos, self.Key) |
|---|
| 95 | set_style(1, self.Assignment) |
|---|
| 96 | length = length - pos - 1 |
|---|
| 97 | state = self.Value |
|---|
| 98 | else: |
|---|
| 99 | state = self.Default |
|---|
| 100 | set_style(length, state) |
|---|
| 101 | |
|---|
| 102 | index += 1 |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | if __name__ == "__main__": |
|---|
| 106 | app = QtGui.QApplication(sys.argv) |
|---|
| 107 | app.connect(app, QtCore.SIGNAL('lastWindowClosed()'), |
|---|
| 108 | QtCore.SLOT('quit()')) |
|---|
| 109 | win = MainWindow() |
|---|
| 110 | win.show() |
|---|
| 111 | sys.exit(app.exec_()) |
|---|