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