- 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
- enhancement: more accurate auto indent calculation
- 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();
}
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;
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<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;
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<int> newIndents = range.indents.mid(range.firstIndentThisLine);
int i = 0;
int len = matchingIndents.length();
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);
if (idx >=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,9 +2052,7 @@ 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);

View File

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

View File

@ -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();
}

View File

@ -10,10 +10,13 @@
#include <QVector>
#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<int> 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<int> 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;

View File

@ -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<mRange.firstIndentThisLine)
mRange.firstIndentThisLine = idx;
mRange.indents.append(indentType);
mRange.indents.push_back(indentType);
}
bool SynEditCppHighlighter::getTokenFinished() const
@ -1532,7 +1548,7 @@ void SynEditCppHighlighter::setLine(const QString &newLine, int lineNumber)
mRange.leftBraces = 0;
mRange.rightBraces = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents = "";
mRange.matchingIndents.clear();
next();
}
@ -1600,7 +1616,7 @@ void SynEditCppHighlighter::setState(const SynRangeState& rangeState)
mRange.leftBraces = 0;
mRange.rightBraces = 0;
mRange.firstIndentThisLine = mRange.indents.length();
mRange.matchingIndents = "";
mRange.matchingIndents.clear();
}
void SynEditCppHighlighter::resetState()
@ -1612,9 +1628,9 @@ void SynEditCppHighlighter::resetState()
mRange.parenthesisLevel = 0;
mRange.leftBraces = 0;
mRange.rightBraces = 0;
mRange.indents = "";
mRange.indents.clear();
mRange.firstIndentThisLine = 0;
mRange.matchingIndents = "";
mRange.matchingIndents.clear();
mAsmStart = false;
}

View File

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