void Indenter::indentBlock(const QTextBlock &block, const QChar &, const TextEditor::TabSettings &settings, int) { int indent; QTextBlock previous = block.previous(); // Previous line ends on comma, ignore everything and follow the indent if (previous.text().endsWith(',')) { indent = previous.text().indexOf(QRegularExpression("\\S")) / settings.m_indentSize; } else { // Use the stored indent plus some bizarre heuristics that even myself remember how it works. indent = block.userState() >> 20; if (indent < 0) { while (indent == -1 && previous.isValid()) { indent = previous.userState() >> 20; previous = previous.previous(); } } if (didBlockStart(block) && indent > 0) indent--; } settings.indentLine(block, indent * settings.m_indentSize); }
void CMakeIndenter::indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings) { Q_UNUSED(doc) Q_UNUSED(typedChar) QTextBlock previousBlock = block.previous(); // find the next previous block that is non-empty (contains non-whitespace characters) while (previousBlock.isValid() && lineIsEmpty(previousBlock.text())) previousBlock = previousBlock.previous(); if (previousBlock.isValid()) { const QString previousLine = previousBlock.text(); const QString currentLine = block.text(); int indentation = tabSettings.indentationColumn(previousLine); if (lineStartsBlock(previousLine)) indentation += tabSettings.m_indentSize; if (lineEndsBlock(currentLine)) indentation = qMax(0, indentation - tabSettings.m_indentSize); // increase/decrease/keep the indentation level depending on if we have more opening or closing parantheses indentation = qMax(0, indentation + tabSettings.m_indentSize * paranthesesLevel(previousLine)); tabSettings.indentLine(block, indentation); } else { // First line in whole document tabSettings.indentLine(block, 0); } }
void KNoteEdit::autoIndent() { QTextCursor c = textCursor(); QTextBlock b = c.block(); QString string; while ( ( b.previous().length() > 0 ) && string.trimmed().isEmpty() ) { b = b.previous(); string = b.text(); } if ( string.trimmed().isEmpty() ) { return; } // This routine returns the whitespace before the first non white space // character in string. // It is assumed that string contains at least one non whitespace character // ie \n \r \t \v \f and space QString indentString; const int len = string.length(); int i = 0; while ( i < len && string.at( i ).isSpace() ) { indentString += string.at( i++ ); } if ( !indentString.isEmpty() ) { c.insertText( indentString ); } }
QTextBlock reverseFindLastEmptyBlock(QTextBlock start) { if (start.position() > 0) { start = start.previous(); while (start.position() > 0 && start.text().trimmed().isEmpty()) start = start.previous(); if (!start.text().trimmed().isEmpty()) start = start.next(); } return start; }
// Add extra text in case of the empty line or the line starting with ')'. // Track such extra pieces of text in isInsideModifiedLine(). int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool secondTry) { const QString blockText = block.text(); int firstNonWhitespace = Utils::indexOf(blockText, [](const QChar &ch) { return !ch.isSpace(); }); int utf8Offset = Utils::Text::utf8NthLineOffset(block.document(), buffer, block.blockNumber() + 1); if (firstNonWhitespace > 0) utf8Offset += firstNonWhitespace; else utf8Offset += blockText.length(); const bool closingParenBlock = firstNonWhitespace >= 0 && blockText.at(firstNonWhitespace) == ')'; int extraLength = 0; if (firstNonWhitespace < 0 || closingParenBlock) { //This extra text works for the most cases. QByteArray dummyText("a;a;"); // Search for previous character QTextBlock prevBlock = block.previous(); bool prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty(); while (prevBlockIsEmpty) { prevBlock = prevBlock.previous(); prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty(); } if (closingParenBlock || prevBlock.text().endsWith(',')) dummyText = "&& a"; buffer.insert(utf8Offset, dummyText); extraLength += dummyText.length(); } if (secondTry) { int nextLinePos = buffer.indexOf('\n', utf8Offset); if (nextLinePos < 0) nextLinePos = buffer.size() - 1; if (nextLinePos > 0) { // If first try was not successful try to put ')' in the end of the line to close possibly // unclosed parentheses. // TODO: Does it help to add different endings depending on the context? buffer.insert(nextLinePos, ')'); extraLength += 1; } } return extraLength; }
int formattingRangeStart(const QTextBlock ¤tBlock, const QByteArray &buffer, int documentRevision) { QTextBlock prevBlock = currentBlock.previous(); while ((prevBlock.position() > 0 || prevBlock.length() > 0) && prevBlock.revision() != documentRevision) { // Find the first block with not matching revision. prevBlock = prevBlock.previous(); } if (prevBlock.revision() == documentRevision) prevBlock = prevBlock.next(); return Utils::Text::utf8NthLineOffset(prevBlock.document(), buffer, prevBlock.blockNumber() + 1); }
static int findOpeningMatch(const QTextDocument *doc, int cursorPosition) { QTextBlock block = doc->findBlock(cursorPosition); TextBlockData *blockData = reinterpret_cast<TextBlockData *>(block.userData()); if (!blockData->bracketPositions.isEmpty()) { int depth = 1; while (block.isValid()) { blockData = reinterpret_cast<TextBlockData *>(block.userData()); if (blockData && !blockData->bracketPositions.isEmpty()) { for (int c = blockData->bracketPositions.count() - 1; c >= 0; --c) { int absPos = block.position() + blockData->bracketPositions.at(c); if (absPos >= cursorPosition - 1) continue; if (doc->characterAt(absPos) == '}') depth++; else depth--; if (depth == 0) return absPos; } } block = block.previous(); } } return -1; }
void CodeEditer::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar) { Q_UNUSED(typedChar); // At beginning: Leave as is. if (block == doc->begin()) return; const QTextBlock previous = block.previous(); const QString previousText = previous.text(); // Empty line indicates a start of a new paragraph. Leave as is. if (previousText.isEmpty() || previousText.trimmed().isEmpty()) return; // Just use previous line. // Skip non-alphanumerical characters when determining the indentation // to enable writing bulleted lists whose items span several lines. int i = 0; while (i < previousText.size()) { if (previousText.at(i).isLetterOrNumber() || previousText.at(i) == '{' || previousText.at(i) == '}' || previousText.at(i) == '#') { //const TextEditor::TabSettings &ts = tabSettings(); indentLine(block, columnAt(previousText, i)); break; } ++i; } }
bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = parenList.count()-1; i >= 0; --i) { Parenthesis paren = parenList.at(i); if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}') && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-') && paren.chr != QLatin1Char('[') && paren.chr != QLatin1Char(']')) continue; if (block == cursor->block()) { if (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0)) continue; if (checkStartPosition && paren.type == Parenthesis::Opened && paren.pos== cursor->position()) { return true; } } if (paren.type == Parenthesis::Closed) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos); return true; } } } block = block.previous(); } return false; }
bool TextBlockUserData::findPreviousOpenParenthesis(QTextCursor *cursor, bool select, bool onlyInCurrentBlock) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = parenList.count()-1; i >= 0; --i) { Parenthesis paren = parenList.at(i); if (block == cursor->block() && (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0))) continue; if (paren.type == Parenthesis::Closed) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); return true; } } } if (onlyInCurrentBlock) return false; block = block.previous(); } return false; }
QString QueryPanel::getActiveStatement(int block, int col) { int from = 0, to = -1; State st; QTextBlock b = editor->document()->findBlockByNumber(block); int scol = col; while(b.isValid()) { st.opaque = b.userState(); if(st.s.col != -1 && st.s.col < scol) { from = b.position() + st.s.col + 1; break; } scol = INT_MAX; b = b.previous(); } b = editor->document()->findBlockByNumber(block); scol = col; while(b.isValid()) { st.opaque = b.userState(); if(st.s.col != -1 && st.s.col >= scol) { to = b.position() + st.s.col; break; } scol = 0; b = b.next(); } QString all = editor->document()->toPlainText(); if(to < 0) to = all.length(); return all.mid(from,to);; }
TokenIterator& operator --() { if(idx > 0) { --idx; return *this; } else if( idx < 0 ) { return *this; } idx = -1; while( (blk = blk.previous()).isValid() ) { data = static_cast<TextBlockData*>(blk.userData()); if(data) idx = data->tokens.size() - 1; if (idx < 0) continue; // we have a valid idx break; } return *this; }
int ShaderEdit::searchPreviousMatch( QTextBlock block, int start, QString close, QString open ) { int skipNext = 0; --start; TextBlockData *data = (TextBlockData*)block.userData(); do { if ( data ) { for ( int i = start; i >= 0; --i ) { ParenthesisInfo pi = data->parenthesis[i]; QString s = pi.character; if ( s == open ) { if ( skipNext > 0 ) --skipNext; else return block.position() + pi.position; } else if ( s == close ) ++skipNext; } } block = block.previous(); data = (TextBlockData*)block.userData(); if ( data ) start = data->parenthesis.count() - 1; } while ( block.isValid() ); return -1; }
void CppQtStyleIndenter::indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings) { Q_UNUSED(doc) CppTools::QtStyleCodeFormatter codeFormatter(tabSettings, codeStyleSettings()); codeFormatter.updateStateUntil(block); int indent; int padding; codeFormatter.indentFor(block, &indent, &padding); if (isElectricCharacter(typedChar)) { // : should not be electric for labels if (typedChar == QLatin1Char(':') && !colonIsElectric(block.text())) return; // only reindent the current line when typing electric characters if the // indent is the same it would be if the line were empty int newlineIndent; int newlinePadding; codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding); if (tabSettings.indentationColumn(block.text()) != newlineIndent + newlinePadding) return; } tabSettings.indentLine(block, indent + padding, padding); }
void MarkdownEdit::insert_head(const QString &tag, bool blockStart) { QTextCursor cur = m_ed->textCursor(); cur.beginEditBlock(); if (cur.hasSelection()) { QTextBlock begin = m_ed->document()->findBlock(cur.selectionStart()); QTextBlock end = m_ed->document()->findBlock(cur.selectionEnd()); if (end.position() == cur.selectionEnd()) { end = end.previous(); } QTextBlock block = begin; do { if (block.text().length() > 0) { if (blockStart) { cur.setPosition(block.position()); } else { QString text = block.text(); foreach(QChar c, text) { if (!c.isSpace()) { cur.setPosition(block.position()+text.indexOf(c)); break; } } } cur.insertText(tag); } block = block.next(); } while(block.isValid() && block.position() <= end.position()); } else {
void GLSLIndenter::indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings) { Q_UNUSED(doc) // TODO: do something with it CppTools::QtStyleCodeFormatter codeFormatter(tabSettings, CppTools::CppToolsSettings::instance()->cppCodeStyle()->codeStyleSettings()); codeFormatter.updateStateUntil(block); int indent; int padding; codeFormatter.indentFor(block, &indent, &padding); // only reindent the current line when typing electric characters if the // indent is the same it would be if the line were empty if (isElectricCharacter(typedChar)) { int newlineIndent; int newlinePadding; codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding); if (tabSettings.indentationColumn(block.text()) != newlineIndent + newlinePadding) return; } tabSettings.indentLine(block, indent + padding, padding); }
int SoTextEdit::findBraceLeft(void) { QTextCursor cursor = textCursor(); QTextBlock block = cursor.block(); int brace_count = 0, i, blockNumber = block.blockNumber(); QString text; while (blockNumber != UNVALID_BLOCK) { text = block.text(); i = text.size(); for (; 0 <= i; i--) { if (text[i] == QChar('}')) { brace_count++; } else if (text[i] == QChar('{')) { brace_count--; if (brace_count == 0) { // cursor.deletePreviousChar(); // cursor.insertText("}", colorFormat(Qt::darkCyan)); cursor.setPosition((block.position()) + i); // cursor.deleteChar(); // cursor.insertText("{", colorFormat(Qt::darkCyan)); return (block.position() + i); } } } block = block.previous(); blockNumber = block.blockNumber(); } return -1; }
bool CodeEditor::matchRightParenthesis(QTextBlock currentBlock, int i, int numRightParentheses) { TextBlockData *data = static_cast<TextBlockData *>(currentBlock.userData()); QVector<ParenthesisInfo *> parentheses = data->parentheses(); int docPos = currentBlock.position(); for (; i > -1 && parentheses.size() > 0; --i) { ParenthesisInfo *info = parentheses.at(i); if (info->character == ')') { ++numRightParentheses; continue; } if (info->character == '(' && numRightParentheses == 0) { createParenthesisSelection(docPos + info->position); return true; } else { --numRightParentheses; } } currentBlock = currentBlock.previous(); if (currentBlock.isValid()) return matchRightParenthesis(currentBlock, 0, numRightParentheses); return false; }
void EditorUtil::EnumEditor(QPlainTextEdit *ed, EnumEditorProc proc, void *param) { if (!ed) { return; } QTextCursor cur = ed->textCursor(); cur.beginEditBlock(); if (cur.hasSelection()) { QTextBlock begin = ed->document()->findBlock(cur.selectionStart()); QTextBlock end = ed->document()->findBlock(cur.selectionEnd()); if (end.position() == cur.selectionEnd()) { end = end.previous(); } QTextBlock block = begin; do { if (block.text().length() > 0) { proc(cur,block,param); } block = block.next(); } while(block.isValid() && block.position() <= end.position()); } else { QTextBlock block = cur.block(); proc(cur,block,param); } cur.endEditBlock(); ed->setTextCursor(cur); }
void OMS::selectCommandLine() { cursor_.movePosition( QTextCursor::End, QTextCursor::MoveAnchor ); QTextBlock block = moshEdit_->document()->findBlock( cursor_.position() ); while( true ) { if( block.isValid() ) { if( block.text().indexOf( ">> ", 0, Qt::CaseInsensitive ) == 0 ) { // last command sign found, move cursor there cursor_.setPosition( block.position()+3, QTextCursor::KeepAnchor ); break; } else { // no command sign, look in previous text block block = block.previous(); } } else { cout << "Not a valid QTextBlock (selectCommandLine)" << endl; break; } } moshEdit_->ensureCursorVisible(); }
void TextProcessor::textChangeEvent() { if (autoInsertion_) return; QTextCursor c = edit_->textCursor(); if (c.atBlockStart()) { QTextBlock bl = c.block(); QTextBlock prevBl = bl.previous(); if (bl.isValid() && prevBl.isValid()) { // ensure that cursor was moved from the previous row if (lastRow_ - 1 != preLastRow_) return; QString text = bl.text(); QString prevText = prevBl.text(); if (/*text.isEmpty() &&*/ !prevText.isEmpty()) { int lineBeginIndex = prevText.indexOf(QRegExp("[^ \t]")); QString lineBegin = prevText.left(lineBeginIndex); autoInsertion_ = true; while (bl.text().startsWith('\t') || bl.text().startsWith(' ')) { c.deleteChar(); } c.insertText(lineBegin); autoInsertion_ = false; } } } }
int CodeFormatter::indentFor(const QTextBlock &block) { // qDebug() << "indenting for" << block.blockNumber() + 1; restoreCurrentState(block.previous()); correctIndentation(block); return m_indentDepth; }
void CodeFormatter::correctIndentation(const QTextBlock &block) { tokenizeBlock(block); Q_ASSERT(m_currentState.size() >= 1); const int startLexerState = loadLexerState(block.previous()); adjustIndent(m_tokens, startLexerState, &m_indentDepth); }
void replaceSignature(QTextDocument *document, const QString &newSignature) { // The QTextEdit is set up in such a way as to treat a fully terminated line as a standalone text block, // hence no newlines in the signature separator const QLatin1String signatureSeperator("-- "); QTextBlock block = document->lastBlock(); while (block.isValid() && block.blockNumber() > 0) { if (block.text() == signatureSeperator) { // So this block holds the last signature separator -- great! break; } block = block.previous(); } QTextCursor cursor(block); if (block.text() == signatureSeperator) { // Remove everything till the end of the document since the end of the previous block if (block.previous().isValid()) { // Prevent adding newlines when switching signatures block = block.previous(); cursor = QTextCursor(block); cursor.movePosition(QTextCursor::EndOfBlock); } cursor.beginEditBlock(); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); cursor.removeSelectedText(); cursor.endEditBlock(); } else { // We have not removed anything, so we have to "fake" an edit action so that we're adding the signature to a correct place block = document->lastBlock(); cursor = QTextCursor(block); cursor.movePosition(QTextCursor::EndOfBlock); cursor.beginEditBlock(); cursor.endEditBlock(); } if (!newSignature.isEmpty()) { cursor.joinPreviousEditBlock(); cursor.insertBlock(); cursor.insertText(signatureSeperator); cursor.insertBlock(); cursor.insertText(newSignature); cursor.endEditBlock(); } }
///Indique si on est à la première ligne bool RzxTextEdit::atBeginning() const { QTextBlock block = textCursor().block(); if(block.previous().isValid()) return false; QTextLine line = currentTextLine(); return line.isValid() && !line.lineNumber(); }
QString ExpressionUnderCursor::operator()(const QTextCursor &cursor) { enum { MAX_BLOCK_COUNT = 5 }; QTextBlock block = cursor.block(); QTextBlock initialBlock = block; for (int i = 0; i < MAX_BLOCK_COUNT; ++i) { if (! initialBlock.previous().isValid()) break; initialBlock = initialBlock.previous(); } QString text; QTextBlock it = initialBlock; for (; it.isValid(); it = it.next()) { QString textBlock = it.text(); if (it == block) textBlock = textBlock.left(cursor.position() - cursor.block().position()); text += textBlock; if (it == block) break; text += QLatin1Char('\n'); } SimpleLexer tokenize; tokenize.setSkipComments(true); QList<SimpleToken> tokens = tokenize(text, previousBlockState(initialBlock)); tokens.prepend(SimpleToken()); // sentinel _jumpedComma = false; const int i = startOfExpression(tokens, tokens.size()); if (i == tokens.size()) return QString(); return text.mid(tokens.at(i).position(), tokens.last().position() + tokens.last().length() - tokens.at(i).position()); }
void GoCodeFormatter::calcIndentation(const QTextBlock &block, int *indentation, int *padding, bool withoutLexer) { restoreCurrentState(block.previous()); adjustIndentation(block, withoutLexer); *indentation = m_indentation; *padding = m_padding; }
QString QSAEditor::functionCode() const { QTextBlock block = textCursor().block(); QString funcName; int pos; int braceCount = -1; QString s; while (block.isValid() && (pos = block.text().indexOf(QLatin1String("function"))) == -1) { s = block.text(); braceCount += s.count(QLatin1Char('{')); braceCount -= s.count(QLatin1Char('}')); block = block.previous(); } if (block.isValid()) { s = block.text(); braceCount += s.count( '{' ); braceCount -= s.count( '}' ); } if (block.isValid() && pos != -1 && braceCount >= 0) { funcName = block.text().mid(pos + 9).simplified(); funcName = funcName.left(funcName.indexOf(QLatin1Char('('))); } QuickClassParser parser; parser.parse(toPlainText()); QList<QuickClass> classes = parser.classes(); const bool global = funcName.isNull() || !block.isValid(); QString code; for (QList<QuickClass>::ConstIterator it = classes.begin(); it != classes.end(); ++it) { if ((*it).type == QuickClass::Global) { for (QStringList::ConstIterator vit = (*it).variables.begin(); vit != (*it).variables.end(); ++vit) code += *vit + QString::fromLatin1(";\n"); code += QString::fromLatin1("\n"); if (global) break; } if (global) continue; for (QList<LanguageInterface::Function>::ConstIterator fit = (*it).functions.begin(); fit != (*it).functions.end(); ++fit) { if ((*fit).name.left( (*fit).name.indexOf( '(' ) ) == funcName) { if ((*it).type != QuickClass::Global) { for (QStringList::ConstIterator vit = (*it).variables.begin(); vit != (*it).variables.end(); ++vit) code += *vit + QString::fromLatin1(";\n"); code += QString::fromLatin1("\n"); } code += QString::fromLatin1("\n") + (*fit).body + QString::fromLatin1("\n"); break; } } } return code; }
/* Returns true if the start of the bottom line of yyProgram (and potentially the whole line) is part of a C-style comment; otherwise returns false. */ bool LineInfo::bottomLineStartsInMultilineComment() { QTextBlock currentLine = yyProgram.lastBlock().previous(); QTextBlock previousLine = currentLine.previous(); int startState = qMax(0, previousLine.userState()) & 0xff; if (startState > 0) return true; return false; }
int CodeFormatter::indentForNewLineAfter(const QTextBlock &block) { restoreCurrentState(block); m_tokens.clear(); m_currentLine.clear(); const int startLexerState = loadLexerState(block.previous()); adjustIndent(m_tokens, startLexerState, &m_indentDepth); return m_indentDepth; }