diff --git a/modules/gui/src/python_shell/gutter.cc b/modules/gui/src/python_shell/gutter.cc index fa952218400a5ab350d62a01238f1d4a90944288..e60b4c4d6b8985535c67ab6fa4d8480a601d5ab4 100644 --- a/modules/gui/src/python_shell/gutter.cc +++ b/modules/gui/src/python_shell/gutter.cc @@ -51,17 +51,17 @@ void Gutter::paintEvent(QPaintEvent* paint_event) painter.fillRect(paint_event->rect(), QBrush(Qt::lightGray)); for (GutterBlockList::const_iterator it=blocks.begin(); it!=blocks.end(); ++it) { - if (it->type == BLOCKTYPE_ACTIVE) { + if (it->type & BLOCKTYPE_ACTIVE) { QColor green(Qt::green); painter.setPen(QPen(green.darker(), 3)); - }else if (it->type == BLOCKTYPE_BLOCKEDIT) { + }else if (it->type & BLOCKTYPE_BLOCKEDIT) { painter.setPen(QPen(Qt::yellow, 3)); - }else if (it->type == BLOCKTYPE_CODE) { + }else if (it->type & BLOCKTYPE_CODE) { QColor green(Qt::green); painter.setPen(QPen(green.darker(), 1)); - } else if (it->type == BLOCKTYPE_OUTPUT) { + } else if (it->type & BLOCKTYPE_OUTPUT) { painter.setPen(QPen(Qt::blue, 1)); - } else if (it->type == BLOCKTYPE_ERROR) { + } else if (it->type & BLOCKTYPE_ERROR) { painter.setPen(QPen(Qt::red, 1)); } else { painter.setPen(QPen(Qt::black, 1)); diff --git a/modules/gui/src/python_shell/python_shell_fw.hh b/modules/gui/src/python_shell/python_shell_fw.hh index e86b3804f89f866b451e4cbfde4a21b392f6d877..0d3f1e641d58a946c46f9ed882aada2efd79f928 100644 --- a/modules/gui/src/python_shell/python_shell_fw.hh +++ b/modules/gui/src/python_shell/python_shell_fw.hh @@ -35,11 +35,13 @@ enum BlockEditMode { EDITMODE_MULTILINE_INACTIVE }; enum BlockType { - BLOCKTYPE_OUTPUT, - BLOCKTYPE_ERROR, - BLOCKTYPE_CODE, - BLOCKTYPE_ACTIVE, - BLOCKTYPE_BLOCKEDIT + BLOCKTYPE_OUTPUT=1, + BLOCKTYPE_ERROR=2, + BLOCKTYPE_CODE=4, + BLOCKTYPE_ACTIVE=8, + BLOCKTYPE_BLOCKEDIT=16, + BLOCKTYPE_MULTILINE_SQ=32, + BLOCKTYPE_MULTILINE_DQ=64 }; struct GutterBlock{ diff --git a/modules/gui/src/python_shell/python_syntax_highlighter.cc b/modules/gui/src/python_shell/python_syntax_highlighter.cc index c6f16ba6ae99dff924284267fb64b4720a949151..1d2d75591de13d2d9400d8cdedcc30ca0bf1a3a8 100644 --- a/modules/gui/src/python_shell/python_syntax_highlighter.cc +++ b/modules/gui/src/python_shell/python_syntax_highlighter.cc @@ -21,7 +21,7 @@ */ #include <iostream> - +#include <QDebug> #include <QTextCursor> #include "python_shell.hh" @@ -72,11 +72,32 @@ PythonSyntaxHighlighter::PythonSyntaxHighlighter(QTextDocument* parent): void PythonSyntaxHighlighter::highlightBlock(const QString& text_block) { QTextCursor cursor(currentBlock()); - cursor.setBlockFormat(block_formats_[static_cast<BlockType>(currentBlockState())]); - if (currentBlockState() == BLOCKTYPE_BLOCKEDIT || currentBlockState() == BLOCKTYPE_ACTIVE || currentBlockState() == BLOCKTYPE_CODE){ + int base_state=-1; + if (currentBlockState() & BLOCKTYPE_OUTPUT) { + base_state=BLOCKTYPE_OUTPUT; + } else if (currentBlockState() & BLOCKTYPE_ERROR) { + base_state=BLOCKTYPE_ERROR; + } else if (currentBlockState() & BLOCKTYPE_ACTIVE) { + base_state=BLOCKTYPE_ACTIVE; + } else if (currentBlockState() & BLOCKTYPE_BLOCKEDIT) { + base_state=BLOCKTYPE_BLOCKEDIT; + } else if (currentBlockState() & BLOCKTYPE_CODE) { + base_state=BLOCKTYPE_CODE; + } + cursor.setBlockFormat(block_formats_[static_cast<BlockType>(base_state)]); + if (currentBlockState() & BLOCKTYPE_BLOCKEDIT || + currentBlockState() & BLOCKTYPE_ACTIVE || + currentBlockState() & BLOCKTYPE_CODE) { StringLiteralPositions* positions=new StringLiteralPositions(); int blockposition=currentBlock().position(); - PythonTokenizer pt(text_block,0); + int string_state=0; + int bs=previousBlockState()==-1 ? 0 : previousBlockState(); + if (bs & BLOCKTYPE_MULTILINE_SQ) { + string_state=1; + } else if (bs & BLOCKTYPE_MULTILINE_DQ) { + string_state=2; + } + PythonTokenizer pt(text_block,string_state); PythonToken t; PythonToken last; int type_before_last=PythonToken::END; @@ -84,14 +105,28 @@ void PythonSyntaxHighlighter::highlightBlock(const QString& text_block) { while((t = pt.NextToken()).GetType() != PythonToken::END) { setFormat(t.GetRange().location,t.GetRange().length,formats_[t.GetType()]); if(t.GetType()==PythonToken::STRING_LITERAL){ - positions->Append(blockposition+t.GetRange().location,blockposition+t.GetRange().location+t.GetRange().length); + positions->Append(blockposition+t.GetRange().location, + blockposition+t.GetRange().location+ + t.GetRange().length); } type_before_last=last.GetType(); last=t; } - if(last.GetType()==PythonToken::STRING_DELIM && type_before_last!=PythonToken::STRING_LITERAL && type_before_last!=PythonToken::STRING_DELIM){ - positions->Append(blockposition+last.GetRange().location+1,blockposition+last.GetRange().location+1); + if(last.GetType()==PythonToken::STRING_DELIM && + type_before_last!=PythonToken::STRING_LITERAL && + type_before_last!=PythonToken::STRING_DELIM){ + positions->Append(blockposition+last.GetRange().location+1, + blockposition+last.GetRange().location+1); + } + int new_state=base_state; + if (pt.InString()) { + if (pt.GetDelim()=="'''") { + new_state|=BLOCKTYPE_MULTILINE_SQ; + } else if (pt.GetDelim()=="\"\"\""){ + new_state|=BLOCKTYPE_MULTILINE_DQ; + } } + setCurrentBlockState(new_state); currentBlock().setUserData(positions); } } diff --git a/modules/gui/src/python_shell/python_tokenizer.cc b/modules/gui/src/python_shell/python_tokenizer.cc index 1049b3b803d4a40810c7ee75cd2b86b598cd0b36..11126baadf515a4a2e4aed5bb1f2cca5bbc1d659 100644 --- a/modules/gui/src/python_shell/python_tokenizer.cc +++ b/modules/gui/src/python_shell/python_tokenizer.cc @@ -137,11 +137,13 @@ PythonToken PythonTokenizer::GetOperatorToken() { static QString operators[] = { QString("+="), QString("-="), QString("*="), + QString("**"), QString("&="), QString("|="), QString("/="), QString("+"), QString("-"), QString("/"), QString("*"), QString("."), QString("%"), QString("="), QString("!="), QString("!"), QString("<="), QString(">="), - QString("<"), QString(":"), QString("?"), + QString("<"), QString(":"), QString("?"), + QString("|"), QString("&"), QString("^"), QString("") }; size_t index = -1; @@ -205,7 +207,7 @@ PythonToken PythonTokenizer::GetStringDelim() { Range range(current_pos_,0); // Find out which type of delimiters are used for the String. i.e. <">, - // <"""> or <'> + // <""">, <'''> or <'> QString delimiter = "\""; if (command_[current_pos_] == '\'') delimiter = "'"; diff --git a/modules/gui/src/python_shell/python_tokenizer.hh b/modules/gui/src/python_shell/python_tokenizer.hh index 2c398dfbdf673d002c0bf7c484c94c199e2298e3..142870da44f863085855c97d70b6ecdaff684fe9 100644 --- a/modules/gui/src/python_shell/python_tokenizer.hh +++ b/modules/gui/src/python_shell/python_tokenizer.hh @@ -86,7 +86,8 @@ public: PythonToken NextToken(); const PythonToken& CurrentToken() const; void SetInString(bool in_string); - + bool InString() const { return in_string_; } + const QString& GetDelim() const { return string_delim_; } private: void EatWhities(); QString GetSubString(const Range& range);