diff --git a/NEWS.md b/NEWS.md index e54adeeb..56318f2d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.7.6 + - change: don't auto insert a new line when input an enter between '(' and ')' or between '[' and ']' (indent instead) + - enhancement: the line containing '}' will use the indents of the matching '{' line, instead of just unindent one level + Version 0.7.5 - enhancement: more accurate auto indent calculation - change: remove "add indent" option in the editor general options widget ( It's merged with "auto indent" option) diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 184e0908..b6fc104a 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -1100,7 +1100,37 @@ void SynEdit::clearUndo() mRedoList->Clear(); } -BufferCoord SynEdit::getPreviousLeftBracket(int x, int y) +int SynEdit::findIndentsStartLine(int line, QVector indents) +{ + line--; + if (line<0 || line>=mLines->count()) + return -1; + while (line>=1) { + SynRangeState range = mLines->ranges(line); + QVector newIndents = range.indents.mid(range.firstIndentThisLine); + int i = 0; + int len = indents.length(); + while (i=0) { + newIndents.remove(idx,newIndents.size()); + } else { + break; + } + i++; + } + if (i>=len) { + return line+1; + } else { + indents = range.matchingIndents + indents.mid(i); + } + line--; + } + return -1; +} + +BufferCoord SynEdit::getPreviousLeftBrace(int x, int y) { QChar Test; QString vDummy; @@ -1386,20 +1416,55 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent) indentSpaces = leftSpaces(s); if (addIndent) { SynRangeState rangePreceeding = mLines->ranges(startLine-1); - if (!rangePreceeding.matchingIndents.isEmpty()) { + mHighlighter->setState(rangePreceeding); + mHighlighter->setLine(lineText.trimmed(),line-1); + SynRangeState rangeAfterFirstToken = mHighlighter->getRangeState(); + QString firstToken = mHighlighter->getToken(); + PSynHighlighterAttribute attr = mHighlighter->getTokenAttribute(); + if (attr == mHighlighter->keywordAttribute() + && lineText.endsWith(':') + && ( + firstToken == "public" || firstToken == "private" + || firstToken == "protected" || firstToken == "case")) { + mHighlighter->setState(rangePreceeding); + mHighlighter->setLine("}",line-1); + rangeAfterFirstToken = mHighlighter->getRangeState(); + firstToken = mHighlighter->getToken(); + attr = mHighlighter->getTokenAttribute(); + } + bool dontAddIndent = false; + QVector matchingIndents; + int l; + if (attr == mHighlighter->symbolAttribute() + && firstToken == '}' ) { + matchingIndents = rangeAfterFirstToken.matchingIndents; + dontAddIndent = true; + l = startLine; + } else { + matchingIndents = rangePreceeding.matchingIndents; + l = startLine-1; + } + + if (!matchingIndents.isEmpty() + ) { // find the indent's start line, and use it's indent as the default indent; - QString matchingIndents = rangePreceeding.matchingIndents; - int l = startLine-1; while (l>=1) { SynRangeState range = mLines->ranges(l-1); - QString newIndents = range.indents.mid(range.firstIndentThisLine); + QVector newIndents = range.indents.mid(range.firstIndentThisLine); int i = 0; int len = matchingIndents.length(); while (i= sitStatemntBrace) { + int counts = indent - sitStatemntBrace; + for (int j=0;j=0) { - newIndents.truncate(idx); + newIndents.remove(idx,newIndents.length()-idx); } else { break; } @@ -1407,8 +1472,8 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent) } if (i>=len) { indentSpaces = leftSpaces(mLines->getString(l-1)); - if (newIndents.length()>0) - indentSpaces+=mTabWidth; +// if (newIndents.length()>0) +// indentSpaces+=mTabWidth; break; } else { matchingIndents = range.matchingIndents + matchingIndents.mid(i); @@ -1416,28 +1481,13 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent) l--; } } - if ((rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) // there are indents added at this (preceeding) line - || (s.trimmed().endsWith(':')) + if (!dontAddIndent && + ( + (rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) // there are indents added at this (preceeding) line + || s.trimmed().endsWith(':')) ) { indentSpaces += mTabWidth; } - mHighlighter->setState(rangePreceeding); - mHighlighter->setLine(lineText.trimmed(),line-1); - SynRangeState rangeAfterFirstToken = mHighlighter->getRangeState(); - QString firstToken = mHighlighter->getToken(); - PSynHighlighterAttribute attr = mHighlighter->getTokenAttribute(); - if (rangeAfterFirstToken.indents.length() < rangePreceeding.indents.length()) { - indentSpaces -= mTabWidth; - } else if (rangeAfterFirstToken.getLastIndent() == BraceIndentType - && rangePreceeding.getLastIndent() == StatementIndentType) { - indentSpaces -= mTabWidth; - } else if (attr == mHighlighter->keywordAttribute() - && lineText.endsWith(':') - && ( - firstToken == "public" || firstToken == "private" - || firstToken == "protected" || firstToken == "case")) { - indentSpaces -= mTabWidth; - } } } return std::max(0,indentSpaces); @@ -2002,10 +2052,8 @@ void SynEdit::insertLine(bool moveCaret) SynSelectionMode::smNormal); //insert new line in middle of "{" and "}" if (notInComment && - ( (leftLineText.endsWith('{') && rightLineText.startsWith('}')) - || (leftLineText.endsWith('(') && rightLineText.startsWith(')')) - || (leftLineText.endsWith('[') && rightLineText.startsWith(')')) - )) { + ( leftLineText.endsWith('{') && rightLineText.startsWith('}') + )) { indentSpaces = calcIndentSpaces(mCaretY+1, "" , mOptions.testFlag(eoAutoIndent) && notInComment); indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true); diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index d573887f..f4301d05 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -513,7 +513,8 @@ private: void processGutterClick(QMouseEvent* event); void clearUndo(); - BufferCoord getPreviousLeftBracket(int x,int y); + int findIndentsStartLine(int line, QVector indents); + BufferCoord getPreviousLeftBrace(int x,int y); bool canDoBlockIndent(); QRect calculateCaretRect(); diff --git a/RedPandaIDE/qsynedit/highlighter/base.cpp b/RedPandaIDE/qsynedit/highlighter/base.cpp index a57b370c..340cd3ba 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.cpp +++ b/RedPandaIDE/qsynedit/highlighter/base.cpp @@ -218,9 +218,9 @@ bool SynRangeState::operator==(const SynRangeState &s2) ; } -QChar SynRangeState::getLastIndent() +int SynRangeState::getLastIndent() { if (indents.isEmpty()) - return QChar(); + return -1; return indents.back(); } diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h index 22e7312b..f8ccd6d9 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.h +++ b/RedPandaIDE/qsynedit/highlighter/base.h @@ -10,10 +10,13 @@ #include #include "../Types.h" -constexpr QChar BraceIndentType('{'); -constexpr QChar ParenthesisIndentType('('); -constexpr QChar BracketIndentType('['); -constexpr QChar StatementIndentType('S'); +enum SynIndentType { + sitBrace = 0, + sitParenthesis = 1, + sitBracket = 2, + sitStatement = 3, + sitStatemntBrace = 100 +}; struct SynRangeState { int state; // current syntax parsing state @@ -23,14 +26,14 @@ struct SynRangeState { int parenthesisLevel; // current parenthesis embedding level (needed by rainbow color) int leftBraces; // unpairing left braces in the current line ( needed by block folding) int rightBraces; // unparing right braces in the current line (needed by block folding) - QString indents; // indents stack (each char represents an indent) (needed by auto indent) + QVector indents; // indents stack (needed by auto indent) int firstIndentThisLine; /* index of first indent that appended to the indents * stack at this line ( need by auto indent) */ - QString matchingIndents; /* the indent matched ( and removed ) + QVector matchingIndents; /* the indent matched ( and removed ) but not started at this line (need by auto indent) */ bool operator==(const SynRangeState& s2); - QChar getLastIndent(); + int getLastIndent(); }; typedef int SynTokenKind; diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.cpp b/RedPandaIDE/qsynedit/highlighter/cpp.cpp index 32f15d4c..349c9987 100644 --- a/RedPandaIDE/qsynedit/highlighter/cpp.cpp +++ b/RedPandaIDE/qsynedit/highlighter/cpp.cpp @@ -376,7 +376,7 @@ void SynEditCppHighlighter::braceCloseProc() } else { mRange.rightBraces++ ; } - popIndents(BraceIndentType); + popIndents(sitBrace); } void SynEditCppHighlighter::braceOpenProc() @@ -390,18 +390,18 @@ void SynEditCppHighlighter::braceOpenProc() } mRange.braceLevel += 1; mRange.leftBraces++; - if (mRange.getLastIndent() == StatementIndentType) { + if (mRange.getLastIndent() == sitStatement) { // if last indent is started by 'if' 'for' etc // just replace it - popIndents(StatementIndentType); - pushIndents(BraceIndentType); + int counts = popStatementIndents(); + pushIndents(sitStatemntBrace+counts); // int idx = mRange.indents.length()-1; // if (idx < mRange.firstIndentThisLine) { // mRange.firstIndentThisLine = idx; // } // mRange.indents.replace(idx,1,BraceIndentType); } else { - pushIndents(BraceIndentType); + pushIndents(sitBrace); } } @@ -545,7 +545,7 @@ void SynEditCppHighlighter::identProc() if (isKeyword(word)) { mTokenId = TokenKind::Key; if (StatementKeyWords.contains(word)) { - pushIndents(StatementIndentType); + pushIndents(sitStatement); } } else { mTokenId = TokenKind::Identifier; @@ -907,7 +907,7 @@ void SynEditCppHighlighter::roundCloseProc() mTokenId = TokenKind::Symbol; mExtTokenId = ExtTokenKind::RoundClose; mRange.parenthesisLevel--; - popIndents(ParenthesisIndentType); + popIndents(sitParenthesis); } void SynEditCppHighlighter::roundOpenProc() @@ -916,7 +916,7 @@ void SynEditCppHighlighter::roundOpenProc() mTokenId = TokenKind::Symbol; mExtTokenId = ExtTokenKind::RoundOpen; mRange.parenthesisLevel++; - pushIndents(ParenthesisIndentType); + pushIndents(sitParenthesis); } void SynEditCppHighlighter::semiColonProc() @@ -926,8 +926,8 @@ void SynEditCppHighlighter::semiColonProc() mExtTokenId = ExtTokenKind::SemiColon; if (mRange.state == RangeState::rsAsm) mRange.state = RangeState::rsUnknown; - if (mRange.getLastIndent() == StatementIndentType) { - popIndents(StatementIndentType); + if (mRange.getLastIndent() == sitStatement) { + popIndents(sitStatement); } } @@ -982,7 +982,7 @@ void SynEditCppHighlighter::squareCloseProc() mTokenId = TokenKind::Symbol; mExtTokenId = ExtTokenKind::SquareClose; mRange.bracketLevel--; - popIndents(BracketIndentType); + popIndents(sitBracket); } void SynEditCppHighlighter::squareOpenProc() @@ -991,7 +991,7 @@ void SynEditCppHighlighter::squareOpenProc() mTokenId = TokenKind::Symbol; mExtTokenId = ExtTokenKind::SquareOpen; mRange.bracketLevel++; - pushIndents(BracketIndentType); + pushIndents(sitBracket); } void SynEditCppHighlighter::starProc() @@ -1355,26 +1355,42 @@ void SynEditCppHighlighter::processChar() } } -void SynEditCppHighlighter::popIndents(QChar indentType) +void SynEditCppHighlighter::popIndents(int indentType) { while (!mRange.indents.isEmpty() && mRange.indents.back()!=indentType) { - mRange.indents.remove(mRange.indents.length()-1,1); + if (indentType == sitBrace && mRange.indents.back() >= sitStatemntBrace) + break; + mRange.indents.pop_back(); } if (!mRange.indents.isEmpty()) { int idx = mRange.indents.length()-1; if (idx < mRange.firstIndentThisLine) { mRange.matchingIndents.append(mRange.indents[idx]); } - mRange.indents.remove(idx,1); + mRange.indents.pop_back(); } } -void SynEditCppHighlighter::pushIndents(QChar indentType) +int SynEditCppHighlighter::popStatementIndents() +{ + int counts = 0; + while (!mRange.indents.isEmpty() && mRange.indents.back() == sitStatement) { + int idx = mRange.indents.length()-1; + if (idx < mRange.firstIndentThisLine) { +// mRange.matchingIndents.append(mRange.indents[idx]); + counts++; + } + mRange.indents.pop_back(); + } + return counts; +} + +void SynEditCppHighlighter::pushIndents(int indentType) { int idx = mRange.indents.length(); if (idx