File indexing completed on 2024-04-28 03:57:11
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2014 Miquel Sabaté Solà <mikisabate@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "view.h" 0009 #include <QClipboard> 0010 #include <QFontDatabase> 0011 #include <inputmode/kateviinputmode.h> 0012 #include <katebuffer.h> 0013 #include <kateconfig.h> 0014 #include <katedocument.h> 0015 #include <kateview.h> 0016 0017 #include <QMainWindow> 0018 #include <QTest> 0019 0020 using namespace KTextEditor; 0021 0022 QTEST_MAIN(ViewTest) 0023 0024 void ViewTest::yankHighlightingTests() 0025 { 0026 const QColor yankHighlightColour = kate_view->rendererConfig()->savedLineColor(); 0027 0028 BeginTest(QStringLiteral("foo bar xyz")); 0029 const QList<Kate::TextRange *> rangesInitial = rangesOnFirstLine(); 0030 Q_ASSERT(rangesInitial.isEmpty() && "Assumptions about ranges are wrong - this test is invalid and may need updating!"); 0031 TestPressKey(QStringLiteral("wyiw")); 0032 { 0033 const QList<Kate::TextRange *> rangesAfterYank = rangesOnFirstLine(); 0034 QCOMPARE(rangesAfterYank.size(), rangesInitial.size() + 1); 0035 QCOMPARE(rangesAfterYank.first()->attribute()->background().color(), yankHighlightColour); 0036 QCOMPARE(rangesAfterYank.first()->start().line(), 0); 0037 QCOMPARE(rangesAfterYank.first()->start().column(), 4); 0038 QCOMPARE(rangesAfterYank.first()->end().line(), 0); 0039 QCOMPARE(rangesAfterYank.first()->end().column(), 7); 0040 } 0041 FinishTest("foo bar xyz"); 0042 0043 BeginTest(QStringLiteral("foom bar xyz")); 0044 TestPressKey(QStringLiteral("wY")); 0045 { 0046 const QList<Kate::TextRange *> rangesAfterYank = rangesOnFirstLine(); 0047 QCOMPARE(rangesAfterYank.size(), rangesInitial.size() + 1); 0048 QCOMPARE(rangesAfterYank.first()->attribute()->background().color(), yankHighlightColour); 0049 QCOMPARE(rangesAfterYank.first()->start().line(), 0); 0050 QCOMPARE(rangesAfterYank.first()->start().column(), 5); 0051 QCOMPARE(rangesAfterYank.first()->end().line(), 0); 0052 QCOMPARE(rangesAfterYank.first()->end().column(), 12); 0053 } 0054 FinishTest("foom bar xyz"); 0055 0056 // Unhighlight on keypress. 0057 DoTest("foo bar xyz", "yiww", "foo bar xyz"); 0058 QCOMPARE(rangesOnFirstLine().size(), rangesInitial.size()); 0059 0060 // Update colour on config change. 0061 DoTest("foo bar xyz", "yiw", "foo bar xyz"); 0062 const QColor newYankHighlightColour = QColor(255, 0, 0); 0063 kate_view->rendererConfig()->setSavedLineColor(newYankHighlightColour); 0064 QCOMPARE(rangesOnFirstLine().first()->attribute()->background().color(), newYankHighlightColour); 0065 0066 // Visual Mode. 0067 DoTest("foo", "viwy", "foo"); 0068 QCOMPARE(rangesOnFirstLine().size(), rangesInitial.size() + 1); 0069 0070 // Unhighlight on keypress in Visual Mode 0071 DoTest("foo", "viwyw", "foo"); 0072 QCOMPARE(rangesOnFirstLine().size(), rangesInitial.size()); 0073 0074 // Add a yank highlight and directly (i.e. without using Vim commands, 0075 // which would clear the highlight) delete all text; if this deletes the yank highlight behind our back 0076 // and we don't respond correctly to this, it will be double-deleted by KateViNormalMode. 0077 // Currently, this seems like it doesn't occur, but better safe than sorry :) 0078 BeginTest(QStringLiteral("foo bar xyz")); 0079 TestPressKey(QStringLiteral("yiw")); 0080 QCOMPARE(rangesOnFirstLine().size(), rangesInitial.size() + 1); 0081 kate_document->documentReload(); 0082 kate_document->clear(); 0083 vi_input_mode->reset(); 0084 vi_input_mode_manager = vi_input_mode->viInputModeManager(); 0085 FinishTest(""); 0086 } 0087 0088 void ViewTest::visualLineUpDownTests() 0089 { 0090 // Need to ensure we have dynamic wrap, a fixed width font, and a decent size kate_view. 0091 ensureKateViewVisible(); 0092 const QFont oldFont = kate_view->rendererConfig()->baseFont(); 0093 QFont fixedWidthFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); 0094 kate_view->rendererConfig()->setFont(fixedWidthFont); 0095 const bool oldDynWordWrap = KateViewConfig::global()->dynWordWrap(); 0096 KateViewConfig::global()->setDynWordWrap(true); 0097 const bool oldReplaceTabsDyn = kate_document->config()->replaceTabsDyn(); 0098 kate_document->config()->setReplaceTabsDyn(false); 0099 const int oldTabWidth = kate_document->config()->tabWidth(); 0100 const int tabWidth = 5; 0101 kate_document->config()->setTabWidth(tabWidth); 0102 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollbars, KateViewConfig::ScrollbarMode::AlwaysOn); 0103 0104 // Compute the maximum width of text before line-wrapping sets it. 0105 int textWrappingLength = 1; 0106 while (true) { 0107 QString text = QStringLiteral("X").repeated(textWrappingLength) + QLatin1Char(' ') + QLatin1Char('O'); 0108 const int posOfO = text.length() - 1; 0109 kate_document->setText(text); 0110 if (kate_view->cursorToCoordinate(Cursor(0, posOfO)).y() != kate_view->cursorToCoordinate(Cursor(0, 0)).y()) { 0111 textWrappingLength++; // Number of x's, plus space. 0112 break; 0113 } 0114 textWrappingLength++; 0115 } 0116 const QString fillsLineAndEndsOnSpace = QStringLiteral("X").repeated(textWrappingLength - 1) + QLatin1Char(' '); 0117 0118 // Create a QString consisting of enough concatenated fillsLineAndEndsOnSpace to completely 0119 // fill the viewport of the kate View. 0120 QString fillsView = fillsLineAndEndsOnSpace; 0121 while (true) { 0122 kate_document->setText(fillsView); 0123 const QString visibleText = kate_document->text(kate_view->visibleRange()); 0124 if (fillsView.length() > visibleText.length() * 2) { // Overkill. 0125 break; 0126 } 0127 fillsView += fillsLineAndEndsOnSpace; 0128 } 0129 const int numVisibleLinesToFillView = fillsView.length() / fillsLineAndEndsOnSpace.length(); 0130 0131 { 0132 // gk/ gj when there is only one line. 0133 DoTest("foo", "lgkr.", "f.o"); 0134 DoTest("foo", "lgjr.", "f.o"); 0135 } 0136 0137 { 0138 // gk when sticky bit is set to the end. 0139 const QString originalText = fillsLineAndEndsOnSpace.repeated(2); 0140 QString expectedText = originalText; 0141 kate_document->setText(originalText); 0142 Q_ASSERT(expectedText[textWrappingLength - 1] == QLatin1Char(' ')); 0143 expectedText[textWrappingLength - 1] = QLatin1Char('.'); 0144 DoTest(originalText.toUtf8().constData(), "$gkr.", expectedText.toUtf8().constData()); 0145 } 0146 0147 { 0148 // Regression test: more than fill the view up, go to end, and do gk on wrapped text (used to crash). 0149 // First work out the text that will fill up the view. 0150 QString expectedText = fillsView; 0151 Q_ASSERT(expectedText[expectedText.length() - textWrappingLength - 1] == QLatin1Char(' ')); 0152 expectedText[expectedText.length() - textWrappingLength - 1] = QLatin1Char('.'); 0153 0154 DoTest(fillsView.toUtf8().constData(), "$gkr.", expectedText.toUtf8().constData()); 0155 } 0156 0157 { 0158 // Jump down a few lines all in one go, where we have some variable length lines to navigate. 0159 const int numVisualLinesOnLine[] = {3, 5, 2, 3}; 0160 const int numLines = sizeof(numVisualLinesOnLine) / sizeof(int); 0161 const int startVisualLine = 2; 0162 const int numberLinesToGoDownInOneGo = 10; 0163 0164 int totalVisualLines = 0; 0165 for (int i = 0; i < numLines; i++) { 0166 totalVisualLines += numVisualLinesOnLine[i]; 0167 } 0168 0169 QString startText; 0170 for (int i = 0; i < numLines; i++) { 0171 QString thisLine = fillsLineAndEndsOnSpace.repeated(numVisualLinesOnLine[i]); 0172 // Replace trailing space with carriage return. 0173 thisLine.chop(1); 0174 thisLine.append(QLatin1Char('\n')); 0175 startText += thisLine; 0176 } 0177 QString expectedText = startText; 0178 expectedText[((startVisualLine - 1) + numberLinesToGoDownInOneGo) * fillsLineAndEndsOnSpace.length()] = QLatin1Char('.'); 0179 0180 Q_ASSERT(numberLinesToGoDownInOneGo + startVisualLine < totalVisualLines); 0181 Q_ASSERT(numberLinesToGoDownInOneGo + startVisualLine < numVisibleLinesToFillView); 0182 DoTest(startText.toUtf8().constData(), 0183 QString(QStringLiteral("gj").repeated(startVisualLine - 1) + QString::number(numberLinesToGoDownInOneGo) + QStringLiteral("gjr.")) 0184 .toUtf8() 0185 .constData(), 0186 expectedText.toUtf8().constData()); 0187 // Now go up a few lines. 0188 const int numLinesToGoBackUp = 7; 0189 expectedText = startText; 0190 expectedText[((startVisualLine - 1) + numberLinesToGoDownInOneGo - numLinesToGoBackUp) * fillsLineAndEndsOnSpace.length()] = QLatin1Char('.'); 0191 DoTest(startText.toUtf8().constData(), 0192 QString(QStringLiteral("gj").repeated(startVisualLine - 1) + QString::number(numberLinesToGoDownInOneGo) + QStringLiteral("gj") 0193 + QString::number(numLinesToGoBackUp) + QStringLiteral("gkr.")) 0194 .toUtf8() 0195 .constData(), 0196 expectedText.toUtf8().constData()); 0197 } 0198 0199 { 0200 // Move down enough lines in one go to disappear off the view. 0201 // About half-a-viewport past the end of the current viewport. 0202 const int numberLinesToGoDown = numVisibleLinesToFillView * 3 / 2; 0203 const int visualColumnNumber = 7; 0204 Q_ASSERT(fillsLineAndEndsOnSpace.length() > visualColumnNumber); 0205 QString expectedText = fillsView.repeated(2); 0206 Q_ASSERT(expectedText[expectedText.length() - textWrappingLength - 1] == QLatin1Char(' ')); 0207 expectedText[visualColumnNumber + fillsLineAndEndsOnSpace.length() * numberLinesToGoDown] = QLatin1Char('.'); 0208 0209 DoTest(fillsView.repeated(2).toUtf8().constData(), 0210 QString(QStringLiteral("l").repeated(visualColumnNumber) + QString::number(numberLinesToGoDown) + QStringLiteral("gjr.")).toUtf8().constData(), 0211 expectedText.toUtf8().constData()); 0212 } 0213 0214 { 0215 // Deal with dynamic wrapping and indented blocks - continuations of a line are "invisibly" idented by 0216 // the same amount as the beginning of the line, and we have to subtract this indentation. 0217 const QString unindentedFirstLine = QStringLiteral("stickyhelper\n"); 0218 const int numIndentationSpaces = 5; 0219 Q_ASSERT(textWrappingLength > numIndentationSpaces * 2 /* keep some wriggle room */); 0220 const QString indentedFillsLineEndsOnSpace = 0221 QStringLiteral(" ").repeated(numIndentationSpaces) + QStringLiteral("X").repeated(textWrappingLength - 1 - numIndentationSpaces) + QLatin1Char(' '); 0222 DoTest(QString(unindentedFirstLine + indentedFillsLineEndsOnSpace + QStringLiteral("LINE3")).toUtf8().constData(), 0223 QString(QStringLiteral("l").repeated(numIndentationSpaces) + QStringLiteral("jgjr.")).toUtf8().constData(), 0224 QString(unindentedFirstLine + indentedFillsLineEndsOnSpace + QStringLiteral(".INE3")).toUtf8().constData()); 0225 0226 // The first, non-wrapped portion of the line is not invisibly indented, though, so ensure we don't mess that up. 0227 QString expectedSecondLine = indentedFillsLineEndsOnSpace; 0228 expectedSecondLine[numIndentationSpaces] = QLatin1Char('.'); 0229 DoTest(QString(unindentedFirstLine + indentedFillsLineEndsOnSpace + QStringLiteral("LINE3")).toUtf8().constData(), 0230 QString(QStringLiteral("l").repeated(numIndentationSpaces) + QStringLiteral("jgjgkr.")).toUtf8().constData(), 0231 (unindentedFirstLine + expectedSecondLine + QStringLiteral("LINE3")).toUtf8().constData()); 0232 } 0233 0234 { 0235 // Take into account any invisible indentation when setting the sticky column. 0236 const int numIndentationSpaces = 5; 0237 Q_ASSERT(textWrappingLength > numIndentationSpaces * 2 /* keep some wriggle room */); 0238 const QString indentedFillsLineEndsOnSpace = 0239 QStringLiteral(" ").repeated(numIndentationSpaces) + QStringLiteral("X").repeated(textWrappingLength - 1 - numIndentationSpaces) + QLatin1Char(' '); 0240 const int posInSecondWrappedLineToChange = 3; 0241 QString expectedText = indentedFillsLineEndsOnSpace + fillsLineAndEndsOnSpace; 0242 expectedText[textWrappingLength + posInSecondWrappedLineToChange] = QLatin1Char('.'); 0243 DoTest((indentedFillsLineEndsOnSpace + fillsLineAndEndsOnSpace).toUtf8().constData(), 0244 (QString::number(textWrappingLength + posInSecondWrappedLineToChange) + QStringLiteral("lgkgjr.")).toUtf8().constData(), 0245 expectedText.toUtf8().constData()); 0246 // Make sure we can do this more than once (i.e. clear any flags that need clearing). 0247 DoTest((indentedFillsLineEndsOnSpace + fillsLineAndEndsOnSpace).toUtf8().constData(), 0248 (QString::number(textWrappingLength + posInSecondWrappedLineToChange) + QStringLiteral("lgkgjr.")).toUtf8().constData(), 0249 expectedText.toUtf8().constData()); 0250 } 0251 0252 { 0253 // Take into account any invisible indentation when setting the sticky column as above, but use tabs. 0254 const QString indentedFillsLineEndsOnSpace = QStringLiteral("\t") + QStringLiteral("X").repeated(textWrappingLength - 1 - tabWidth) + QLatin1Char(' '); 0255 const int posInSecondWrappedLineToChange = 3; 0256 QString expectedText = indentedFillsLineEndsOnSpace + fillsLineAndEndsOnSpace; 0257 expectedText[textWrappingLength - tabWidth + posInSecondWrappedLineToChange] = QLatin1Char('.'); 0258 DoTest(QString(indentedFillsLineEndsOnSpace + fillsLineAndEndsOnSpace).toUtf8().constData(), 0259 QString(QStringLiteral("fXf ") + QString::number(posInSecondWrappedLineToChange) + QStringLiteral("lgkgjr.")).toUtf8().constData(), 0260 expectedText.toUtf8().constData()); 0261 } 0262 0263 { 0264 // Deal with the fact that j/ k may set a sticky column that is impossible to adhere to in visual mode because 0265 // it is too high. 0266 // Here, we have one dummy line and one wrapped line. We start from the beginning of the wrapped line and 0267 // move right until we wrap and end up at posInWrappedLineToChange one the second line of the wrapped line. 0268 // We then move up and down with j and k to set the sticky column to a value to large to adhere to in a 0269 // visual line, and try to move a visual line up. 0270 const QString dummyLineForUseWithK(QStringLiteral("dummylineforusewithk\n")); 0271 QString startText = dummyLineForUseWithK + fillsLineAndEndsOnSpace.repeated(2); 0272 const int posInWrappedLineToChange = 3; 0273 QString expectedText = startText; 0274 expectedText[dummyLineForUseWithK.length() + posInWrappedLineToChange] = QLatin1Char('.'); 0275 DoTest(startText.toUtf8().constData(), 0276 QString(QStringLiteral("j") + QString::number(textWrappingLength + posInWrappedLineToChange) + QStringLiteral("lkjgkr.")).toUtf8().constData(), 0277 expectedText.toUtf8().constData()); 0278 } 0279 0280 { 0281 // Ensure gj works in Visual mode. 0282 Q_ASSERT(fillsLineAndEndsOnSpace.toLower() != fillsLineAndEndsOnSpace); 0283 QString expectedText = fillsLineAndEndsOnSpace.toLower() + fillsLineAndEndsOnSpace; 0284 expectedText[textWrappingLength] = expectedText[textWrappingLength].toLower(); 0285 DoTest(fillsLineAndEndsOnSpace.repeated(2).toUtf8().constData(), QStringLiteral("vgjgu").toUtf8().constData(), expectedText.toUtf8().constData()); 0286 } 0287 0288 { 0289 // Ensure gk works in Visual mode. 0290 Q_ASSERT(fillsLineAndEndsOnSpace.toLower() != fillsLineAndEndsOnSpace); 0291 DoTest(fillsLineAndEndsOnSpace.repeated(2).toUtf8().constData(), 0292 QStringLiteral("$vgkgu").toUtf8().constData(), 0293 QString(fillsLineAndEndsOnSpace + fillsLineAndEndsOnSpace.toLower()).toUtf8().constData()); 0294 } 0295 0296 { 0297 // Some tests for how well we handle things with real tabs. 0298 QString beginsWithTabFillsLineEndsOnSpace = QStringLiteral("\t"); 0299 while (beginsWithTabFillsLineEndsOnSpace.length() + (tabWidth - 1) < textWrappingLength - 1) { 0300 beginsWithTabFillsLineEndsOnSpace += QLatin1Char('X'); 0301 } 0302 beginsWithTabFillsLineEndsOnSpace += QLatin1Char(' '); 0303 const QString unindentedFirstLine = QStringLiteral("stockyhelper\n"); 0304 const int posOnThirdLineToChange = 3; 0305 QString expectedThirdLine = fillsLineAndEndsOnSpace; 0306 expectedThirdLine[posOnThirdLineToChange] = QLatin1Char('.'); 0307 DoTest((unindentedFirstLine + beginsWithTabFillsLineEndsOnSpace + fillsLineAndEndsOnSpace).toUtf8().constData(), 0308 QString(QStringLiteral("l").repeated(tabWidth + posOnThirdLineToChange) + QStringLiteral("gjgjr.")).toUtf8().constData(), 0309 (unindentedFirstLine + beginsWithTabFillsLineEndsOnSpace + expectedThirdLine).toUtf8().constData()); 0310 0311 // As above, but go down twice and return to the middle line. 0312 const int posOnSecondLineToChange = 2; 0313 QString expectedSecondLine = beginsWithTabFillsLineEndsOnSpace; 0314 expectedSecondLine[posOnSecondLineToChange + 1 /* "+1" as we're not counting the leading tab as a pos */] = QLatin1Char('.'); 0315 DoTest((unindentedFirstLine + beginsWithTabFillsLineEndsOnSpace + fillsLineAndEndsOnSpace).toUtf8().constData(), 0316 QString(QStringLiteral("l").repeated(tabWidth + posOnSecondLineToChange) + QStringLiteral("gjgjgkr.")).toUtf8().constData(), 0317 QString(unindentedFirstLine + expectedSecondLine + fillsLineAndEndsOnSpace).toUtf8().constData()); 0318 } 0319 0320 // Restore back to how we were before. 0321 kate_view->rendererConfig()->setFont(oldFont); 0322 KateViewConfig::global()->setDynWordWrap(oldDynWordWrap); 0323 kate_document->config()->setReplaceTabsDyn(oldReplaceTabsDyn); 0324 kate_document->config()->setTabWidth(oldTabWidth); 0325 } 0326 0327 void ViewTest::ScrollViewTests() 0328 { 0329 QSKIP("This is too unstable in Jenkins", SkipAll); 0330 0331 // First of all, we have to initialize some sizes and fonts. 0332 ensureKateViewVisible(); 0333 0334 const QFont oldFont = kate_view->rendererConfig()->baseFont(); 0335 QFont fixedWidthFont(QStringLiteral("Monospace")); 0336 0337 fixedWidthFont.setStyleHint(QFont::TypeWriter); 0338 fixedWidthFont.setPixelSize(14); 0339 Q_ASSERT_X(QFontInfo(fixedWidthFont).fixedPitch(), "setting up ScrollViewTests", "Need a fixed pitch font!"); 0340 kate_view->rendererConfig()->setFont(fixedWidthFont); 0341 0342 // Generating our text here. 0343 QString text; 0344 for (int i = 0; i < 20; i++) { 0345 text += QLatin1String(" aaaaaaaaaaaaaaaa\n"); 0346 } 0347 0348 // TODO: fix the visibleRange's tests. 0349 0350 // zz 0351 BeginTest(text); 0352 TestPressKey(QStringLiteral("10l9jzz")); 0353 QCOMPARE(kate_view->cursorPosition().line(), 9); 0354 QCOMPARE(kate_view->cursorPosition().column(), 10); 0355 QCOMPARE(kate_view->visibleRange(), Range(4, 0, 13, 20)); 0356 FinishTest(text.toUtf8().constData()); 0357 0358 // z. 0359 BeginTest(text); 0360 TestPressKey(QStringLiteral("10l9jz.")); 0361 QCOMPARE(kate_view->cursorPosition().line(), 9); 0362 QCOMPARE(kate_view->cursorPosition().column(), 4); 0363 QCOMPARE(kate_view->visibleRange(), Range(4, 0, 13, 20)); 0364 FinishTest(text.toUtf8().constData()); 0365 0366 // zt 0367 BeginTest(text); 0368 TestPressKey(QStringLiteral("10l9jzt")); 0369 QCOMPARE(kate_view->cursorPosition().line(), 9); 0370 QCOMPARE(kate_view->cursorPosition().column(), 10); 0371 QCOMPARE(kate_view->visibleRange(), Range(9, 0, 18, 20)); 0372 FinishTest(text.toUtf8().constData()); 0373 0374 // z<cr> 0375 BeginTest(text); 0376 TestPressKey(QStringLiteral("10l9jz\\return")); 0377 QCOMPARE(kate_view->cursorPosition().line(), 9); 0378 QCOMPARE(kate_view->cursorPosition().column(), 4); 0379 QCOMPARE(kate_view->visibleRange(), Range(9, 0, 18, 20)); 0380 FinishTest(text.toUtf8().constData()); 0381 0382 // zb 0383 BeginTest(text); 0384 TestPressKey(QStringLiteral("10l9jzb")); 0385 QCOMPARE(kate_view->cursorPosition().line(), 9); 0386 QCOMPARE(kate_view->cursorPosition().column(), 10); 0387 QCOMPARE(kate_view->visibleRange(), Range(0, 0, 9, 20)); 0388 FinishTest(text.toUtf8().constData()); 0389 0390 // z- 0391 BeginTest(text); 0392 TestPressKey(QStringLiteral("10l9jz-")); 0393 QCOMPARE(kate_view->cursorPosition().line(), 9); 0394 QCOMPARE(kate_view->cursorPosition().column(), 4); 0395 QCOMPARE(kate_view->visibleRange(), Range(0, 0, 9, 20)); 0396 FinishTest(text.toUtf8().constData()); 0397 0398 // Restore back to how we were before. 0399 kate_view->rendererConfig()->setFont(oldFont); 0400 } 0401 0402 void ViewTest::clipboardTests_data() 0403 { 0404 QTest::addColumn<QString>("text"); 0405 QTest::addColumn<QString>("commands"); 0406 QTest::addColumn<QString>("clipboard"); 0407 0408 QTest::newRow("yank") << "yyfoo\nbar" 0409 << "yy" 0410 << "yyfoo\n"; 0411 QTest::newRow("delete") << "ddfoo\nbar" 0412 << "dd" 0413 << "ddfoo\n"; 0414 QTest::newRow("yank empty line") << "\nbar" 0415 << "yy" << QString(); 0416 QTest::newRow("delete word") << "word foo" 0417 << "dw" 0418 << "word "; 0419 QTest::newRow("delete onechar word") << "w foo" 0420 << "dw" 0421 << "w "; 0422 QTest::newRow("delete onechar") << "word foo" 0423 << "dc" << QString(); 0424 QTest::newRow("delete empty lines") << " \t\n\n \nfoo" 0425 << "d3d" << QString(); 0426 } 0427 0428 void ViewTest::clipboardTests() 0429 { 0430 QFETCH(QString, text); 0431 QFETCH(QString, commands); 0432 QFETCH(QString, clipboard); 0433 0434 QApplication::clipboard()->clear(); 0435 BeginTest(text); 0436 TestPressKey(commands); 0437 QCOMPARE(QApplication::clipboard()->text(), clipboard); 0438 } 0439 0440 QList<Kate::TextRange *> ViewTest::rangesOnFirstLine() 0441 { 0442 return kate_document->buffer().rangesForLine(0, kate_view, true); 0443 } 0444 0445 #include "moc_view.cpp"