- enhancement: more accurate auto indent calculation
This commit is contained in:
parent
19e7143efc
commit
5aa91e1bc1
|
@ -1371,8 +1371,8 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
|
|||
line = std::min(line, mLines->count()+1);
|
||||
if (line<=1)
|
||||
return 0;
|
||||
// find the first non-empty preceeding line
|
||||
int startLine = line-1;
|
||||
int indentSpaces = 0;
|
||||
QString s;
|
||||
while (startLine>=1) {
|
||||
s = mLines->getString(startLine-1);
|
||||
|
@ -1381,25 +1381,37 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
|
|||
}
|
||||
startLine -- ;
|
||||
}
|
||||
int indentSpaces = 0;
|
||||
if (startLine>=1) {
|
||||
indentSpaces = leftSpaces(s);
|
||||
if (addIndent) {
|
||||
SynRangeState range = mLines->ranges(startLine-1);
|
||||
if ((!range.indentStartLines.isEmpty()
|
||||
&& range.indentStartLines.back() == startLine-1)
|
||||
SynRangeState rangePreceeding = mLines->ranges(startLine-1);
|
||||
if (!rangePreceeding.lastMatchingIndent.isNull()) {
|
||||
// find the indent's start line, and use it's indent as the default indent;
|
||||
int l = startLine-1;
|
||||
while (l>=1) {
|
||||
SynRangeState range = mLines->ranges(l-1);
|
||||
if (range.indents.mid(range.firstIndentThisLine).contains(rangePreceeding.lastMatchingIndent)) {
|
||||
indentSpaces = leftSpaces(mLines->getString(l-1));
|
||||
break;
|
||||
}
|
||||
l--;
|
||||
}
|
||||
}
|
||||
if ((rangePreceeding.firstIndentThisLine < rangePreceeding.indents.length()) // there are indents added at this (preceeding) line
|
||||
|| (s.trimmed().endsWith(':'))
|
||||
) {
|
||||
indentSpaces += mTabWidth;
|
||||
}
|
||||
mHighlighter->setState(range);
|
||||
mHighlighter->setLine(lineText,line-1);
|
||||
mHighlighter->nextToEol();
|
||||
SynRangeState newRange = mHighlighter->getRangeState();
|
||||
while (!newRange.indentStartLines.isEmpty() && newRange.indentStartLines.back()==line-1) {
|
||||
newRange.indentStartLines.pop_back();
|
||||
}
|
||||
if (newRange.indentStartLines.length() < range.indentStartLines.length())
|
||||
mHighlighter->setState(rangePreceeding);
|
||||
mHighlighter->setLine(lineText.trimmed(),line-1);
|
||||
SynRangeState rangeAfterFirstToken = mHighlighter->getRangeState();
|
||||
if (rangeAfterFirstToken.indents.length() < rangePreceeding.indents.length()) {
|
||||
indentSpaces -= mTabWidth;
|
||||
} else if (rangeAfterFirstToken.getLastIndent() == BraceIndentType
|
||||
&& rangePreceeding.getLastIndent() == StatementIndentType) {
|
||||
indentSpaces -= mTabWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::max(0,indentSpaces);
|
||||
|
|
|
@ -211,17 +211,16 @@ SynHighlighterAttribute::SynHighlighterAttribute(const QString &name):
|
|||
|
||||
bool SynRangeState::operator==(const SynRangeState &s2)
|
||||
{
|
||||
// indents contains the information of brace/parenthesis/brackets embedded levels
|
||||
return (state == s2.state)
|
||||
&& (spaceState == s2.spaceState)
|
||||
&& (braceLevel == s2.braceLevel)
|
||||
&& (bracketLevel == s2.bracketLevel)
|
||||
&& (parenthesisLevel == s2.parenthesisLevel)
|
||||
&& (leftBraces == s2.leftBraces)
|
||||
&& (leftParenthesis = s2.leftParenthesis)
|
||||
&& (leftBrackets == s2.leftBrackets)
|
||||
&& (rightBraces == s2.rightBraces)
|
||||
&& (rightParenthesis = s2.rightParenthesis)
|
||||
&& (rightBrackets == s2.rightBrackets)
|
||||
&& (indents == s2.indents)
|
||||
;
|
||||
}
|
||||
|
||||
QChar SynRangeState::getLastIndent()
|
||||
{
|
||||
if (indents.isEmpty())
|
||||
return QChar();
|
||||
return indents.back();
|
||||
}
|
||||
|
|
|
@ -13,23 +13,24 @@
|
|||
constexpr QChar BraceIndentType('{');
|
||||
constexpr QChar ParenthesisIndentType('(');
|
||||
constexpr QChar BracketIndentType('[');
|
||||
constexpr QChar StatementIndentType('K');
|
||||
constexpr QChar StatementIndentType('S');
|
||||
|
||||
struct SynRangeState {
|
||||
int state;
|
||||
int spaceState;
|
||||
int braceLevel;
|
||||
int bracketLevel;
|
||||
int parenthesisLevel;
|
||||
int leftBraces;
|
||||
int rightBraces;
|
||||
int leftBrackets;
|
||||
int rightBrackets;
|
||||
int leftParenthesis;
|
||||
int rightParenthesis;
|
||||
QString indents;
|
||||
QVector<int> indentStartLines;
|
||||
int state; // current syntax parsing state
|
||||
int spaceState; // the last syntax parsing state before meeting space
|
||||
int braceLevel; // current braces embedding level (needed by rainbow color)
|
||||
int bracketLevel; // current brackets 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 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)
|
||||
int firstIndentThisLine; /* index of first indent that appended to the indents
|
||||
* stack at this line ( need by auto indent) */
|
||||
QChar lastMatchingIndent; /* the last indent matched ( and removed )
|
||||
but not started at this line
|
||||
(need by auto indent) */
|
||||
bool operator==(const SynRangeState& s2);
|
||||
QChar getLastIndent();
|
||||
};
|
||||
|
||||
typedef int SynTokenKind;
|
||||
|
|
|
@ -375,7 +375,7 @@ void SynEditCppHighlighter::braceCloseProc()
|
|||
} else {
|
||||
mRange.rightBraces++ ;
|
||||
}
|
||||
popIndentsByType(BraceIndentType);
|
||||
popIndents(BraceIndentType);
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::braceOpenProc()
|
||||
|
@ -392,11 +392,15 @@ void SynEditCppHighlighter::braceOpenProc()
|
|||
if (!mRange.indents.isEmpty() && mRange.indents.back() == StatementIndentType) {
|
||||
// if last indent is started by 'if' 'for' etc
|
||||
// just replace it
|
||||
mRange.indents.replace(mRange.indents.length()-1,1,BraceIndentType);
|
||||
mRange.indentStartLines.replace(mRange.indents.length()-1,mLineNumber);
|
||||
popIndents(StatementIndentType);
|
||||
pushIndents(BraceIndentType);
|
||||
// int idx = mRange.indents.length()-1;
|
||||
// if (idx < mRange.firstIndentThisLine) {
|
||||
// mRange.firstIndentThisLine = idx;
|
||||
// }
|
||||
// mRange.indents.replace(idx,1,BraceIndentType);
|
||||
} else {
|
||||
mRange.indents.append(BraceIndentType);
|
||||
mRange.indentStartLines.append(mLineNumber);
|
||||
pushIndents(BraceIndentType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,8 +544,7 @@ void SynEditCppHighlighter::identProc()
|
|||
if (isKeyword(word)) {
|
||||
mTokenId = TokenKind::Key;
|
||||
if (StatementKeyWords.contains(word)) {
|
||||
mRange.indents.append(StatementIndentType);
|
||||
mRange.indentStartLines.append(mLineNumber);
|
||||
pushIndents(StatementIndentType);
|
||||
}
|
||||
} else {
|
||||
mTokenId = TokenKind::Identifier;
|
||||
|
@ -903,12 +906,7 @@ void SynEditCppHighlighter::roundCloseProc()
|
|||
mTokenId = TokenKind::Symbol;
|
||||
mExtTokenId = ExtTokenKind::RoundClose;
|
||||
mRange.parenthesisLevel--;
|
||||
if (mRange.leftParenthesis>0) {
|
||||
mRange.leftParenthesis--;
|
||||
} else {
|
||||
mRange.rightParenthesis++ ;
|
||||
}
|
||||
popIndentsByType(ParenthesisIndentType);
|
||||
popIndents(ParenthesisIndentType);
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::roundOpenProc()
|
||||
|
@ -917,9 +915,7 @@ void SynEditCppHighlighter::roundOpenProc()
|
|||
mTokenId = TokenKind::Symbol;
|
||||
mExtTokenId = ExtTokenKind::RoundOpen;
|
||||
mRange.parenthesisLevel++;
|
||||
mRange.leftParenthesis++;
|
||||
mRange.indents.append(ParenthesisIndentType);
|
||||
mRange.indentStartLines.append(mLineNumber);
|
||||
pushIndents(ParenthesisIndentType);
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::semiColonProc()
|
||||
|
@ -930,8 +926,7 @@ void SynEditCppHighlighter::semiColonProc()
|
|||
if (mRange.state == RangeState::rsAsm)
|
||||
mRange.state = RangeState::rsUnknown;
|
||||
if (mRange.indents.back() == StatementIndentType) {
|
||||
mRange.indents.remove(mRange.indents.length()-1,1);
|
||||
mRange.indentStartLines.pop_back();
|
||||
popIndents(StatementIndentType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,12 +981,7 @@ void SynEditCppHighlighter::squareCloseProc()
|
|||
mTokenId = TokenKind::Symbol;
|
||||
mExtTokenId = ExtTokenKind::SquareClose;
|
||||
mRange.bracketLevel--;
|
||||
if (mRange.leftBrackets>0) {
|
||||
mRange.leftBrackets--;
|
||||
} else {
|
||||
mRange.rightBrackets++ ;
|
||||
}
|
||||
popIndentsByType(BracketIndentType);
|
||||
popIndents(BracketIndentType);
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::squareOpenProc()
|
||||
|
@ -1000,9 +990,7 @@ void SynEditCppHighlighter::squareOpenProc()
|
|||
mTokenId = TokenKind::Symbol;
|
||||
mExtTokenId = ExtTokenKind::SquareOpen;
|
||||
mRange.bracketLevel++;
|
||||
mRange.leftBrackets++;
|
||||
mRange.indents.append(BracketIndentType);
|
||||
mRange.indentStartLines.append(mLineNumber);
|
||||
pushIndents(BracketIndentType);
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::starProc()
|
||||
|
@ -1366,17 +1354,26 @@ void SynEditCppHighlighter::processChar()
|
|||
}
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::popIndentsByType(QChar indentType)
|
||||
void SynEditCppHighlighter::popIndents(QChar indentType)
|
||||
{
|
||||
while (!mRange.indents.isEmpty() && mRange.indents.back()!=indentType) {
|
||||
mRange.indents.remove(mRange.indents.length()-1,1);
|
||||
mRange.indentStartLines.pop_back();
|
||||
}
|
||||
if (!mRange.indents.isEmpty()) {
|
||||
mRange.indents.remove(mRange.indents.length()-1,1);
|
||||
mRange.indentStartLines.pop_back();
|
||||
int idx = mRange.indents.length()-1;
|
||||
if (idx < mRange.firstIndentThisLine) {
|
||||
mRange.lastMatchingIndent = mRange.indents[idx];
|
||||
}
|
||||
mRange.indents.remove(idx,1);
|
||||
}
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::pushIndents(QChar indentType)
|
||||
{
|
||||
int idx = mRange.indents.length();
|
||||
if (idx<mRange.firstIndentThisLine)
|
||||
mRange.firstIndentThisLine = idx;
|
||||
mRange.indents.append(indentType);
|
||||
}
|
||||
|
||||
bool SynEditCppHighlighter::getTokenFinished() const
|
||||
|
@ -1532,11 +1529,9 @@ void SynEditCppHighlighter::setLine(const QString &newLine, int lineNumber)
|
|||
mLineNumber = lineNumber;
|
||||
mRun = 0;
|
||||
mRange.leftBraces = 0;
|
||||
mRange.leftBrackets = 0;
|
||||
mRange.leftParenthesis = 0;
|
||||
mRange.rightBraces = 0;
|
||||
mRange.rightBrackets = 0;
|
||||
mRange.rightParenthesis = 0;
|
||||
mRange.firstIndentThisLine = mRange.indents.length();
|
||||
mRange.lastMatchingIndent = QChar();
|
||||
next();
|
||||
}
|
||||
|
||||
|
@ -1602,11 +1597,9 @@ void SynEditCppHighlighter::setState(const SynRangeState& rangeState)
|
|||
mRange = rangeState;
|
||||
// current line's left / right parenthesis count should be reset before parsing each line
|
||||
mRange.leftBraces = 0;
|
||||
mRange.leftBrackets = 0;
|
||||
mRange.leftParenthesis = 0;
|
||||
mRange.rightBraces = 0;
|
||||
mRange.rightBrackets = 0;
|
||||
mRange.rightParenthesis = 0;
|
||||
mRange.firstIndentThisLine = mRange.indents.length();
|
||||
mRange.lastMatchingIndent = QChar();
|
||||
}
|
||||
|
||||
void SynEditCppHighlighter::resetState()
|
||||
|
@ -1617,13 +1610,10 @@ void SynEditCppHighlighter::resetState()
|
|||
mRange.bracketLevel = 0;
|
||||
mRange.parenthesisLevel = 0;
|
||||
mRange.leftBraces = 0;
|
||||
mRange.leftBrackets = 0;
|
||||
mRange.leftParenthesis = 0;
|
||||
mRange.rightBraces = 0;
|
||||
mRange.rightBrackets = 0;
|
||||
mRange.rightParenthesis = 0;
|
||||
mRange.indents = "";
|
||||
mRange.indentStartLines.clear();
|
||||
mRange.firstIndentThisLine = 0;
|
||||
mRange.lastMatchingIndent = QChar();
|
||||
mAsmStart = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@ private:
|
|||
void unknownProc();
|
||||
void xorSymbolProc();
|
||||
void processChar();
|
||||
void popIndentsByType(QChar indentType);
|
||||
void popIndents(QChar indentType);
|
||||
void pushIndents(QChar indentType);
|
||||
|
||||
private:
|
||||
bool mAsmStart;
|
||||
|
|
Loading…
Reference in New Issue