diff options
Diffstat (limited to 'src/libs/utils/textutils.cpp')
-rw-r--r-- | src/libs/utils/textutils.cpp | 134 |
1 files changed, 100 insertions, 34 deletions
diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp index 1222038039..28a9e12e1b 100644 --- a/src/libs/utils/textutils.cpp +++ b/src/libs/utils/textutils.cpp @@ -2,40 +2,116 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "textutils.h" +#include "qtcassert.h" -#include <QTextDocument> +#include <QRegularExpression> #include <QTextBlock> +#include <QTextDocument> + +namespace Utils::Text { + +bool Position::operator==(const Position &other) const +{ + return line == other.line && column == other.column; +} + +/*! + Returns the text position of a \a fileName and sets the \a postfixPos if + it can find a positional postfix. + + The following patterns are supported: \c {filepath.txt:19}, + \c{filepath.txt:19:12}, \c {filepath.txt+19}, + \c {filepath.txt+19+12}, and \c {filepath.txt(19)}. +*/ + +Position Position::fromFileName(QStringView fileName, int &postfixPos) +{ + static const auto regexp = QRegularExpression("[:+](\\d+)?([:+](\\d+)?)?$"); + // (10) MSVC-style + static const auto vsRegexp = QRegularExpression("[(]((\\d+)[)]?)?$"); + const QRegularExpressionMatch match = regexp.match(fileName); + Position pos; + if (match.hasMatch()) { + postfixPos = match.capturedStart(0); + if (match.lastCapturedIndex() > 0) { + pos.line = match.captured(1).toInt(); + if (match.lastCapturedIndex() > 2) // index 2 includes the + or : for the column number + pos.column = match.captured(3).toInt() - 1; //column is 0 based, despite line being 1 based + } + } else { + const QRegularExpressionMatch vsMatch = vsRegexp.match(fileName); + postfixPos = vsMatch.capturedStart(0); + if (vsMatch.lastCapturedIndex() > 1) // index 1 includes closing ) + pos.line = vsMatch.captured(2).toInt(); + } + if (pos.line > 0 && pos.column < 0) + pos.column = 0; // if we got a valid line make sure to return a valid TextPosition + return pos; +} + +Position Position::fromPositionInDocument(const QTextDocument *document, int pos) +{ + QTC_ASSERT(document, return {}); + const QTextBlock block = document->findBlock(pos); + if (block.isValid()) + return {block.blockNumber() + 1, pos - block.position()}; + + return {}; +} + +Position Position::fromCursor(const QTextCursor &c) +{ + return c.isNull() ? Position{} : Position{c.blockNumber() + 1, c.positionInBlock()}; +} + +int Range::length(const QString &text) const +{ + if (end.line < begin.line) + return -1; -namespace Utils { -namespace Text { + if (begin.line == end.line) + return end.column - begin.column; + + int index = 0; + int currentLine = 1; + while (currentLine < begin.line) { + index = text.indexOf(QChar::LineFeed, index); + if (index < 0) + return -1; + ++index; + ++currentLine; + } + const int beginIndex = index + begin.column; + while (currentLine < end.line) { + index = text.indexOf(QChar::LineFeed, index); + if (index < 0) + return -1; + ++index; + ++currentLine; + } + return index + end.column - beginIndex; +} + +bool Range::operator==(const Range &other) const +{ + return begin == other.begin && end == other.end; +} bool convertPosition(const QTextDocument *document, int pos, int *line, int *column) { QTextBlock block = document->findBlock(pos); if (!block.isValid()) { (*line) = -1; - (*column) = -1; + (*column) = 0; return false; } else { // line and column are both 1-based (*line) = block.blockNumber() + 1; - (*column) = pos - block.position() + 1; + (*column) = pos - block.position(); return true; } } -OptionalLineColumn convertPosition(const QTextDocument *document, int pos) -{ - OptionalLineColumn optional; - - QTextBlock block = document->findBlock(pos); - - if (block.isValid()) - optional.emplace(block.blockNumber() + 1, pos - block.position() + 1); - - return optional; -} - int positionInText(const QTextDocument *textDocument, int line, int column) { // Deduct 1 from line and column since they are 1-based. @@ -141,21 +217,6 @@ int utf8NthLineOffset(const QTextDocument *textDocument, const QByteArray &buffe return utf8Offset; } -LineColumn utf16LineColumn(const QByteArray &utf8Buffer, int utf8Offset) -{ - LineColumn lineColumn; - lineColumn.line = static_cast<int>( - std::count(utf8Buffer.begin(), utf8Buffer.begin() + utf8Offset, '\n')) - + 1; - const int startOfLineOffset = utf8Offset ? (utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1) - : 0; - lineColumn.column = QString::fromUtf8( - utf8Buffer.mid(startOfLineOffset, utf8Offset - startOfLineOffset)) - .length() - + 1; - return lineColumn; -} - QString utf16LineTextInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset) { const int lineStartUtf8Offset = currentUtf8Offset @@ -211,5 +272,10 @@ void applyReplacements(QTextDocument *doc, const Replacements &replacements) editCursor.endEditBlock(); } -} // Text -} // Utils +QDebug &operator<<(QDebug &stream, const Position &pos) +{ + stream << "line: " << pos.line << ", column: " << pos.column; + return stream; +} + +} // namespace Utils::Text |