From 95130d03ebcecc39793095712688a263b6b2c957 Mon Sep 17 00:00:00 2001 From: marco <marco@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Tue, 15 Jun 2010 10:05:47 +0000 Subject: [PATCH] improved handling of multiline strings in python shell git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2402 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/gui/src/python_shell/gutter.cc | 10 ++-- .../gui/src/python_shell/python_shell_fw.hh | 12 +++-- .../python_shell/python_syntax_highlighter.cc | 49 ++++++++++++++++--- .../gui/src/python_shell/python_tokenizer.cc | 6 ++- .../gui/src/python_shell/python_tokenizer.hh | 3 +- 5 files changed, 60 insertions(+), 20 deletions(-) diff --git a/modules/gui/src/python_shell/gutter.cc b/modules/gui/src/python_shell/gutter.cc index fa9522184..e60b4c4d6 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 e86b3804f..0d3f1e641 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 c6f16ba6a..1d2d75591 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 1049b3b80..11126baad 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 2c398dfbd..142870da4 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); -- GitLab