- 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
This commit is contained in:
royqh1979 2021-10-30 18:28:40 +08:00
parent af03c417ec
commit 44cf39d8ca
7 changed files with 138 additions and 65 deletions

View File

@ -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 Version 0.7.5
- enhancement: more accurate auto indent calculation - enhancement: more accurate auto indent calculation
- change: remove "add indent" option in the editor general options widget ( It's merged with "auto indent" option) - change: remove "add indent" option in the editor general options widget ( It's merged with "auto indent" option)

View File

@ -1100,7 +1100,37 @@ void SynEdit::clearUndo()
mRedoList->Clear(); mRedoList->Clear();
} }
BufferCoord SynEdit::getPreviousLeftBracket(int x, int y) int SynEdit::findIndentsStartLine(int line, QVector<int> indents)
{
line--;
if (line<0 || line>=mLines->count())
return -1;
while (line>=1) {
SynRangeState range = mLines->ranges(line);
QVector<int> newIndents = range.indents.mid(range.firstIndentThisLine);
int i = 0;
int len = indents.length();
while (i<len && !newIndents.isEmpty()) {
int indent = indents[i];
int idx = newIndents.lastIndexOf(indent);
if (idx >=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; QChar Test;
QString vDummy; QString vDummy;
@ -1386,20 +1416,55 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
indentSpaces = leftSpaces(s); indentSpaces = leftSpaces(s);
if (addIndent) { if (addIndent) {
SynRangeState rangePreceeding = mLines->ranges(startLine-1); 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<int> 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; // 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) { while (l>=1) {
SynRangeState range = mLines->ranges(l-1); SynRangeState range = mLines->ranges(l-1);
QString newIndents = range.indents.mid(range.firstIndentThisLine); QVector<int> newIndents = range.indents.mid(range.firstIndentThisLine);
int i = 0; int i = 0;
int len = matchingIndents.length(); int len = matchingIndents.length();
while (i<len && !newIndents.isEmpty()) { while (i<len && !newIndents.isEmpty()) {
QChar indent = matchingIndents[i]; int indent = matchingIndents[i];
if (indent >= sitStatemntBrace) {
int counts = indent - sitStatemntBrace;
for (int j=0;j<counts;j++) {
matchingIndents.insert(i+1,sitStatement);
}
len = matchingIndents.length();
}
int idx = newIndents.lastIndexOf(indent); int idx = newIndents.lastIndexOf(indent);
if (idx >=0) { if (idx >=0) {
newIndents.truncate(idx); newIndents.remove(idx,newIndents.length()-idx);
} else { } else {
break; break;
} }
@ -1407,8 +1472,8 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
} }
if (i>=len) { if (i>=len) {
indentSpaces = leftSpaces(mLines->getString(l-1)); indentSpaces = leftSpaces(mLines->getString(l-1));
if (newIndents.length()>0) // if (newIndents.length()>0)
indentSpaces+=mTabWidth; // indentSpaces+=mTabWidth;
break; break;
} else { } else {
matchingIndents = range.matchingIndents + matchingIndents.mid(i); matchingIndents = range.matchingIndents + matchingIndents.mid(i);
@ -1416,28 +1481,13 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
l--; l--;
} }
} }
if ((rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) // there are indents added at this (preceeding) line if (!dontAddIndent &&
|| (s.trimmed().endsWith(':')) (
(rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) // there are indents added at this (preceeding) line
|| s.trimmed().endsWith(':'))
) { ) {
indentSpaces += mTabWidth; 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); return std::max(0,indentSpaces);
@ -2002,10 +2052,8 @@ void SynEdit::insertLine(bool moveCaret)
SynSelectionMode::smNormal); SynSelectionMode::smNormal);
//insert new line in middle of "{" and "}" //insert new line in middle of "{" and "}"
if (notInComment && 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) indentSpaces = calcIndentSpaces(mCaretY+1, "" , mOptions.testFlag(eoAutoIndent)
&& notInComment); && notInComment);
indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true); indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true);

View File

@ -513,7 +513,8 @@ private:
void processGutterClick(QMouseEvent* event); void processGutterClick(QMouseEvent* event);
void clearUndo(); void clearUndo();
BufferCoord getPreviousLeftBracket(int x,int y); int findIndentsStartLine(int line, QVector<int> indents);
BufferCoord getPreviousLeftBrace(int x,int y);
bool canDoBlockIndent(); bool canDoBlockIndent();
QRect calculateCaretRect(); QRect calculateCaretRect();

View File

