1 // Copyright (C) 2015-2016 OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : PyEditor_PyHighlighter.cxx
20 // Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
23 #include "PyEditor_PyHighlighter.h"
26 #define TRIPLESINGLE 1
27 #define TRIPLEDOUBLE 2
30 \class PyEditor_PyHighlighter
31 \brief Python highlighter class defines the syntax highlighting rules.
34 PyEditor_PyHighlighter::TextBlockData::TextBlockData()
38 QVector<PyEditor_PyHighlighter::ParenthesisInfo*> PyEditor_PyHighlighter::TextBlockData::parentheses()
43 void PyEditor_PyHighlighter::TextBlockData::insert( PyEditor_PyHighlighter::ParenthesisInfo* theInfo )
46 while ( i < myParentheses.size() && theInfo->position > myParentheses.at(i)->position )
49 myParentheses.insert( i, theInfo );
54 \param theDocument container for structured rich text documents.
56 PyEditor_PyHighlighter::PyEditor_PyHighlighter( QTextDocument* theDocument )
57 : QSyntaxHighlighter( theDocument )
63 \brief Initialization rules.
65 void PyEditor_PyHighlighter::initialize()
67 HighlightingRule aRule;
70 keywordFormat.setForeground( Qt::blue );
71 QStringList aKeywords = keywords();
72 foreach ( const QString& keyword, aKeywords )
74 aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
75 aRule.format = keywordFormat;
77 highlightingRules.append( aRule );
81 specialFromat.setForeground( Qt::magenta );
82 QStringList aSpecialKeywords = specialKeywords();
83 foreach ( const QString& keyword, aSpecialKeywords )
85 aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
86 aRule.format = specialFromat;
88 highlightingRules.append( aRule );
91 // Reference to the current instance of the class
92 referenceClassFormat.setForeground( QColor( 179, 143, 0 ) );
93 referenceClassFormat.setFontItalic( true );
94 aRule.pattern = QRegExp( "\\bself\\b" );
95 aRule.format = referenceClassFormat;
97 highlightingRules.append( aRule );
100 numberFormat.setForeground( Qt::darkMagenta );
101 aRule.pattern = QRegExp( "\\b([-+])?(\\d+(\\.)?\\d*|\\d*(\\.)?\\d+)(([eE]([-+])?)?\\d+)?\\b" );
102 aRule.format = numberFormat;
104 highlightingRules.append( aRule );
107 quotationFormat.setForeground( Qt::darkGreen );
108 aRule.pattern = QRegExp( "(?:'[^']*'|\"[^\"]*\")" );
109 aRule.pattern.setMinimal( true );
110 aRule.format = quotationFormat;
112 highlightingRules.append( aRule );
115 functionFormat.setFontWeight( QFont::Bold );
116 aRule.pattern = QRegExp( "(?:def\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
118 aRule.format = functionFormat;
119 highlightingRules.append( aRule );
122 classFormat.setForeground( Qt::darkBlue );
123 classFormat.setFontWeight( QFont::Bold );
124 aRule.pattern = QRegExp( "(?:class\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
126 aRule.format = classFormat;
127 highlightingRules.append( aRule );
129 // Multi line comments
130 multiLineCommentFormat.setForeground( Qt::darkRed );
131 tripleQuotesExpression = QRegExp( "(:?\"[\"]\".*\"[\"]\"|'''.*''')" );
132 aRule.pattern = tripleQuotesExpression;
133 aRule.pattern.setMinimal( true );
134 aRule.format = multiLineCommentFormat;
136 highlightingRules.append( aRule );
138 tripleSingleExpression = QRegExp( "'''(?!\")" );
139 tripleDoubleExpression = QRegExp( "\"\"\"(?!')" );
142 singleLineCommentFormat.setForeground( Qt::darkGray );
143 aRule.pattern = QRegExp( "#[^\n]*" );
144 aRule.format = singleLineCommentFormat;
146 highlightingRules.append( aRule );
150 \return string list of Python keywords.
152 QStringList PyEditor_PyHighlighter::keywords()
154 QStringList aKeywords;
192 \return string list of special Python keywords.
194 QStringList PyEditor_PyHighlighter::specialKeywords()
196 QStringList aSpecialKeywords;
197 aSpecialKeywords << "ArithmeticError"
200 << "EnvironmentError"
203 << "FloatingPointError"
205 << "IndentationError"
208 << "KeyboardInterrupt"
213 << "NotImplementedError"
225 << "UnboundLocalError"
226 << "UnicodeDecodeError"
227 << "UnicodeEncodeError"
229 << "UnicodeTranslateError"
232 << "ZeroDivisionError"
235 << "DeprecationWarning"
236 << "PendingDeprecationWarning"
241 return aSpecialKeywords;
244 void PyEditor_PyHighlighter::highlightBlock( const QString& theText )
246 TextBlockData* aData = new TextBlockData;
248 insertBracketsData( RoundBrackets, aData, theText );
249 insertBracketsData( CurlyBrackets, aData, theText );
250 insertBracketsData( SquareBrackets, aData, theText );
252 setCurrentBlockUserData( aData );
254 foreach ( const HighlightingRule& rule, highlightingRules )
256 QRegExp expression( rule.pattern );
257 int anIndex = expression.indexIn( theText );
258 while ( anIndex >= 0 )
260 anIndex = expression.pos( rule.capture );
261 int aLength = expression.cap( rule.capture ).length();
262 setFormat( anIndex, aLength, rule.format );
263 anIndex = expression.indexIn( theText, anIndex + aLength );
267 setCurrentBlockState( NORMAL );
269 if ( theText.indexOf( tripleQuotesExpression ) != -1 )
272 QList<int> aTripleSingle;
273 aTripleSingle << theText.indexOf( tripleSingleExpression ) << TRIPLESINGLE;
275 QList<int> aTripleDouble;
276 aTripleDouble << theText.indexOf( tripleDoubleExpression ) << TRIPLEDOUBLE;
278 QList< QList<int> > aTripleExpressions;
279 aTripleExpressions << aTripleSingle << aTripleDouble;
281 for ( int i = 0; i < aTripleExpressions.length(); i++ )
283 QList<int> aBlock = aTripleExpressions[i];
284 int anIndex = aBlock[0];
285 int aState = aBlock[1];
286 if ( previousBlockState() == aState )
290 anIndex = theText.length();
291 setCurrentBlockState( aState );
293 setFormat( 0, anIndex + 3, multiLineCommentFormat );
295 else if ( anIndex > -1 )
297 setCurrentBlockState( aState );
298 setFormat( anIndex, theText.length(), multiLineCommentFormat );
303 void PyEditor_PyHighlighter::insertBracketsData( char theLeftSymbol,
305 TextBlockData* theData,
306 const QString& theText )
308 int leftPosition = theText.indexOf( theLeftSymbol );
309 while( leftPosition != -1 )
311 ParenthesisInfo* info = new ParenthesisInfo();
312 info->character = theLeftSymbol;
313 info->position = leftPosition;
315 theData->insert( info );
316 leftPosition = theText.indexOf( theLeftSymbol, leftPosition + 1 );
319 int rightPosition = theText.indexOf( theRightSymbol );
320 while( rightPosition != -1 )
322 ParenthesisInfo* info = new ParenthesisInfo();
323 info->character = theRightSymbol;
324 info->position = rightPosition;
326 theData->insert( info );
327 rightPosition = theText.indexOf( theRightSymbol, rightPosition + 1 );
331 void PyEditor_PyHighlighter::insertBracketsData( Brackets theBrackets,
332 TextBlockData* theData,
333 const QString& theText )
336 char rightChar = '0';
338 switch( theBrackets )
354 insertBracketsData( leftChar, rightChar, theData, theText );