Skip to content

Commit 5e5bd8f

Browse files
committed
Indentation and Syntax Highlight Bug Fixes
1 parent f8875f9 commit 5e5bd8f

6 files changed

Lines changed: 139 additions & 40 deletions

File tree

CodeEditor/codeeditor.cpp

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
****************************************************************************/
4242

4343
#include <QtWidgets>
44+
#include <QDebug>
45+
#include <QTextStream>
4446
#include "CodeEditor/codeeditor.h"
4547

4648
CodeEditor::CodeEditor(QWidget* parent)
@@ -97,14 +99,98 @@ void CodeEditor::resizeEvent(QResizeEvent* e)
9799
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
98100
}
99101

102+
void CodeEditor::SelectLineMarginBlock()
103+
{
104+
int start, end;
105+
106+
// get current positions
107+
start = this->textCursor().selectionStart();
108+
end = this->textCursor().selectionEnd();
109+
110+
QTextCursor cursor(this->document());
111+
112+
// move cursor to begin of the line, of the line
113+
// start position is located.
114+
cursor.clearSelection();
115+
cursor.setPosition(start);
116+
cursor.movePosition(QTextCursor::StartOfLine);
117+
this->setTextCursor(cursor);
118+
start = this->textCursor().selectionStart();
119+
120+
// move cursor to end of the line, of the line
121+
// end position is located.
122+
cursor.setPosition(end);
123+
cursor.movePosition(QTextCursor::EndOfLine);
124+
this->setTextCursor(cursor);
125+
end = this->textCursor().selectionEnd();
126+
127+
// select line margin block
128+
cursor.setPosition(start, QTextCursor::KeepAnchor);
129+
this->setTextCursor(cursor);
130+
}
131+
QString CodeEditor::GetLine()
132+
{
133+
int start = this->textCursor().position();
134+
QTextCursor cursor(this->document());
135+
cursor.setPosition(start);
136+
cursor.movePosition(QTextCursor::StartOfLine);
137+
this->setTextCursor(cursor);
138+
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
139+
this->setTextCursor(cursor);
140+
QString text = this->textCursor().selection().toPlainText();
141+
cursor.movePosition(QTextCursor::EndOfLine);
142+
this->setTextCursor(cursor);
143+
return text;
144+
}
145+
bool CodeEditor::KeepIndent()
146+
{
147+
if (this->textCursor().hasSelection() || !this->textCursor().atBlockEnd()) {
148+
return false;
149+
}
150+
QRegExp spaces("(\\s*).*");
151+
152+
spaces.indexIn(GetLine());
153+
this->insertPlainText(tr("\n"));
154+
this->insertPlainText(spaces.cap(1));
155+
156+
return true;
157+
}
100158
void CodeEditor::keyPressEvent(QKeyEvent* e)
101159
{
102-
//TODO handle automatical indentation
103-
//TODO backspace auto unindent
104-
//TODO indent selected text
105160
switch (e->key()) {
161+
case Qt::Key_Backtab:
162+
SelectLineMarginBlock();
163+
{
164+
QString text("");
165+
QStringList lines = this->textCursor().selection().toPlainText().split(QRegExp("\n|\r\n|\r"));
166+
foreach (QString line, lines) {
167+
line.replace(QRegExp("( | | | )(.*)"), "\\2");
168+
text.append(line);
169+
text.append("\n");
170+
}
171+
text.truncate(text.length() - 1);
172+
this->textCursor().insertText(text);
173+
}
174+
break;
106175
case Qt::Key_Tab:
107-
QPlainTextEdit::insertPlainText(" ");
176+
SelectLineMarginBlock();
177+
{
178+
QString text("");
179+
QStringList lines = this->textCursor().selection().toPlainText().split(QRegExp("\n|\r\n|\r"));
180+
foreach (QString line, lines) {
181+
text.append(" ");
182+
text.append(line);
183+
text.append("\n");
184+
}
185+
text.truncate(text.length() - 1);
186+
this->textCursor().insertText(text);
187+
}
188+
break;
189+
case Qt::Key_Enter:
190+
case Qt::Key_Return:
191+
if (!KeepIndent()) {
192+
QPlainTextEdit::keyPressEvent(e);
193+
}
108194
break;
109195
default:
110196
QPlainTextEdit::keyPressEvent(e);

CodeEditor/codeeditor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ private slots:
7171
private:
7272
QWidget* lineNumberArea;
7373
void keyPressEvent(QKeyEvent* e);
74+
void SelectLineMarginBlock();
75+
QString GetLine();
76+
bool KeepIndent();
7477
};
7578

7679
class LineNumberArea : public QWidget {

CodeEditor/pythonsyntaxhighlighter.cpp

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ PythonSyntaxHighlighter::PythonSyntaxHighlighter(QTextDocument* parent)
8888
<< ">>"
8989
<< "<<";
9090

91-
braces = QStringList() << "{"
91+
braces = QStringList() << ":"
92+
<< ";"
93+
<< ","
94+
<< "@"
95+
<< "{"
9296
<< "}"
9397
<< "\\("
9498
<< "\\)"
@@ -106,15 +110,17 @@ PythonSyntaxHighlighter::PythonSyntaxHighlighter(QTextDocument* parent)
106110
void PythonSyntaxHighlighter::setStyles()
107111
{
108112
basicStyles.insert("keyword", getTextCharFormat("orange", "bold"));
109-
basicStyles.insert("operator", getTextCharFormat("red"));
113+
basicStyles.insert("operator", getTextCharFormat("yellow", "bold"));
110114
basicStyles.insert("brace", getTextCharFormat("red", "bold"));
111-
basicStyles.insert("defclass", getTextCharFormat("white", "bold"));
112115
basicStyles.insert("string", getTextCharFormat("magenta"));
113-
basicStyles.insert("string2", getTextCharFormat("darkMagenta"));
114-
basicStyles.insert("comment", getTextCharFormat("darkGreen", "bold"));
115-
basicStyles.insert("self", getTextCharFormat("white", "bold"));
116+
basicStyles.insert("stringlong", getTextCharFormat("magenta", "bold"));
117+
basicStyles.insert("comment", getTextCharFormat("darkgreen", "bold"));
118+
basicStyles.insert("special", getTextCharFormat("teal", "bold"));
116119
basicStyles.insert("numbers", getTextCharFormat("cyan"));
117120
basicStyles.insert("bugs", getTextCharFormat("yellow", "bold", "red"));
121+
basicStyles.insert("hackish", getTextCharFormat("royalblue", "bold"));
122+
basicStyles.insert("private", getTextCharFormat("white", "italic"));
123+
basicStyles.insert("bytes", getTextCharFormat("lightsteelblue"));
118124
}
119125

120126
void PythonSyntaxHighlighter::initializeRules()
@@ -128,50 +134,52 @@ void PythonSyntaxHighlighter::initializeRules()
128134
foreach (QString currBrace, braces) {
129135
rules.append(HighlightingRule(QString("%1").arg(currBrace), 0, basicStyles.value("brace")));
130136
}
131-
// 'self'
132-
rules.append(HighlightingRule("\\bself\\b", 0, basicStyles.value("self")));
133137

134-
// Double-quoted string, possibly containing escape sequences
135-
rules.append(HighlightingRule("\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"", 0, basicStyles.value("string")));
136-
// Single-quoted string, possibly containing escape sequences
137-
rules.append(HighlightingRule("'[^'\\\\]*(\\\\.[^'\\\\]*)*'", 0, basicStyles.value("string")));
138+
rules.append(HighlightingRule("\\b__[\\w_]+__\\b", 0, basicStyles.value("hackish")));
139+
rules.append(HighlightingRule("\\b_[\\w_]+\\b", 0, basicStyles.value("private")));
138140

139-
// 'def' followed by an identifier
140-
rules.append(HighlightingRule("\\bdef\\b\\s*(\\w+)", 1, basicStyles.value("defclass")));
141-
// 'class' followed by an identifier
142-
rules.append(HighlightingRule("\\bclass\\b\\s*(\\w+)", 1, basicStyles.value("defclass")));
141+
rules.append(HighlightingRule("\\b_\\b", 0, basicStyles.value("special")));
142+
rules.append(HighlightingRule("\\bself\\b", 0, basicStyles.value("special")));
143+
144+
rules.append(HighlightingRule("[uUrR]?\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"", 0, basicStyles.value("string")));
145+
rules.append(HighlightingRule("[uUrR]?'[^'\\\\]*(\\\\.[^'\\\\]*)*'", 0, basicStyles.value("string")));
146+
147+
rules.append(HighlightingRule("(b|B|br|Br|bR|BR|rb|rB|Rb|RB)\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"", 0, basicStyles.value("bytes")));
148+
rules.append(HighlightingRule("(b|B|br|Br|bR|BR|rb|rB|Rb|RB)'[^'\\\\]*(\\\\.[^'\\\\]*)*'", 0, basicStyles.value("bytes")));
143149

144-
// Numeric literals
145150
rules.append(HighlightingRule("\\b[+-]?[0-9]+[lL]?\\b", 0, basicStyles.value("numbers")));
146151
rules.append(HighlightingRule("\\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\\b", 0, basicStyles.value("numbers")));
147152
rules.append(HighlightingRule("\\b[+-]?[0-9]+(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b", 0, basicStyles.value("numbers")));
148153

149-
// tab and space mixed
150-
rules.append(HighlightingRule("[^\\n]*(?:\\t | \\t)[^\\n]*", 0, basicStyles.value("bugs")));
154+
rules.append(HighlightingRule("\\t+", 0, basicStyles.value("bugs")));
155+
rules.append(HighlightingRule("\\?", 0, basicStyles.value("bugs")));
156+
rules.append(HighlightingRule("\\$", 0, basicStyles.value("bugs")));
151157

152-
// From '#' until a newline
153158
rules.append(HighlightingRule("#[^\\n]*", 0, basicStyles.value("comment")));
154159
}
155160

156161
void PythonSyntaxHighlighter::highlightBlock(const QString& text)
157162
{
158-
foreach (HighlightingRule currRule, rules) {
159-
int idx = currRule.pattern.indexIn(text, 0);
160-
while (idx >= 0) {
161-
// Get index of Nth match
162-
idx = currRule.pattern.pos(currRule.nth);
163-
int length = currRule.pattern.cap(currRule.nth).length();
164-
setFormat(idx, length, currRule.format);
165-
idx = currRule.pattern.indexIn(text, idx + length);
163+
int len = text.length();
164+
for (int i = 0; i < len; i++) {
165+
foreach (HighlightingRule currRule, rules) {
166+
int idx = currRule.pattern.indexIn(text, i);
167+
if (idx == i) {
168+
idx = currRule.pattern.pos(currRule.nth);
169+
int length = currRule.pattern.cap(currRule.nth).length();
170+
setFormat(idx, length, currRule.format);
171+
i = idx + length - 1;
172+
break;
173+
}
166174
}
167175
}
168176

169177
setCurrentBlockState(0);
170178

171179
// Do multi-line strings
172-
bool isInMultilne = matchMultiline(text, triSingleQuote, 1, basicStyles.value("string2"));
180+
bool isInMultilne = matchMultiline(text, triSingleQuote, 1, basicStyles.value("stringlong"));
173181
if (!isInMultilne)
174-
isInMultilne = matchMultiline(text, triDoubleQuote, 2, basicStyles.value("string2"));
182+
isInMultilne = matchMultiline(text, triDoubleQuote, 2, basicStyles.value("stringlong"));
175183
}
176184

177185
bool PythonSyntaxHighlighter::matchMultiline(const QString& text, const QRegExp& delimiter, const int inState, const QTextCharFormat& style)
@@ -233,5 +241,7 @@ const QTextCharFormat PythonSyntaxHighlighter::getTextCharFormat(
233241
charFormat.setFontWeight(QFont::Bold);
234242
if (style.contains("italic", Qt::CaseInsensitive))
235243
charFormat.setFontItalic(true);
244+
if (style.contains("underline", Qt::CaseInsensitive))
245+
charFormat.setFontUnderline(true);
236246
return charFormat;
237247
}

CodeEditor/pythonsyntaxhighlighter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE A
2020
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2121
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2222
USE OR OTHER DEALINGS IN THE SOFTWARE.
23+
24+
-----------Modified By Bhathiya Perera-------------
2325
*/
2426

2527
#ifndef KICKPYTHONSYNTAXHIGHLIGHTER_H

PyRun.pro

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ RESOURCES += \
3737
RC_FILE = WindowsResources/win_rsrc.rc
3838

3939

40-
win32: LIBS += -L$$PWD/../Python34/libs/ -lpython34
41-
42-
INCLUDEPATH += $$PWD/../Python34/include
43-
DEPENDPATH += $$PWD/../Python34/include
44-
45-
OTHER_FILES +=
40+
win32: LIBS += -LC:\Python34\libs\ -lpython34
41+
win32: INCLUDEPATH += C:\Python34\include
42+
win32: DEPENDPATH += C:\Python34\include

main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "UI/mainview.h"
55
#include <QApplication>
66

7+
78
static Snippets* snip;
89
static MainView* mainView;
910
int main(int argc, char* argv[])

0 commit comments

Comments
 (0)