Rework code folding

The new and cleaner foldingIndent in the block user data will
make it easier to support other kinds of indentation for various
other programming languages (like Python).
This commit is contained in:
mae
2010-05-20 15:10:26 +02:00
parent 55b26868e6
commit e07c34017e
11 changed files with 377 additions and 532 deletions

View File

@@ -44,6 +44,7 @@ Highlighter::Highlighter(QTextDocument *parent)
{
m_currentBlockParentheses.reserve(20);
m_braceDepth = 0;
m_foldingIndent = 0;
}
Highlighter::~Highlighter()
@@ -102,27 +103,27 @@ void Highlighter::highlightBlock(const QString &text)
break;
case Token::LeftParenthesis:
onOpeningParenthesis('(', token.offset);
onOpeningParenthesis('(', token.offset, index == 0);
break;
case Token::RightParenthesis:
onClosingParenthesis(')', token.offset);
onClosingParenthesis(')', token.offset, index == tokens.size()-1);
break;
case Token::LeftBrace:
onOpeningParenthesis('{', token.offset);
onOpeningParenthesis('{', token.offset, index == 0);
break;
case Token::RightBrace:
onClosingParenthesis('}', token.offset);
onClosingParenthesis('}', token.offset, index == tokens.size()-1);
break;
case Token::LeftBracket:
onOpeningParenthesis('[', token.offset);
onOpeningParenthesis('[', token.offset, index == 0);
break;
case Token::RightBracket:
onClosingParenthesis(']', token.offset);
onClosingParenthesis(']', token.offset, index == tokens.size()-1);
break;
case Token::Identifier: {
@@ -232,12 +233,8 @@ void Highlighter::highlightBlock(const QString &text)
setFormat(previousTokenEnd, text.length() - previousTokenEnd, m_formats[VisualWhitespace]);
int firstNonSpace = 0;
if (! tokens.isEmpty())
firstNonSpace = tokens.first().offset;
setCurrentBlockState(m_scanner.state());
onBlockEnd(m_scanner.state(), firstNonSpace);
onBlockEnd(m_scanner.state());
}
bool Highlighter::maybeQmlKeyword(const QStringRef &text) const
@@ -301,6 +298,12 @@ int Highlighter::onBlockStart()
{
m_currentBlockParentheses.clear();
m_braceDepth = 0;
m_foldingIndent = 0;
if (TextEditor::TextBlockUserData *userData = TextEditor::BaseTextDocumentLayout::testUserData(currentBlock())) {
userData->setFoldingIndent(0);
userData->setFoldingStartIncluded(false);
userData->setFoldingEndIncluded(false);
}
int state = 0;
int previousState = previousBlockState();
@@ -308,56 +311,41 @@ int Highlighter::onBlockStart()
state = previousState & 0xff;
m_braceDepth = previousState >> 8;
}
m_foldingIndent = m_braceDepth;
return state;
}
void Highlighter::onBlockEnd(int state, int firstNonSpace)
void Highlighter::onBlockEnd(int state)
{
typedef TextEditor::TextBlockUserData TextEditorBlockData;
setCurrentBlockState((m_braceDepth << 8) | state);
// Set block data parentheses. Force creation of block data unless empty
TextEditorBlockData *blockData = 0;
if (QTextBlockUserData *userData = currentBlockUserData())
blockData = static_cast<TextEditorBlockData *>(userData);
if (!blockData && !m_currentBlockParentheses.empty()) {
blockData = new TextEditorBlockData;
setCurrentBlockUserData(blockData);
}
if (blockData) {
blockData->setParentheses(m_currentBlockParentheses);
blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse);
blockData->setCollapseMode(TextEditor::TextBlockUserData::NoCollapse);
}
if (!m_currentBlockParentheses.isEmpty()) {
QTC_ASSERT(blockData, return);
int collapse = Parenthesis::collapseAtPos(m_currentBlockParentheses);
if (collapse >= 0) {
if (collapse == firstNonSpace)
blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseThis);
else
blockData->setCollapseMode(TextEditor::TextBlockUserData::CollapseAfter);
}
if (Parenthesis::hasClosingCollapse(m_currentBlockParentheses))
blockData->setClosingCollapseMode(TextEditor::TextBlockUserData::NoClosingCollapse);
}
TextEditor::BaseTextDocumentLayout::setParentheses(currentBlock(), m_currentBlockParentheses);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(currentBlock(), m_foldingIndent);
}
void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos)
void Highlighter::onOpeningParenthesis(QChar parenthesis, int pos, bool atStart)
{
if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('['))
if (parenthesis == QLatin1Char('{') || parenthesis == QLatin1Char('[')) {
++m_braceDepth;
// if a folding block opens at the beginning of a line, treat the entire line
// as if it were inside the folding block
if (atStart)
TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
}
m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Opened, parenthesis, pos));
}
void Highlighter::onClosingParenthesis(QChar parenthesis, int pos)
void Highlighter::onClosingParenthesis(QChar parenthesis, int pos, bool atEnd)
{
if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']'))
if (parenthesis == QLatin1Char('}') || parenthesis == QLatin1Char(']')) {
--m_braceDepth;
if (atEnd)
TextEditor::BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
else
m_foldingIndent = qMin(m_braceDepth, m_foldingIndent); // folding indent is the minimum brace depth of a block
}
m_currentBlockParentheses.push_back(Parenthesis(Parenthesis::Closed, parenthesis, pos));
}