diff --git a/docs/API/knut/textdocument.md b/docs/API/knut/textdocument.md index da2f6f50..e7818ad4 100644 --- a/docs/API/knut/textdocument.md +++ b/docs/API/knut/textdocument.md @@ -63,8 +63,10 @@ Inherited properties: [Document properties](../knut/document.md#properties) |bool |**[hasSelection](#hasSelection)**()| ||**[indent](#indent)**(int count)| ||**[indentLine](#indentLine)**(int count, int line)| -||**[indentationAtLine](#indentationAtLine)**(int line = -1)| -||**[indentationAtPosition](#indentationAtPosition)**(int pos)| +|string |**[indentTextAtLine](#indentTextAtLine)**(int line = -1)| +|string |**[indentTextAtPosition](#indentTextAtPosition)**(int pos)| +|int |**[indentationAtLine](#indentationAtLine)**(int line = -1)| +|int |**[indentationAtPosition](#indentationAtPosition)**(int pos)| ||**[insert](#insert)**(string text)| ||**[insertAtLine](#insertAtLine)**(string text, int line = -1)| ||**[insertAtPosition](#insertAtPosition)**(string text, int pos)| @@ -322,16 +324,31 @@ Indents the `line` `count` times. See also: [`indent`](#indent) -#### **indentationAtLine**(int line = -1) +#### string **indentTextAtLine**(int line = -1) -Returns the indentation at the given line. +Returns the indentation text at the given line. If `line` is -1 it will return the indentation at the current line. If `line` is larger than the number of lines in the document, it will return an empty string -#### **indentationAtPosition**(int pos) +Note: To get the level of indentation, use [`indentationAtLine`](#indentationAtLine). -Returns the indentation at the given position. +#### string **indentTextAtPosition**(int pos) + +Returns the indentation text at the given position. + +Note: To get the level of indentation, use [`indentationAtPosition`](#indentationAtPosition). + +#### int **indentationAtLine**(int line = -1) + +Returns the indentation level at the given line. + +If `line` is -1 it will return the indentation at the current line. +If `line` is larger than the number of lines in the document, it will return 0 + +#### int **indentationAtPosition**(int pos) + +Returns the indentation level at the given position. #### **insert**(string text) diff --git a/src/core/cppdocument.cpp b/src/core/cppdocument.cpp index b5662c78..046dfe01 100644 --- a/src/core/cppdocument.cpp +++ b/src/core/cppdocument.cpp @@ -1339,12 +1339,12 @@ CppDocument::addMemberOrMethod(const QString &memberInfo, const QString &classNa const auto fields = match.getAll("field"); if (!fields.isEmpty()) { const auto &pos = fields.last(); - const auto indent = indentationAtPosition(pos.end()); + const auto indent = indentTextAtPosition(pos.end()); insertAtPosition("\n" + indent + memberText, pos.end()); } else { const auto access = match.getAll("access"); const auto &pos = access.last(); - const auto indent = indentationAtPosition(pos.end()); + const auto indent = indentTextAtPosition(pos.end()); insertAtPosition("\n" + indent + memberText, pos.end()); } } else { @@ -1519,7 +1519,7 @@ bool CppDocument::addSpecifierSection(const QString &memberText, const QString & if (!result.isEmpty()) { const auto &match = result.last(); const auto pos = match.get("pos"); - const auto indent = indentationAtPosition(pos.end()); + const auto indent = indentTextAtPosition(pos.end()); const QString newSpecifier = QString("\n\n%1:").arg(accessSpecifierMap.value(specifier)); diff --git a/src/core/textdocument.cpp b/src/core/textdocument.cpp index 79674e56..eff0439d 100644 --- a/src/core/textdocument.cpp +++ b/src/core/textdocument.cpp @@ -1534,6 +1534,11 @@ static int firstNonSpace(const QString &text) return i; } +static QString indentToString(int indentSize, const TabSettings &settings) +{ + return settings.insertSpaces ? QString(indentSize * settings.tabSize, ' ') : QString(indentSize, '\t'); +} + static int indentOneLine(QTextCursor &cursor, int tabCount, const TabSettings &settings, bool relative) { QString text = cursor.selectedText(); @@ -1546,10 +1551,7 @@ static int indentOneLine(QTextCursor &cursor, int tabCount, const TabSettings &s const int indentSize = qMax(relative ? (currentIndent + tabCount) : tabCount, 0); text.remove(0, firstChar); - if (settings.insertSpaces) - text = QString(indentSize * settings.tabSize, ' ') + text; - else - text = QString(indentSize, '\t') + text; + text = indentToString(indentSize, settings) + text; cursor.insertText(text); return text.size() - oldSize; @@ -1694,12 +1696,15 @@ void TextDocument::setLineEnding(LineEnding newLineEnding) } /*! - * \qmlmethod TextDocument::indentationAtPosition(int pos) - * Returns the indentation at the given position. + * \qmlmethod string TextDocument::indentTextAtPosition(int pos) + * Returns the indentation text at the given position. + * + * Note: To get the level of indentation, use [`indentationAtPosition`](#indentationAtPosition). */ -QString TextDocument::indentationAtPosition(int pos) +QString TextDocument::indentTextAtPosition(int pos) const { LOG(LOG_ARG("position", pos)); + auto cursor = m_document->textCursor(); cursor.setPosition(pos); cursor.movePosition(QTextCursor::StartOfLine); @@ -1709,13 +1714,15 @@ QString TextDocument::indentationAtPosition(int pos) } /*! - * \qmlmethod TextDocument::indentationAtLine(int line = -1) - * Returns the indentation at the given line. + * \qmlmethod string TextDocument::indentTextAtLine(int line = -1) + * Returns the indentation text at the given line. * * If `line` is -1 it will return the indentation at the current line. * If `line` is larger than the number of lines in the document, it will return an empty string + * + * Note: To get the level of indentation, use [`indentationAtLine`](#indentationAtLine). */ -QString TextDocument::indentationAtLine(int line /* = -1 */) +QString TextDocument::indentTextAtLine(int line /* = -1 */) const { LOG(LOG_ARG("line", line)); @@ -1728,9 +1735,38 @@ QString TextDocument::indentationAtLine(int line /* = -1 */) const QTextBlock &block = m_document->document()->findBlockByNumber(blockNumber); if (block.isValid()) { - return indentationAtPosition(block.position()); + return indentTextAtPosition(block.position()); } - return ""; + return 0; +} + +/*! + * \qmlmethod int TextDocument::indentationAtPosition(int pos) + * Returns the indentation level at the given position. + */ +int TextDocument::indentationAtPosition(int pos) const +{ + LOG(LOG_ARG("position", pos)); + + const auto indentText = indentTextAtPosition(pos); + const auto settings = Core::Settings::instance()->value(Core::Settings::Tab); + return columnAt(indentText, indentText.size(), settings.tabSize) / settings.tabSize; +} + +/*! + * \qmlmethod int TextDocument::indentationAtLine(int line = -1) + * Returns the indentation level at the given line. + * + * If `line` is -1 it will return the indentation at the current line. + * If `line` is larger than the number of lines in the document, it will return 0 + */ +int TextDocument::indentationAtLine(int line /* = -1 */) const +{ + LOG(LOG_ARG("line", line)); + + const auto indentText = indentTextAtLine(line); + const auto settings = Core::Settings::instance()->value(Core::Settings::Tab); + return columnAt(indentText, indentText.size(), settings.tabSize) / settings.tabSize; } } // namespace Core diff --git a/src/core/textdocument.h b/src/core/textdocument.h index 974560aa..9ef9aa2b 100644 --- a/src/core/textdocument.h +++ b/src/core/textdocument.h @@ -194,8 +194,10 @@ public slots: void removeIndentAtLine(int count, int line); void setIndentation(int indent); void setIndentationAtLine(int indent, int line); - QString indentationAtPosition(int pos); - QString indentationAtLine(int line = -1); + int indentationAtPosition(int pos) const; + int indentationAtLine(int line = -1) const; + QString indentTextAtPosition(int pos) const; + QString indentTextAtLine(int line = -1) const; signals: void positionChanged(); diff --git a/test_data/tst_textdocument/indent/indent.txt.expected b/test_data/tst_textdocument/indent/indent.txt.expected index 092c91d1..2d7e8c87 100644 --- a/test_data/tst_textdocument/indent/indent.txt.expected +++ b/test_data/tst_textdocument/indent/indent.txt.expected @@ -1,4 +1,4 @@ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque convallis ipsum ac odio aliquet tincidunt. Mauris ut magna vitae mauris fringilla condimentum. @@ -26,4 +26,4 @@ Mauris ut magna vitae mauris fringilla condimentum. Quisque convallis ipsum ac odio aliquet tincidunt. Mauris ut magna vitae mauris fringilla condimentum. - Proin non mi placerat, ultricies diam sit amet, ultricies nisi. + Proin non mi placerat, ultricies diam sit amet, ultricies nisi. diff --git a/test_data/tst_textdocument/indent/indent.txt.original b/test_data/tst_textdocument/indent/indent.txt.original index 70d2a241..78506b82 100644 --- a/test_data/tst_textdocument/indent/indent.txt.original +++ b/test_data/tst_textdocument/indent/indent.txt.original @@ -1,4 +1,4 @@ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque convallis ipsum ac odio aliquet tincidunt. Mauris ut magna vitae mauris fringilla condimentum. @@ -26,4 +26,4 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque convallis ipsum ac odio aliquet tincidunt. Mauris ut magna vitae mauris fringilla condimentum. - Proin non mi placerat, ultricies diam sit amet, ultricies nisi. + Proin non mi placerat, ultricies diam sit amet, ultricies nisi. diff --git a/tests/tst_textdocument.cpp b/tests/tst_textdocument.cpp index 5898fb45..2dca29f2 100644 --- a/tests/tst_textdocument.cpp +++ b/tests/tst_textdocument.cpp @@ -352,6 +352,15 @@ private slots: auto spaces = [](int count) { return QString(count, ' '); }; +#define COMPARE_LINE_INDENT(LINE, TEXT, INDENT) \ + QCOMPARE(document.indentTextAtLine(LINE), TEXT); \ + QCOMPARE(document.indentationAtLine(LINE), INDENT); + +#define COMPARE_CURRENT_INDENT(TEXT, INDENT) \ + QCOMPARE(document.indentationAtPosition(document.position()), INDENT); \ + QCOMPARE(document.indentationAtLine(-1), INDENT); \ + QCOMPARE(document.indentTextAtPosition(document.position()), TEXT); \ + QCOMPARE(document.indentTextAtLine(-1), TEXT); Test::FileTester file(Test::testDataPath() + "/tst_textdocument/indent/indent.txt"); { @@ -359,27 +368,24 @@ private slots: Core::TextDocument document; document.load(file.fileName()); - QCOMPARE(document.indentationAtLine(1), spaces(4)); - QCOMPARE(document.indentationAtLine(7), " \t\t\t\t"); - QCOMPARE(document.indentationAtLine(29), spaces(2)); + COMPARE_LINE_INDENT(1, spaces(2), 0); + COMPARE_LINE_INDENT(7, " \t\t\t\t", 4); + COMPARE_LINE_INDENT(29, spaces(4), 1); // If the line number is larger than the line count, an empty string is returned - QVERIFY(document.indentationAtLine(50).isEmpty()); + COMPARE_LINE_INDENT(50, "", 0); document.gotoLine(4); document.indent(); - QCOMPARE(document.indentationAtPosition(document.position()), spaces(4)); - QCOMPARE(document.indentationAtLine(-1), spaces(4)); + COMPARE_CURRENT_INDENT(spaces(4), 1) // Test that we can correctly detect columns in mixed tabs and spaces. // In this test, the first column contains 2 spaces and a tab. // Because our tabsize is 4 spaces, the first 2 spaces and the tab combine into the first column. // When we remove 2 levels of indentation, that will result in 2 columns left (aka. 8 spaces). document.gotoLine(7, 4); - QCOMPARE(document.indentationAtPosition(document.position()), " \t\t\t\t"); - QCOMPARE(document.indentationAtLine(-1), " \t\t\t\t"); + COMPARE_CURRENT_INDENT(" \t\t\t\t", 4) document.removeIndent(2); - QCOMPARE(document.indentationAtPosition(document.position()), spaces(8)); - QCOMPARE(document.indentationAtLine(-1), spaces(8)); + COMPARE_CURRENT_INDENT(spaces(8), 2) document.gotoLine(10); document.selectNextLine(); @@ -401,6 +407,8 @@ private slots: QVERIFY(file.compare()); } +#undef COMPARE_CURRENT_INDENT +#undef COMPARE_LINE_INDENT } void findReplace()