@ -218,9 +218,9 @@ bool SynRangeState::operator==(const SynRangeState &s2)
; ;
} }
QChar SynRangeState::getLastIndent() int SynRangeState::getLastIndent()
{ {
if (indents.isEmpty()) if (indents.isEmpty())
return QChar(); return -1;
return indents.back(); return indents.back();
} }

View File

@ -10,10 +10,13 @@
#include <QVector> #include <QVector>
#include "../Types.h" #include "../Types.h"
constexpr QChar BraceIndentType('{'); enum SynIndentType {
constexpr QChar ParenthesisIndentType('('); sitBrace = 0,
constexpr QChar BracketIndentType('['); sitParenthesis = 1,
constexpr QChar StatementIndentType('S'); sitBracket = 2,
sitStatement = 3,
sitStatemntBrace = 100
};
struct SynRangeState { struct SynRangeState {
int state; // current syntax parsing state int state; // current syntax parsing state
@ -23,14 +26,14 @@ struct SynRangeState {
int parenthesisLevel; // current parenthesis embedding level (needed by rainbow color) int parenthesisLevel; // current parenthesis embedding level (needed by rainbow color)
int leftBraces; // unpairing left braces in the current line ( needed by block folding) 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) 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<int> indents; // indents stack (needed by auto indent)
int firstIndentThisLine; /* index of first indent that appended to the indents int firstIndentThisLine; /* index of first indent that appended to the indents
* stack at this line ( need by auto indent) */ * stack at this line ( need by auto indent) */
QString matchingIndents; /* the indent matched ( and removed ) QVector<int> matchingIndents; /* the indent matched ( and removed )
but not started at this line but not started at this line
(need by auto indent) */ (need by auto indent) */
bool operator==(const SynRangeState& s2); bool operator==(const SynRangeState& s2);
QChar getLastIndent(); int getLastIndent();
}; };
typedef int SynTokenKind; typedef int SynTokenKind;

View File

@ -376,7 +376,7 @@ void SynEditCppHighlighter::braceCloseProc()
} else { } else {
mRange.rightBraces++ ; mRange.rightBraces++ ;
} }
popIndents(BraceIndentType); popIndents(sitBrace);
} }
void SynEditCppHighlighter::braceOpenProc() void SynEditCppHighlighter::braceOpenProc()
@ -390,18 +390,18 @@ void SynEditCppHighlighter::braceOpenProc()
} }
mRange.braceLevel += 1; mRange.braceLevel += 1;
mRange.leftBraces++; mRange.leftBraces++;
if (mRange.getLastIndent() == StatementIndentType) { if (mRange.getLastIndent() == sitStatement) {
// if last indent is started by 'if' 'for' etc // if last indent is started by 'if' 'for' etc
// just replace it // just replace it
popIndents(StatementIndentType); int counts = popStatementIndents();
pushIndents(BraceIndentType); pushIndents(sitStatemntBrace+counts);
// int idx = mRange.indents.length()-1; // int idx = mRange.indents.length()-1;
// if (idx < mRange.firstIndentThisLine) { // if (idx < mRange.firstIndentThisLine) {
// mRange.firstIndentThisLine = idx; // mRange.firstIndentThisLine = idx;
// } // }
// mRange.indents.replace(idx,1,BraceIndentType); // mRange.indents.replace(idx,1,BraceIndentType);
} else { } else {
pushIndents(BraceIndentType); pushIndents(sitBrace);
} }
} }
@ -545,7 +545,7 @@ void SynEditCppHighlighter::identProc()
if (isKeyword(word)) { if (isKeyword(word)) {
mTokenId = TokenKind::Key; mTokenId = TokenKind::Key;
if (StatementKeyWords.contains(word)) { if (StatementKeyWords.contains(word)) {
pushIndents(StatementIndentType); pushIndents(sitStatement);
} }
} else { } else {
mTokenId = TokenKind::Identifier; mTokenId = TokenKind::Identifier;
@ -907,7 +907,7 @@ void SynEditCppHighlighter::roundCloseProc()
mTokenId = TokenKind::Symbol; mTokenId = TokenKind::Symbol;
mExtTokenId = ExtTokenKind::RoundClose; mExtTokenId = ExtTokenKind::RoundClose;
mRange.parenthesisLevel--; mRange.parenthesisLevel--;
popIndents(ParenthesisIndentType); popIndents(sitParenthesis);
} }
void SynEditCppHighlighter::roundOpenProc() void SynEditCppHighlighter::roundOpenProc()
@ -916,7 +916,7 @@ void SynEditCppHighlighter::roundOpenProc()
mTokenId = TokenKind::Symbol; mTokenId = TokenKind::Symbol;
mExtTokenId = ExtTokenKind::RoundOpen; mExtTokenId = ExtTokenKind::RoundOpen;
mRange.parenthesisLevel++; mRange.parenthesisLevel++;
pushIndents(ParenthesisIndentType); pushIndents(sitParenthesis);
} }
void SynEditCppHighlighter::semiColonProc() void SynEditCppHighlighter::semiColonProc()
@ -926,8 +926,8 @@ void SynEditCppHighlighter::semiColonProc()
mExtTokenId = ExtTokenKind::SemiColon; mExtTokenId = ExtTokenKind::SemiColon;
if (mRange.state == RangeState::rsAsm) if (mRange.state == RangeState::rsAsm)
mRange.state = RangeState::rsUnknown; mRange.state = RangeState::rsUnknown;
if (mRange.getLastIndent() == StatementIndentType) { if (mRange.getLastIndent() == sitStatement) {
popIndents(StatementIndentType); popIndents(sitStatement);
} }
} }
@ -982,7 +982,7 @@ void SynEditCppHighlighter::squareCloseProc()
mTokenId = TokenKind::Symbol; mTokenId = TokenKind::Symbol;
mExtTokenId = ExtTokenKind::SquareClose; mExtTokenId = ExtTokenKind::SquareClose;
mRange.bracketLevel--; mRange.bracketLevel--;
popIndents(BracketIndentType); popIndents(sitBracket);
} }
void SynEditCppHighlighter::squareOpenProc() void SynEditCppHighlighter::squareOpenProc()
@ -991,7 +991,7 @@ void SynEditCppHighlighter::squareOpenProc()
mTokenId = TokenKind::Symbol; mTokenId = TokenKind::Symbol;
mExtTokenId = ExtTokenKind::SquareOpen; mExtTokenId = ExtTokenKind::SquareOpen;
mRange.bracketLevel++; mRange.bracketLevel++;
pushIndents(BracketIndentType); pushIndents(sitBracket);
} }
void SynEditCppHighlighter::starProc() 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) { 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()) { if (!mRange.indents.isEmpty()) {
int idx = mRange.indents.length()-1; int idx = mRange.indents.length()-1;
if (idx < mRange.firstIndentThisLine) { if (idx < mRange.firstIndentThisLine) {
mRange.matchingIndents.append(mRange.indents[idx]); 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(); int idx = mRange.indents.length();
if (idx<mRange.firstIndentThisLine) if (idx<mRange.firstIndentThisLine)
mRange.firstIndentThisLine = idx; mRange.firstIndentThisLine = idx;
mRange.indents.append(indentType); mRange.indents.push_back(indentType);
} }
bool SynEditCppHighlighter::getTokenFinished() const bool SynEditCppHighlighter::getTokenFinished() const
@ -1532,7 +1548,7 @@ void SynEditCppHighlighter::setLine(const QString &newLine, int lineNumber)
mRange.leftBraces = 0; mRange.leftBraces = 0;
mRange.rightBraces = 0; mRange.rightBraces = 0;
mRange.firstIndentThisLine = mRange.indents.length(); mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents = ""; mRange.matchingIndents.clear();
next(); next();
} }
@ -1600,7 +1616,7 @@ void SynEditCppHighlighter::setState(const SynRangeState& rangeState)
mRange.leftBraces = 0; mRange.leftBraces = 0;
mRange.rightBraces = 0; mRange.rightBraces = 0;
mRange.firstIndentThisLine = mRange.indents.length(); mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents = ""; mRange.matchingIndents.clear();
} }
void SynEditCppHighlighter::resetState() void SynEditCppHighlighter::resetState()
@ -1612,9 +1628,9 @@ void SynEditCppHighlighter::resetState()
mRange.parenthesisLevel = 0; mRange.parenthesisLevel = 0;
mRange.leftBraces = 0; mRange.leftBraces = 0;
mRange.rightBraces = 0; mRange.rightBraces = 0;
mRange.indents = ""; mRange.indents.clear();
mRange.firstIndentThisLine = 0; mRange.firstIndentThisLine = 0;
mRange.matchingIndents = ""; mRange.matchingIndents.clear();
mAsmStart = false; mAsmStart = false;
} }

View File

@ -125,8 +125,9 @@ private:
void unknownProc(); void unknownProc();
void xorSymbolProc(); void xorSymbolProc();
void processChar(); void processChar();
void popIndents(QChar indentType); void popIndents(int indentType);
void pushIndents(QChar indentType); int popStatementIndents();
void pushIndents(int indentType);
private: private:
bool mAsmStart; bool mAsmStart;