diff --git a/src/backends/python/pythonhighlighter.cpp b/src/backends/python/pythonhighlighter.cpp index 34d894b6..40645249 100644 --- a/src/backends/python/pythonhighlighter.cpp +++ b/src/backends/python/pythonhighlighter.cpp @@ -1,101 +1,150 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2013 Filipe Saraiva */ #include "pythonhighlighter.h" #include "pythonkeywords.h" #include #include PythonHighlighter::PythonHighlighter(QObject* parent) : Cantor::DefaultHighlighter(parent) { qDebug() << "PythonHighlighter construtor"; - addRule(QRegExp(QLatin1String("\\b[A-Za-z0-9_]+(?=\\()")), functionFormat()); + addRule(QRegExp(QLatin1String("\\b\\w+(?=\\()")), functionFormat()); //Code highlighting the different keywords addKeywords(PythonKeywords::instance()->keywords()); - - addRule(QLatin1String("FIXME"), commentFormat()); - addRule(QLatin1String("TODO"), commentFormat()); - addFunctions(PythonKeywords::instance()->functions()); addVariables(PythonKeywords::instance()->variables()); - - addRule(QRegExp(QLatin1String("\".*\"")), stringFormat()); - addRule(QRegExp(QLatin1String("'.*'")), stringFormat()); - addRule(QRegExp(QLatin1String("#[^\n]*")), commentFormat()); - - commentStartExpression = QRegExp(QLatin1String("'''[^\n]*")); - commentEndExpression = QRegExp(QLatin1String("'''")); } PythonHighlighter::~PythonHighlighter() { } -void PythonHighlighter::highlightBlock(const QString& text) +void PythonHighlighter::highlightBlock(const QString &text) { - qDebug() << "PythonHighlighter::highlightBlock"; - qDebug() << "text: " << text; - - if (skipHighlighting(text)){ - qDebug() << "skipHighlighting(" << text << " ) " << "== true"; + if (skipHighlighting(text)) { return; } - //Do some backend independent highlighting (brackets etc.) + // Do some backend independent highlighting (brackets etc.) DefaultHighlighter::highlightBlock(text); - setCurrentBlockState(0); + const int IN_MULTILINE_COMMENT = 1; + const int IN_SMALL_QUOTE_STRING = 2; + const int IN_SINGLE_QUOTE_STRING = 4; + const int IN_TRIPLE_QUOTE_STRING = 8; - int startIndex = 0; - if (previousBlockState() != 1) - startIndex = commentStartExpression.indexIn(text); + QRegExp multiLineCommentStartEnd(QLatin1String("'''")); + QRegExp smallQuoteStartEnd(QLatin1String("'")); + QRegExp singleQuoteStringStartEnd(QLatin1String("\"")); + QRegExp tripleQuoteStringStartEnd(QLatin1String("\"\"\"")); + QRegExp singleLineCommentStart(QLatin1String("#")); - while (startIndex >= 0) { + int state = previousBlockState(); + if (state == -1) { + state = 0; + } - int endIndex = commentEndExpression.indexIn(text, startIndex); - int commentLength; - if (endIndex == -1) { + QList flags = { + IN_TRIPLE_QUOTE_STRING, + IN_SINGLE_QUOTE_STRING, + IN_SMALL_QUOTE_STRING, + IN_MULTILINE_COMMENT + }; + QList regexps = { + tripleQuoteStringStartEnd, + singleQuoteStringStartEnd, + smallQuoteStartEnd, + multiLineCommentStartEnd + }; + QList formats = { + stringFormat(), + stringFormat(), + stringFormat(), + commentFormat() + }; + + int pos = 0; + while (pos < text.length()) { + // Trying to close current environments + bool triggered = false; + for (int i = 0; i < flags.size() and not triggered; i++) { + int flag = flags[i]; + QRegExp ®exp = regexps[i]; + QTextCharFormat &format = formats[i]; + if (state & flag) { + int new_pos = regexp.indexIn(text, pos); + int length; + if (new_pos == -1) { + length = text.length() - pos; + } else { + length = new_pos - pos + regexp.matchedLength(); + state -= flag; + } + setFormat(pos, length, format); + pos = pos + length; + triggered = true; + } + } + if (triggered) { + continue; + } - setCurrentBlockState(1); - commentLength = text.length() - startIndex; - } else { - commentLength = endIndex - startIndex - + commentEndExpression.matchedLength(); + QRegExp *minRegexp = nullptr; + int minPos = INT_MAX; + int minIdx = -1; + for (int i = 0; i < regexps.size(); i++) { + QRegExp ®exp = regexps[i]; + int newPos = regexp.indexIn(text, pos); + if (newPos != -1) { + minPos = qMin(minPos, newPos); + minRegexp = ®exp; + minIdx = i; + } } - setFormat(startIndex, commentLength, commentFormat()); - startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); + + int singleLineCommentStartPos = + singleLineCommentStart.indexIn(text, pos); + + if (singleLineCommentStartPos != -1 + and singleLineCommentStartPos < minPos) { + setFormat(pos, text.length() - pos, commentFormat()); + break; + } else if (minRegexp) { + state += flags[minIdx]; + pos = minPos + minRegexp->matchedLength(); + setFormat(minPos, minRegexp->matchedLength(), formats[minIdx]); + } else { + break; + } } + + setCurrentBlockState(state); } void PythonHighlighter::updateHighlight() { qDebug(); addVariables(PythonKeywords::instance()->variables()); rehighlight(); } - -QString PythonHighlighter::nonSeparatingCharacters() const -{ - qDebug() << "PythonHighlighter::nonSeparatingCharacters() function"; - return QLatin1String("[%]"); -} diff --git a/src/backends/python/pythonhighlighter.h b/src/backends/python/pythonhighlighter.h index 3ef2dba7..fa84a124 100644 --- a/src/backends/python/pythonhighlighter.h +++ b/src/backends/python/pythonhighlighter.h @@ -1,47 +1,46 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2013 Filipe Saraiva */ #ifndef _PYTHONHIGHLIGHTER_H #define _PYTHONHIGHLIGHTER_H #include "defaulthighlighter.h" class PythonHighlighter : public Cantor::DefaultHighlighter { Q_OBJECT public: PythonHighlighter(QObject* parent); ~PythonHighlighter(); public Q_SLOTS: void updateHighlight(); protected: void highlightBlock(const QString& text); - QString nonSeparatingCharacters() const; private: QRegExp commentStartExpression; QRegExp commentEndExpression; }; #endif /* _PYTHONHIGHLIGHTER_H */