Mercurial > lcfOS
annotate python/codeeditor.py @ 149:74241ca312cc
Fixes on parser and semantics
author | Windel Bouwman |
---|---|
date | Fri, 01 Mar 2013 11:43:52 +0100 |
parents | af0d7913677a |
children | 81e08e2e7777 |
rev | line source |
---|---|
1 | 1 from PyQt4.QtCore import * |
2 from PyQt4.QtGui import * | |
100 | 3 #import compiler.lexer |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
4 import os.path |
1 | 5 |
6 class MySyntaxHighlighter(QSyntaxHighlighter): | |
7 def __init__(self, parent=None): | |
8 super(MySyntaxHighlighter, self).__init__(parent) | |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
9 # Syntax highlighting: |
1 | 10 self.rules = [] |
11 fmt = QTextCharFormat() | |
12 fmt.setForeground(Qt.darkBlue) | |
13 fmt.setFontWeight(QFont.Bold) | |
100 | 14 #for kw in compiler.lexer.keywords: |
15 # pattern = '\\b'+kw+'\\b' | |
16 # self.rules.append( (pattern, fmt) ) | |
1 | 17 |
18 # Comments: | |
19 fmt = QTextCharFormat() | |
20 fmt.setForeground(Qt.gray) | |
21 fmt.setFontItalic(True) | |
22 pattern = '\{.*\}' | |
23 self.rules.append( (pattern, fmt) ) | |
24 | |
25 # Procedure: | |
26 fmt = QTextCharFormat() | |
27 fmt.setForeground(Qt.blue) | |
28 fmt.setFontItalic(True) | |
29 #pattern = '(?<=procedure )[A-Za-z]' | |
30 # TODO lookbehind does not work, think something else | |
31 #self.rules.append( (pattern, fmt) ) | |
32 | |
33 def highlightBlock(self, text): | |
34 for pattern, fmt in self.rules: | |
35 expression = QRegExp(pattern) | |
36 index = expression.indexIn(text) | |
37 while index >= 0: | |
38 length = expression.matchedLength() | |
39 self.setFormat(index, length, fmt) | |
40 index = expression.indexIn(text, index + length) | |
41 | |
42 class LineNumberArea(QWidget): | |
43 def __init__(self, codeedit): | |
44 super(LineNumberArea, self).__init__(codeedit) | |
45 self.codeedit = codeedit | |
46 # TODO: display error in this: self.setToolTip('hello world') | |
47 def sizeHint(self): | |
48 return QSize(self.codeedit.lineNumberAreaWidth(), 0) | |
49 def paintEvent(self, ev): | |
50 self.codeedit.lineNumberAreaPaintEvent(ev) | |
51 | |
52 class CodeEdit(QPlainTextEdit): | |
53 def __init__(self, parent=None): | |
54 super(CodeEdit, self).__init__(parent) | |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
55 # members: |
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
56 self.isUntitled = True |
1 | 57 self.filename = None |
58 self.setFont(QFont('Courier')) | |
59 self.lineNumberArea = LineNumberArea(self) | |
60 | |
61 self.blockCountChanged.connect(self.updateLineNumberAreaWidth) | |
62 self.updateRequest.connect(self.updateLineNumberArea) | |
63 | |
64 # Syntax highlighter: | |
65 self.highlighter = MySyntaxHighlighter(self.document()) | |
66 | |
15 | 67 def setFileName(self, filename): |
1 | 68 self.filename = filename |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
69 self.isUntitled = False |
15 | 70 self.setWindowTitle(filename) |
101 | 71 |
15 | 72 def setSource(self, source): |
1 | 73 self.setPlainText(source) |
101 | 74 def getSource(self): |
75 return self.toPlainText() | |
76 source = property(getSource, setSource) | |
15 | 77 |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
78 def save(self): |
101 | 79 self.saveFile() |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
80 def saveAs(self): |
101 | 81 print('save as') |
8 | 82 |
1 | 83 def saveFile(self): |
9
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
84 if self.isUntitled: |
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
85 self.saveAs() |
92ace1ca50a8
64 bits kernel without interrupts but with printf in C
windel
parents:
8
diff
changeset
|
86 else: |
1 | 87 source = str(self.toPlainText()) |
101 | 88 with open(self.filename, 'w') as f: |
89 f.write(source) | |
1 | 90 |
91 def highlightErrorLocation(self, row, col): | |
92 tc = QTextCursor(self.document()) | |
93 tc.clearSelection() | |
94 tc.movePosition(tc.Down, tc.MoveAnchor, row - 1) | |
95 tc.movePosition(tc.Right, tc.MoveAnchor, col - 1) | |
96 tc.movePosition(tc.NextCharacter, tc.KeepAnchor) # Select 1 character | |
97 selection = QTextEdit.ExtraSelection() | |
98 lineColor = QColor(Qt.red).lighter(160) | |
99 selection.format.setBackground(lineColor) | |
100 #selection.format.setProperty(QTextFormat.FullWidthSelection, True) | |
101 selection.cursor = tc | |
102 self.setExtraSelections( [ selection ] ) | |
103 def clearErrors(self): | |
104 self.setExtraSelections( [ ] ) | |
105 | |
106 def lineNumberAreaWidth(self): | |
107 digits = 1 | |
108 mx = max(1, self.blockCount()) | |
109 while mx >= 10: | |
110 mx = mx / 10 | |
111 digits += 1 | |
112 space = 3 + self.fontMetrics().width('8') * digits | |
113 return space | |
114 def lineNumberAreaPaintEvent(self, ev): | |
115 painter = QPainter(self.lineNumberArea) | |
116 painter.fillRect(ev.rect(), Qt.lightGray) | |
117 block = self.firstVisibleBlock() | |
118 blockNumber = block.blockNumber() | |
119 top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top() | |
120 bottom = top + self.blockBoundingRect(block).height() | |
121 while block.isValid() and top <= ev.rect().bottom(): | |
122 if block.isVisible() and bottom >= ev.rect().top(): | |
123 num = str(blockNumber + 1) | |
124 painter.setPen(Qt.black) | |
125 painter.drawText(0, top, self.lineNumberArea.width(), self.fontMetrics().height(), Qt.AlignRight, num) | |
126 block = block.next() | |
127 top = bottom | |
128 bottom = top + self.blockBoundingRect(block).height() | |
129 blockNumber += 1 | |
130 def resizeEvent(self, ev): | |
131 super(CodeEdit, self).resizeEvent(ev) | |
132 cr = self.contentsRect() | |
133 self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height() )) | |
134 def updateLineNumberAreaWidth(self, newBlockCount): | |
135 self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) | |
136 def updateLineNumberArea(self, rect, dy): | |
137 if dy > 0: | |
138 self.lineNumberArea.scroll(0, dy) | |
139 else: | |
140 self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) | |
141 if rect.contains(self.viewport().rect()): | |
142 self.updateLineNumberAreaWidth(0) | |
143 |