File indexing completed on 2024-05-12 15:45:14
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 "keys.h" 0009 #include "emulatedcommandbarsetupandteardown.h" 0010 #include "fakecodecompletiontestmodel.h" 0011 #include "vimode/globalstate.h" 0012 #include "vimode/mappings.h" 0013 #include <KLocalizedString> 0014 #include <inputmode/kateviinputmode.h> 0015 #include <kateconfig.h> 0016 #include <katedocument.h> 0017 #include <kateview.h> 0018 #include <vimode/emulatedcommandbar/emulatedcommandbar.h> 0019 #include <vimode/keymapper.h> 0020 #include <vimode/keyparser.h> 0021 0022 using namespace KTextEditor; 0023 using KateVi::KeyParser; 0024 using KateVi::Mappings; 0025 0026 QTEST_MAIN(KeysTest) 0027 0028 // BEGIN: KeysTest 0029 0030 void KeysTest::MappingTests() 0031 { 0032 // QVERIFY(false); 0033 const int mappingTimeoutMSOverride = QString::fromLocal8Bit(qgetenv("KATE_VIMODE_TEST_MAPPINGTIMEOUTMS")).toInt(); 0034 const int mappingTimeoutMS = (mappingTimeoutMSOverride > 0) ? mappingTimeoutMSOverride : 2000; 0035 KateViewConfig::global()->setValue(KateViewConfig::ViInputModeStealKeys, true); // For tests involving e.g. <c-a> 0036 { 0037 // Check storage and retrieval of mapping recursion. 0038 clearAllMappings(); 0039 0040 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello", Mappings::Recursive); 0041 QVERIFY(vi_global->mappings()->isRecursive(Mappings::NormalModeMapping, "'")); 0042 0043 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "ihello", Mappings::NonRecursive); 0044 QVERIFY(!vi_global->mappings()->isRecursive(Mappings::NormalModeMapping, "a")); 0045 } 0046 0047 clearAllMappings(); 0048 0049 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "<esc>ihello<esc>^aworld<esc>", Mappings::Recursive); 0050 DoTest("", "'", "hworldello"); 0051 0052 // Ensure that the non-mapping logged keypresses are cleared before we execute a mapping 0053 vi_global->mappings()->add(Mappings::NormalModeMapping, "'a", "rO", Mappings::Recursive); 0054 DoTest("X", "'a", "O"); 0055 0056 { 0057 // Check that '123 is mapped after the timeout, given that we also have mappings that 0058 // extend it (e.g. '1234, '12345, etc) and which it itself extends ('1, '12, etc). 0059 clearAllMappings(); 0060 BeginTest(""); 0061 vi_input_mode_manager->keyMapper()->setMappingTimeout(mappingTimeoutMS); 0062 ; 0063 QString consectiveDigits; 0064 for (int i = 1; i < 9; i++) { 0065 consectiveDigits += QString::number(i); 0066 vi_global->mappings()->add(Mappings::NormalModeMapping, '\'' + consectiveDigits, "iMapped from " + consectiveDigits + "<esc>", Mappings::Recursive); 0067 } 0068 TestPressKey("'123"); 0069 QCOMPARE(kate_document->text(), QString()); // Shouldn't add anything until after the timeout! 0070 QTest::qWait(2 * mappingTimeoutMS); 0071 FinishTest("Mapped from 123"); 0072 } 0073 0074 // Mappings are not "counted": any count entered applies to the first command/ motion in the mapped sequence, 0075 // and is not used to replay the entire mapped sequence <count> times in a row. 0076 clearAllMappings(); 0077 vi_global->mappings()->add(Mappings::NormalModeMapping, "'downmapping", "j", Mappings::Recursive); 0078 vi_global->mappings()->add(Mappings::NormalModeMapping, "'testmapping", "ifoo<esc>ibar<esc>", Mappings::Recursive); 0079 vi_global->mappings()->add(Mappings::NormalModeMapping, "'testmotionmapping", "lj", Mappings::Recursive); 0080 DoTest("AAAA\nXXXX\nXXXX\nXXXX\nXXXX\nBBBB\nCCCC\nDDDD", "jd3'downmapping", "AAAA\nBBBB\nCCCC\nDDDD"); 0081 DoTest("", "5'testmapping", "foofoofoofoofobaro"); 0082 DoTest("XXXX\nXXXX\nXXXX\nXXXX", "3'testmotionmappingrO", "XXXX\nXXXO\nXXXX\nXXXX"); 0083 0084 // Regression test for a weird mistake I made: *completely* remove all counting for the 0085 // first command in the sequence; don't just set it to 1! If it is set to 1, then "%" 0086 // will mean "go to position 1 percent of the way through the document" rather than 0087 // go to matching item. 0088 clearAllMappings(); 0089 vi_global->mappings()->add(Mappings::NormalModeMapping, "gl", "%", Mappings::Recursive); 0090 DoTest("0\n1\n2\n3\n4\n5\nfoo bar(xyz) baz", "jjjjjjwdgl", "0\n1\n2\n3\n4\n5\nfoo baz"); 0091 0092 // Test that countable mappings work even when triggered by timeouts. 0093 clearAllMappings(); 0094 vi_global->mappings()->add(Mappings::NormalModeMapping, "'testmapping", "ljrO", Mappings::Recursive); 0095 vi_global->mappings()->add(Mappings::NormalModeMapping, "'testmappingdummy", "dummy", Mappings::Recursive); 0096 BeginTest("XXXX\nXXXX\nXXXX\nXXXX"); 0097 vi_input_mode_manager->keyMapper()->setMappingTimeout(mappingTimeoutMS); 0098 ; 0099 TestPressKey("3'testmapping"); 0100 QTest::qWait(2 * mappingTimeoutMS); 0101 FinishTest("XXXX\nXXXO\nXXXX\nXXXX"); 0102 0103 // Test that telescoping mappings don't interfere with built-in commands. Assumes that gp 0104 // is implemented and working. 0105 clearAllMappings(); 0106 vi_global->mappings()->add(Mappings::NormalModeMapping, "gdummy", "idummy", Mappings::Recursive); 0107 DoTest("hello", "yiwgpx", "hhellollo"); 0108 0109 // Test that we can map a sequence of keys that extends a built-in command and use 0110 // that sequence without the built-in command firing. 0111 // Once again, assumes that gp is implemented and working. 0112 clearAllMappings(); 0113 vi_global->mappings()->add(Mappings::NormalModeMapping, "gpa", "idummy", Mappings::Recursive); 0114 DoTest("hello", "yiwgpa", "dummyhello"); 0115 0116 // Test that we can map a sequence of keys that extends a built-in command and still 0117 // have the original built-in command fire if we timeout after entering that command. 0118 // Once again, assumes that gp is implemented and working. 0119 clearAllMappings(); 0120 vi_global->mappings()->add(Mappings::NormalModeMapping, "gpa", "idummy", Mappings::Recursive); 0121 BeginTest("hello"); 0122 vi_input_mode_manager->keyMapper()->setMappingTimeout(mappingTimeoutMS); 0123 ; 0124 TestPressKey("yiwgp"); 0125 QTest::qWait(2 * mappingTimeoutMS); 0126 TestPressKey("x"); 0127 FinishTest("hhellollo"); 0128 0129 // Test that something that starts off as a partial mapping following a command 0130 // (the "g" in the first "dg" is a partial mapping of "gj"), when extended to something 0131 // that is definitely not a mapping ("gg"), results in the full command being executed ("dgg"). 0132 clearAllMappings(); 0133 vi_global->mappings()->add(Mappings::NormalModeMapping, "gj", "aj", Mappings::Recursive); 0134 DoTest("foo\nbar\nxyz", "jjdgg", ""); 0135 0136 // Make sure that a mapped sequence of commands is merged into a single undo-able edit. 0137 clearAllMappings(); 0138 vi_global->mappings()->add(Mappings::NormalModeMapping, "'a", "ofoo<esc>ofoo<esc>ofoo<esc>", Mappings::Recursive); 0139 DoTest("bar", "'au", "bar"); 0140 0141 // Make sure that a counted mapping is merged into a single undoable edit. 0142 clearAllMappings(); 0143 vi_global->mappings()->add(Mappings::NormalModeMapping, "'a", "ofoo<esc>", Mappings::Recursive); 0144 DoTest("bar", "5'au", "bar"); 0145 0146 // Some test setup for non-recursive mapping g -> gj (cf: bug:314415) 0147 // Firstly: work out the expected result of gj (this might be fragile as default settings 0148 // change, etc.). We use BeginTest & FinishTest for the setup and teardown etc, but this is 0149 // not an actual test - it's just computing the expected result of the real test! 0150 const QString multiVirtualLineText = 0151 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo " 0152 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo " 0153 "foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo"; 0154 ensureKateViewVisible(); // Needs to be visible in order for virtual lines to make sense. 0155 KateViewConfig::global()->setDynWordWrap(true); 0156 BeginTest(multiVirtualLineText); 0157 TestPressKey("gjrX"); 0158 const QString expectedAfterVirtualLineDownAndChange = kate_document->text(); 0159 Q_ASSERT_X(expectedAfterVirtualLineDownAndChange.contains("X") && !expectedAfterVirtualLineDownAndChange.startsWith('X'), 0160 "setting up j->gj testcase data", 0161 "gj doesn't seem to have worked correctly!"); 0162 FinishTest(expectedAfterVirtualLineDownAndChange); 0163 0164 // Test that non-recursive mappings are not expanded. 0165 clearAllMappings(); 0166 vi_global->mappings()->add(Mappings::NormalModeMapping, "j", "gj", Mappings::NonRecursive); 0167 DoTest(multiVirtualLineText, "jrX", expectedAfterVirtualLineDownAndChange); 0168 KateViewConfig::global()->setDynWordWrap(false); 0169 0170 // Test that recursive mappings are expanded. 0171 clearAllMappings(); 0172 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "X", Mappings::Recursive); 0173 vi_global->mappings()->add(Mappings::NormalModeMapping, "X", "rx", Mappings::Recursive); 0174 DoTest("foo", "la", "fxo"); 0175 0176 // Test that the flag that stops mappings being expanded is reset after the mapping has been executed. 0177 clearAllMappings(); 0178 vi_global->mappings()->add(Mappings::NormalModeMapping, "j", "gj", Mappings::NonRecursive); 0179 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "X", Mappings::Recursive); 0180 vi_global->mappings()->add(Mappings::NormalModeMapping, "X", "rx", Mappings::Recursive); 0181 DoTest("foo", "jla", "fxo"); 0182 0183 // Even if we start with a recursive mapping, as soon as we hit one that is not recursive, we should stop 0184 // expanding. 0185 clearAllMappings(); 0186 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "X", Mappings::NonRecursive); 0187 vi_global->mappings()->add(Mappings::NormalModeMapping, "X", "r.", Mappings::Recursive); 0188 vi_global->mappings()->add(Mappings::NormalModeMapping, "i", "a", Mappings::Recursive); 0189 DoTest("foo", "li", "oo"); 0190 0191 // Regression test: Using a mapping may trigger a call to updateSelection(), which can change the mode 0192 // from VisualLineMode to plain VisualMode. 0193 clearAllMappings(); 0194 vi_global->mappings()->add(Mappings::VisualModeMapping, "gA", "%", Mappings::NonRecursive); 0195 DoTest("xyz\nfoo\n{\nbar\n}", "jVjgAdgglP", "foo\n{\nbar\n}\nxyz"); 0196 // Piggy back on the previous test with a regression test for issue where, if gA is mapped to %, vgly 0197 // will yank one more character than it should. 0198 DoTest("foo(bar)X", "vgAyp", "ffoo(bar)oo(bar)X"); 0199 // Make sure that a successful mapping does not break the "if we select stuff externally in Normal mode, 0200 // we should switch to Visual Mode" thing. 0201 clearAllMappings(); 0202 vi_global->mappings()->add(Mappings::NormalModeMapping, "gA", "%", Mappings::NonRecursive); 0203 BeginTest("foo bar xyz()"); 0204 TestPressKey("gAr."); 0205 kate_view->setSelection(Range(0, 1, 0, 4)); // Actually selects "oo " (i.e. without the "b"). 0206 TestPressKey("d"); 0207 FinishTest("fbar xyz(."); 0208 0209 // Regression tests for BUG:260655 0210 clearAllMappings(); 0211 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "f", Mappings::NonRecursive); 0212 vi_global->mappings()->add(Mappings::NormalModeMapping, "d", "i", Mappings::NonRecursive); 0213 DoTest("foo dar", "adr.", "foo .ar"); 0214 clearAllMappings(); 0215 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "F", Mappings::NonRecursive); 0216 vi_global->mappings()->add(Mappings::NormalModeMapping, "d", "i", Mappings::NonRecursive); 0217 DoTest("foo dar", "$adr.", "foo .ar"); 0218 clearAllMappings(); 0219 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "t", Mappings::NonRecursive); 0220 vi_global->mappings()->add(Mappings::NormalModeMapping, "d", "i", Mappings::NonRecursive); 0221 DoTest("foo dar", "adr.", "foo.dar"); 0222 clearAllMappings(); 0223 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "T", Mappings::NonRecursive); 0224 vi_global->mappings()->add(Mappings::NormalModeMapping, "d", "i", Mappings::NonRecursive); 0225 DoTest("foo dar", "$adr.", "foo d.r"); 0226 clearAllMappings(); 0227 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "r", Mappings::NonRecursive); 0228 vi_global->mappings()->add(Mappings::NormalModeMapping, "d", "i", Mappings::NonRecursive); 0229 DoTest("foo dar", "ad", "doo dar"); 0230 // Feel free to map the keypress after that, though. 0231 DoTest("foo dar", "addber\\esc", "berdoo dar"); 0232 // Also, be careful about how we interpret "waiting for find char/ replace char" 0233 DoTest("foo dar", "ffas", "soo dar"); 0234 0235 // Ignore raw "Ctrl", "Shift", "Meta" and "Alt" keys, which will almost certainly end up being pressed as 0236 // we try to trigger mappings that contain these keys. 0237 clearAllMappings(); 0238 { 0239 // Ctrl. 0240 vi_global->mappings()->add(Mappings::NormalModeMapping, "<c-a><c-b>", "ictrl<esc>", Mappings::NonRecursive); 0241 BeginTest(""); 0242 QKeyEvent *ctrlKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier); 0243 QApplication::postEvent(kate_view->focusProxy(), ctrlKeyDown); 0244 QApplication::sendPostedEvents(); 0245 TestPressKey("\\ctrl-a"); 0246 ctrlKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier); 0247 QApplication::postEvent(kate_view->focusProxy(), ctrlKeyDown); 0248 QApplication::sendPostedEvents(); 0249 TestPressKey("\\ctrl-b"); 0250 FinishTest("ctrl"); 0251 } 0252 { 0253 // Shift. 0254 vi_global->mappings()->add(Mappings::NormalModeMapping, "<c-a>C", "ishift<esc>", Mappings::NonRecursive); 0255 BeginTest(""); 0256 QKeyEvent *ctrlKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier); 0257 QApplication::postEvent(kate_view->focusProxy(), ctrlKeyDown); 0258 QApplication::sendPostedEvents(); 0259 TestPressKey("\\ctrl-a"); 0260 QKeyEvent *shiftKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier); 0261 QApplication::postEvent(kate_view->focusProxy(), shiftKeyDown); 0262 QApplication::sendPostedEvents(); 0263 TestPressKey("C"); 0264 FinishTest("shift"); 0265 } 0266 { 0267 // Alt. 0268 vi_global->mappings()->add(Mappings::NormalModeMapping, "<c-a><a-b>", "ialt<esc>", Mappings::NonRecursive); 0269 BeginTest(""); 0270 QKeyEvent *ctrlKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier); 0271 QApplication::postEvent(kate_view->focusProxy(), ctrlKeyDown); 0272 QApplication::sendPostedEvents(); 0273 TestPressKey("\\ctrl-a"); 0274 QKeyEvent *altKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier); 0275 QApplication::postEvent(kate_view->focusProxy(), altKeyDown); 0276 QApplication::sendPostedEvents(); 0277 TestPressKey("\\alt-b"); 0278 FinishTest("alt"); 0279 } 0280 { 0281 // Meta. 0282 vi_global->mappings()->add(Mappings::NormalModeMapping, "<c-a><m-b>", "imeta<esc>", Mappings::NonRecursive); 0283 BeginTest(""); 0284 QKeyEvent *ctrlKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Control, Qt::NoModifier); 0285 QApplication::postEvent(kate_view->focusProxy(), ctrlKeyDown); 0286 QApplication::sendPostedEvents(); 0287 TestPressKey("\\ctrl-a"); 0288 QKeyEvent *metaKeyDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Meta, Qt::NoModifier); 0289 QApplication::postEvent(kate_view->focusProxy(), metaKeyDown); 0290 QApplication::sendPostedEvents(); 0291 TestPressKey("\\meta-b"); 0292 FinishTest("meta"); 0293 } 0294 { 0295 // Can have mappings in Visual mode, distinct from Normal mode.. 0296 clearAllMappings(); 0297 vi_global->mappings()->add(Mappings::VisualModeMapping, "a", "3l", Mappings::NonRecursive); 0298 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "inose<esc>", Mappings::NonRecursive); 0299 DoTest("0123456", "lvad", "056"); 0300 0301 // The recursion in Visual Mode is distinct from that of Normal mode. 0302 clearAllMappings(); 0303 vi_global->mappings()->add(Mappings::VisualModeMapping, "b", "<esc>", Mappings::NonRecursive); 0304 vi_global->mappings()->add(Mappings::VisualModeMapping, "a", "b", Mappings::NonRecursive); 0305 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "b", Mappings::Recursive); 0306 DoTest("XXX\nXXX", "lvajd", "XXX"); 0307 clearAllMappings(); 0308 vi_global->mappings()->add(Mappings::VisualModeMapping, "b", "<esc>", Mappings::NonRecursive); 0309 vi_global->mappings()->add(Mappings::VisualModeMapping, "a", "b", Mappings::Recursive); 0310 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "b", Mappings::NonRecursive); 0311 DoTest("XXX\nXXX", "lvajd", "XXX\nXXX"); 0312 0313 // A Visual mode mapping applies to all Visual modes (line, block, etc). 0314 clearAllMappings(); 0315 vi_global->mappings()->add(Mappings::VisualModeMapping, "a", "2j", Mappings::NonRecursive); 0316 DoTest("123\n456\n789", "lvad", "19"); 0317 DoTest("123\n456\n789", "l\\ctrl-vad", "13\n46\n79"); 0318 DoTest("123\n456\n789", "lVad", ""); 0319 // Same for recursion. 0320 clearAllMappings(); 0321 vi_global->mappings()->add(Mappings::VisualModeMapping, "b", "2j", Mappings::NonRecursive); 0322 vi_global->mappings()->add(Mappings::VisualModeMapping, "a", "b", Mappings::Recursive); 0323 DoTest("123\n456\n789", "lvad", "19"); 0324 DoTest("123\n456\n789", "l\\ctrl-vad", "13\n46\n79"); 0325 DoTest("123\n456\n789", "lVad", ""); 0326 0327 // Can clear Visual mode mappings. 0328 clearAllMappings(); 0329 vi_global->mappings()->add(Mappings::VisualModeMapping, "h", "l", Mappings::Recursive); 0330 vi_global->mappings()->clear(Mappings::VisualModeMapping); 0331 DoTest("123\n456\n789", "lvhd", "3\n456\n789"); 0332 DoTest("123\n456\n789", "l\\ctrl-vhd", "3\n456\n789"); 0333 DoTest("123\n456\n789", "lVhd", "456\n789"); 0334 vi_global->mappings()->add(Mappings::VisualModeMapping, "h", "l", Mappings::Recursive); 0335 vi_global->mappings()->clear(Mappings::VisualModeMapping); 0336 DoTest("123\n456\n789", "lvhd", "3\n456\n789"); 0337 DoTest("123\n456\n789", "l\\ctrl-vhd", "3\n456\n789"); 0338 DoTest("123\n456\n789", "lVhd", "456\n789"); 0339 vi_global->mappings()->add(Mappings::VisualModeMapping, "h", "l", Mappings::Recursive); 0340 vi_global->mappings()->clear(Mappings::VisualModeMapping); 0341 DoTest("123\n456\n789", "lvhd", "3\n456\n789"); 0342 DoTest("123\n456\n789", "l\\ctrl-vhd", "3\n456\n789"); 0343 DoTest("123\n456\n789", "lVhd", "456\n789"); 0344 } 0345 { 0346 // Can have mappings in Insert mode. 0347 clearAllMappings(); 0348 vi_global->mappings()->add(Mappings::InsertModeMapping, "a", "xyz", Mappings::NonRecursive); 0349 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "inose<esc>", Mappings::NonRecursive); 0350 DoTest("foo", "ia\\esc", "xyzfoo"); 0351 0352 // Recursion for Insert mode. 0353 clearAllMappings(); 0354 vi_global->mappings()->add(Mappings::InsertModeMapping, "b", "c", Mappings::NonRecursive); 0355 vi_global->mappings()->add(Mappings::InsertModeMapping, "a", "b", Mappings::NonRecursive); 0356 DoTest("", "ia\\esc", "b"); 0357 clearAllMappings(); 0358 vi_global->mappings()->add(Mappings::InsertModeMapping, "b", "c", Mappings::NonRecursive); 0359 vi_global->mappings()->add(Mappings::InsertModeMapping, "a", "b", Mappings::Recursive); 0360 DoTest("", "ia\\esc", "c"); 0361 0362 clearAllMappings(); 0363 // Clear mappings for Insert mode. 0364 vi_global->mappings()->add(Mappings::InsertModeMapping, "a", "b", Mappings::NonRecursive); 0365 vi_global->mappings()->clear(Mappings::InsertModeMapping); 0366 DoTest("", "ia\\esc", "a"); 0367 } 0368 0369 { 0370 EmulatedCommandBarSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow); 0371 // Can have mappings in Emulated Command Bar. 0372 clearAllMappings(); 0373 vi_global->mappings()->add(Mappings::CommandModeMapping, "a", "xyz", Mappings::NonRecursive); 0374 DoTest(" a xyz", "/a\\enterrX", " a Xyz"); 0375 // Use mappings from Normal mode as soon as we exit command bar via Enter. 0376 vi_global->mappings()->add(Mappings::NormalModeMapping, "a", "ixyz<c-c>", Mappings::NonRecursive); 0377 DoTest(" a xyz", "/a\\entera", " a xyzxyz"); 0378 // Multiple mappings. 0379 vi_global->mappings()->add(Mappings::CommandModeMapping, "b", "123", Mappings::NonRecursive); 0380 DoTest(" xyz123", "/ab\\enterrX", " Xyz123"); 0381 // Recursive mappings. 0382 vi_global->mappings()->add(Mappings::CommandModeMapping, "b", "a", Mappings::Recursive); 0383 DoTest(" xyz", "/b\\enterrX", " Xyz"); 0384 // Can clear all. 0385 vi_global->mappings()->clear(Mappings::CommandModeMapping); 0386 DoTest(" ab xyz xyz123", "/ab\\enterrX", " Xb xyz xyz123"); 0387 } 0388 0389 // Test that not *both* of the mapping and the mapped keys are logged for repetition via "." 0390 clearAllMappings(); 0391 vi_global->mappings()->add(Mappings::NormalModeMapping, "ixyz", "iabc", Mappings::NonRecursive); 0392 vi_global->mappings()->add(Mappings::NormalModeMapping, "gl", "%", Mappings::NonRecursive); 0393 DoTest("", "ixyz\\esc.", "ababcc"); 0394 DoTest("foo()X\nbarxyz()Y", "cglbaz\\escggj.", "bazX\nbazY"); 0395 0396 // Regression test for a crash when executing a mapping that switches to Normal mode. 0397 clearAllMappings(); 0398 vi_global->mappings()->add(Mappings::VisualModeMapping, "h", "d", Mappings::Recursive); 0399 DoTest("foo", "vlh", "o"); 0400 0401 { 0402 // Test that we can set/ unset mappings from the command-line. 0403 clearAllMappings(); 0404 DoTest("", "\\:nn foo ibar<esc>\\foo", "bar"); 0405 0406 // "nn" is not recursive. 0407 clearAllMappings(); 0408 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0409 DoTest("xxx", "\\:nn foo l\\foorX", "xXx"); 0410 0411 // "no" is not recursive. 0412 clearAllMappings(); 0413 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0414 DoTest("xxx", "\\:no foo l\\foorX", "xXx"); 0415 0416 // "noremap" is not recursive. 0417 clearAllMappings(); 0418 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0419 DoTest("xxx", "\\:noremap foo l\\foorX", "xXx"); 0420 0421 // "nm" is recursive. 0422 clearAllMappings(); 0423 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0424 DoTest("xxx", "\\:nm foo l\\foorX", "abXxxx"); 0425 0426 // "nmap" is recursive. 0427 clearAllMappings(); 0428 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0429 DoTest("xxx", "\\:nmap foo l\\foorX", "abXxxx"); 0430 0431 // Unfortunately, "map" is a reserved word :/ 0432 clearAllMappings(); 0433 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "iabc<esc>", Mappings::NonRecursive); 0434 DoTest("xxx", "\\:map foo l\\foorX", "abXxxx", ShouldFail, "'map' is reserved for other stuff in Kate command line"); 0435 0436 // nunmap works in normal mode. 0437 clearAllMappings(); 0438 vi_global->mappings()->add(Mappings::NormalModeMapping, "w", "ciwabc<esc>", Mappings::NonRecursive); 0439 vi_global->mappings()->add(Mappings::NormalModeMapping, "b", "ciwxyz<esc>", Mappings::NonRecursive); 0440 DoTest(" 123 456 789", "\\:nunmap b\\WWwbrX", " 123 Xbc 789"); 0441 0442 // nmap and nunmap whose "from" is a complex encoded expression. 0443 clearAllMappings(); 0444 BeginTest("123"); 0445 TestPressKey("\\:nmap <c-9> ciwxyz<esc>\\"); 0446 TestPressKey("\\ctrl-9"); 0447 FinishTest("xyz"); 0448 BeginTest("123"); 0449 TestPressKey("\\:nunmap <c-9>\\"); 0450 TestPressKey("\\ctrl-9"); 0451 FinishTest("123"); 0452 0453 // vmap works in Visual mode and is recursive. 0454 clearAllMappings(); 0455 vi_global->mappings()->add(Mappings::VisualModeMapping, "l", "d", Mappings::NonRecursive); 0456 DoTest("abco", "\\:vmap foo l\\v\\rightfoogU", "co"); 0457 0458 // vmap does not work in Normal mode. 0459 clearAllMappings(); 0460 DoTest("xxx", "\\:vmap foo l\\foorX", "xxx\nrX"); 0461 0462 // vm works in Visual mode and is recursive. 0463 clearAllMappings(); 0464 vi_global->mappings()->add(Mappings::VisualModeMapping, "l", "d", Mappings::NonRecursive); 0465 DoTest("abco", "\\:vm foo l\\v\\rightfoogU", "co"); 0466 0467 // vn works in Visual mode and is not recursive. 0468 clearAllMappings(); 0469 vi_global->mappings()->add(Mappings::VisualModeMapping, "l", "d", Mappings::NonRecursive); 0470 DoTest("abco", "\\:vn foo l\\v\\rightfoogU", "ABCo"); 0471 0472 // vnoremap works in Visual mode and is not recursive. 0473 clearAllMappings(); 0474 vi_global->mappings()->add(Mappings::VisualModeMapping, "l", "d", Mappings::NonRecursive); 0475 DoTest("abco", "\\:vnoremap foo l\\v\\rightfoogU", "ABCo"); 0476 0477 // vunmap works in Visual Mode. 0478 clearAllMappings(); 0479 vi_global->mappings()->add(Mappings::VisualModeMapping, "l", "w", Mappings::NonRecursive); 0480 vi_global->mappings()->add(Mappings::VisualModeMapping, "gU", "2b", Mappings::NonRecursive); 0481 DoTest("foo bar xyz", "\\:vunmap gU\\wvlgUd", "foo BAR Xyz"); 0482 0483 // imap works in Insert mode and is recursive. 0484 clearAllMappings(); 0485 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "d", Mappings::NonRecursive); 0486 DoTest("", "\\:imap foo l\\ifoo\\esc", "d"); 0487 0488 // im works in Insert mode and is recursive. 0489 clearAllMappings(); 0490 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "d", Mappings::NonRecursive); 0491 DoTest("", "\\:im foo l\\ifoo\\esc", "d"); 0492 0493 // ino works in Insert mode and is not recursive. 0494 clearAllMappings(); 0495 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "d", Mappings::NonRecursive); 0496 DoTest("", "\\:ino foo l\\ifoo\\esc", "l"); 0497 0498 // inoremap works in Insert mode and is not recursive. 0499 clearAllMappings(); 0500 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "d", Mappings::NonRecursive); 0501 DoTest("", "\\:inoremap foo l\\ifoo\\esc", "l"); 0502 0503 // iunmap works in Insert mode. 0504 clearAllMappings(); 0505 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "d", Mappings::NonRecursive); 0506 vi_global->mappings()->add(Mappings::InsertModeMapping, "m", "e", Mappings::NonRecursive); 0507 DoTest("", "\\:iunmap l\\ilm\\esc", "le"); 0508 0509 { 0510 EmulatedCommandBarSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow); 0511 // cmap works in emulated command bar and is recursive. 0512 // NOTE: need to do the cmap call using the direct execution (i.e. \\:cmap blah blah\\), *not* using 0513 // the emulated command bar (:cmap blah blah\\enter), as this will be subject to mappings, which 0514 // can interfere with the tests! 0515 clearAllMappings(); 0516 vi_global->mappings()->add(Mappings::CommandModeMapping, "l", "d", Mappings::NonRecursive); 0517 DoTest(" l d foo", "\\:cmap foo l\\/foo\\enterrX", " l X foo"); 0518 0519 // cm works in emulated command bar and is recursive. 0520 clearAllMappings(); 0521 vi_global->mappings()->add(Mappings::CommandModeMapping, "l", "d", Mappings::NonRecursive); 0522 DoTest(" l d foo", "\\:cm foo l\\/foo\\enterrX", " l X foo"); 0523 0524 // cnoremap works in emulated command bar and is recursive. 0525 clearAllMappings(); 0526 vi_global->mappings()->add(Mappings::CommandModeMapping, "l", "d", Mappings::NonRecursive); 0527 DoTest(" l d foo", "\\:cnoremap foo l\\/foo\\enterrX", " X d foo"); 0528 0529 // cno works in emulated command bar and is recursive. 0530 clearAllMappings(); 0531 vi_global->mappings()->add(Mappings::CommandModeMapping, "l", "d", Mappings::NonRecursive); 0532 DoTest(" l d foo", "\\:cno foo l\\/foo\\enterrX", " X d foo"); 0533 0534 // cunmap works in emulated command bar. 0535 clearAllMappings(); 0536 vi_global->mappings()->add(Mappings::CommandModeMapping, "l", "d", Mappings::NonRecursive); 0537 vi_global->mappings()->add(Mappings::CommandModeMapping, "m", "e", Mappings::NonRecursive); 0538 DoTest(" de le", "\\:cunmap l\\/lm\\enterrX", " de Xe"); 0539 } 0540 0541 // Can use <space> to signify a space. 0542 clearAllMappings(); 0543 DoTest("", "\\:nn h<space> i<space>a<space>b<esc>\\h ", " a b"); 0544 } 0545 0546 // More recursion tests - don't lose characters from a Recursive mapping if it looks like they might 0547 // be part of a different mapping (but end up not being so). 0548 // (Here, the leading "i" in "irecursive<c-c>" could be part of the mapping "ihello<c-c>"). 0549 clearAllMappings(); 0550 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>", Mappings::Recursive); 0551 vi_global->mappings()->add(Mappings::NormalModeMapping, "ihello<c-c>", "irecursive<c-c>", Mappings::Recursive); 0552 DoTest("", "'", "recursive"); 0553 0554 // Capslock in insert mode is not handled by Vim nor by KateViewInternal, and ends up 0555 // being sent to KateViInputModeManager::handleKeypress twice (it could be argued that this is 0556 // incorrect behaviour on the part of KateViewInternal), which can cause infinite 0557 // recursion if we are not careful about identifying replayed rejected keypresses. 0558 BeginTest("foo bar"); 0559 TestPressKey("i"); 0560 QKeyEvent *capslockKeyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_CapsLock, Qt::NoModifier); 0561 QApplication::postEvent(kate_view->focusProxy(), capslockKeyPress); 0562 QApplication::sendPostedEvents(); 0563 FinishTest("foo bar"); 0564 0565 // Mapping the u and the U commands to other keys. 0566 clearAllMappings(); 0567 vi_global->mappings()->add(Mappings::NormalModeMapping, "t", "u", Mappings::Recursive); 0568 vi_global->mappings()->add(Mappings::NormalModeMapping, "r", "U", Mappings::Recursive); 0569 DoTest("", "ihello\\esct", ""); 0570 DoTest("", "ihello\\esctr", "hello"); 0571 0572 // <nop> 0573 clearAllMappings(); 0574 vi_global->mappings()->add(Mappings::NormalModeMapping, "l", "<nop>", Mappings::Recursive); 0575 DoTest("Hello", "lrr", "rello"); 0576 clearAllMappings(); 0577 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "<nop>", Mappings::Recursive); 0578 DoTest("Hello", "sl\\esc", "ello"); 0579 clearAllMappings(); 0580 vi_global->mappings()->add(Mappings::InsertModeMapping, "l", "<nop>abc", Mappings::Recursive); 0581 DoTest("Hello", "sl\\esc", "abcello"); 0582 0583 // Clear mappings for subsequent tests. 0584 clearAllMappings(); 0585 0586 { 0587 // Test that g<up> and g<down> work as gk and gj (BUG: 418486) 0588 ensureKateViewVisible(); // Needs to be visible in order for virtual lines to make sense. 0589 KateViewConfig::global()->setDynWordWrap(true); 0590 0591 BeginTest(multiVirtualLineText); 0592 TestPressKey("gjrX"); 0593 const QString expectedAfterVirtualLineDownAndChange = kate_document->text(); 0594 QVERIFY(expectedAfterVirtualLineDownAndChange.contains("X") && !expectedAfterVirtualLineDownAndChange.startsWith('X')); 0595 FinishTest(expectedAfterVirtualLineDownAndChange); 0596 0597 BeginTest(multiVirtualLineText); 0598 TestPressKey("g\\downrX"); 0599 const QString expectedAfterVirtualLineDownAndChangeCursor = kate_document->text(); 0600 QVERIFY(expectedAfterVirtualLineDownAndChangeCursor == expectedAfterVirtualLineDownAndChange); 0601 FinishTest(expectedAfterVirtualLineDownAndChangeCursor); 0602 0603 BeginTest(multiVirtualLineText); 0604 TestPressKey("gkrX"); 0605 const QString expectedAfterVirtualLineUpAndChange = kate_document->text(); 0606 QVERIFY(expectedAfterVirtualLineUpAndChange.contains("X") && !expectedAfterVirtualLineUpAndChange.endsWith('X')); 0607 FinishTest(expectedAfterVirtualLineUpAndChange); 0608 0609 BeginTest(multiVirtualLineText); 0610 TestPressKey("g\\uprX"); 0611 const QString expectedAfterVirtualLineUpAndChangeCursor = kate_document->text(); 0612 QVERIFY(expectedAfterVirtualLineUpAndChangeCursor == expectedAfterVirtualLineUpAndChange); 0613 FinishTest(expectedAfterVirtualLineUpAndChangeCursor); 0614 0615 KateViewConfig::global()->setDynWordWrap(false); 0616 } 0617 } 0618 0619 void KeysTest::LeaderTests() 0620 { 0621 // Clean slate. 0622 KateViewConfig::global()->setValue(KateViewConfig::ViInputModeStealKeys, true); 0623 clearAllMappings(); 0624 0625 // By default the backslash character is the leader. The default leader 0626 // is picked from the config. If we don't want to mess this from other 0627 // tests, it's better if we mock the config. 0628 const QString viTestKConfigFileName = QStringLiteral("vimodetest-leader-katevimoderc"); 0629 KConfig viTestKConfig(viTestKConfigFileName); 0630 vi_global->mappings()->setLeader(QChar()); 0631 vi_global->readConfig(&viTestKConfig); 0632 vi_global->mappings()->add(Mappings::NormalModeMapping, "<leader>i", "ii", Mappings::Recursive); 0633 DoTest("", "\\\\i", "i"); 0634 0635 // We can change the leader and it will work. 0636 clearAllMappings(); 0637 vi_global->readConfig(&viTestKConfig); 0638 vi_global->mappings()->setLeader(QChar::fromLatin1(',')); 0639 vi_global->mappings()->add(Mappings::NormalModeMapping, "<leader>i", "ii", Mappings::Recursive); 0640 DoTest("", ",i", "i"); 0641 0642 // Mixing up the <leader> with its value. 0643 clearAllMappings(); 0644 vi_global->readConfig(&viTestKConfig); 0645 vi_global->mappings()->setLeader(QChar::fromLatin1(',')); 0646 vi_global->mappings()->add(Mappings::NormalModeMapping, "<leader>,", "ii", Mappings::Recursive); 0647 DoTest("", ",,", "i"); 0648 vi_global->mappings()->add(Mappings::NormalModeMapping, ",<leader>", "ii", Mappings::Recursive); 0649 DoTest("", ",,", "i"); 0650 0651 // It doesn't work outside normal mode. 0652 clearAllMappings(); 0653 vi_global->readConfig(&viTestKConfig); 0654 vi_global->mappings()->setLeader(QChar::fromLatin1(',')); 0655 vi_global->mappings()->add(Mappings::InsertModeMapping, "<leader>i", "ii", Mappings::Recursive); 0656 DoTest("", "i,ii", ",ii"); 0657 0658 // Clear mappings for subsequent tests. 0659 clearAllMappings(); 0660 } 0661 0662 void KeysTest::ParsingTests() 0663 { 0664 // BUG #298726 0665 const QChar char_o_diaeresis(246); 0666 0667 // Test that we can correctly translate finnish key ö 0668 QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, 214, Qt::NoModifier, 47, 246, 16400, char_o_diaeresis); 0669 QCOMPARE(KeyParser::self()->KeyEventToQChar(*k), QChar(246)); 0670 0671 // Test that it can be used in mappings 0672 clearAllMappings(); 0673 vi_global->mappings()->add(Mappings::NormalModeMapping, char_o_diaeresis, "ifoo", Mappings::Recursive); 0674 DoTest("hello", QString("ll%1bar").arg(char_o_diaeresis), "hefoobarllo"); 0675 0676 // Test that <cr> is parsed like <enter> 0677 QCOMPARE(KeyParser::self()->vi2qt("cr"), int(Qt::Key_Enter)); 0678 const QString &enter = KeyParser::self()->encodeKeySequence(QLatin1String("<cr>")); 0679 QCOMPARE(KeyParser::self()->decodeKeySequence(enter), QLatin1String("<cr>")); 0680 } 0681 0682 void KeysTest::AltGr() 0683 { 0684 QKeyEvent *altGrDown; 0685 QKeyEvent *altGrUp; 0686 // Test Alt-gr still works - this isn't quite how things work in "real-life": in real-life, something like 0687 // Alt-gr+7 would be a "{", but I don't think this can be reproduced without sending raw X11 0688 // keypresses to Qt, so just duplicate the keypress events we would receive if we pressed 0689 // Alt-gr+7 (that is: Alt-gr down; "{"; Alt-gr up). 0690 0691 // Ensure we have auto brackets off, or the test will fail 0692 kate_view->config()->setValue(KateViewConfig::AutoBrackets, false); 0693 0694 BeginTest(""); 0695 TestPressKey("i"); 0696 altGrDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_AltGr, Qt::NoModifier); 0697 QApplication::postEvent(kate_view->focusProxy(), altGrDown); 0698 QApplication::sendPostedEvents(); 0699 // Not really Alt-gr and 7, but this is the key event that is reported by Qt if we press that. 0700 QKeyEvent *altGrAnd7 = new QKeyEvent(QEvent::KeyPress, Qt::Key_BraceLeft, Qt::GroupSwitchModifier, "{"); 0701 QApplication::postEvent(kate_view->focusProxy(), altGrAnd7); 0702 QApplication::sendPostedEvents(); 0703 altGrUp = new QKeyEvent(QEvent::KeyRelease, Qt::Key_AltGr, Qt::NoModifier); 0704 QApplication::postEvent(kate_view->focusProxy(), altGrUp); 0705 QApplication::sendPostedEvents(); 0706 TestPressKey("\\ctrl-c"); 0707 FinishTest("{"); 0708 0709 // French Bepo keyabord AltGr + Shift + s = Ù = Unicode(0x00D9); 0710 const QString ugrave = QString(QChar(0x00D9)); 0711 BeginTest(""); 0712 TestPressKey("i"); 0713 altGrDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_AltGr, Qt::NoModifier); 0714 QApplication::postEvent(kate_view->focusProxy(), altGrDown); 0715 QApplication::sendPostedEvents(); 0716 altGrDown = new QKeyEvent(QEvent::KeyPress, Qt::Key_Shift, Qt::ShiftModifier | Qt::GroupSwitchModifier); 0717 QApplication::postEvent(kate_view->focusProxy(), altGrDown); 0718 QApplication::sendPostedEvents(); 0719 QKeyEvent *altGrAndUGrave = new QKeyEvent(QEvent::KeyPress, Qt::Key_Ugrave, Qt::ShiftModifier | Qt::GroupSwitchModifier, ugrave); 0720 qDebug() << QString("%1").arg(altGrAndUGrave->modifiers(), 10, 16); 0721 QApplication::postEvent(kate_view->focusProxy(), altGrAndUGrave); 0722 QApplication::sendPostedEvents(); 0723 altGrUp = new QKeyEvent(QEvent::KeyRelease, Qt::Key_AltGr, Qt::NoModifier); 0724 QApplication::postEvent(kate_view->focusProxy(), altGrUp); 0725 QApplication::sendPostedEvents(); 0726 FinishTest(ugrave); 0727 } 0728 0729 void KeysTest::MacroTests() 0730 { 0731 // Update the status on qa. 0732 const QString macroIsRecordingStatus = QLatin1String("(") + i18n("recording") + QLatin1String(")"); 0733 clearAllMacros(); 0734 BeginTest(""); 0735 QVERIFY(!kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0736 TestPressKey("qa"); 0737 QVERIFY(kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0738 TestPressKey("q"); 0739 QVERIFY(!kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0740 FinishTest(""); 0741 0742 // The closing "q" is not treated as the beginning of a new "begin recording macro" command. 0743 clearAllMacros(); 0744 BeginTest("foo"); 0745 TestPressKey("qaqa"); 0746 QVERIFY(!kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0747 TestPressKey("xyz\\esc"); 0748 FinishTest("fxyzoo"); 0749 0750 // Record and playback a single keypress into macro register "a". 0751 clearAllMacros(); 0752 DoTest("foo bar", "qawqgg@arX", "foo Xar"); 0753 // Two macros - make sure the old one is cleared. 0754 clearAllMacros(); 0755 DoTest("123 foo bar xyz", "qawqqabqggww@arX", "123 Xoo bar xyz"); 0756 0757 // Update the status on qb. 0758 clearAllMacros(); 0759 BeginTest(""); 0760 QVERIFY(!kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0761 TestPressKey("qb"); 0762 QVERIFY(kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0763 TestPressKey("q"); 0764 QVERIFY(!kate_view->viewModeHuman().contains(macroIsRecordingStatus)); 0765 FinishTest(""); 0766 0767 // Record and playback a single keypress into macro register "b". 0768 clearAllMacros(); 0769 DoTest("foo bar", "qbwqgg@brX", "foo Xar"); 0770 0771 // More complex macros. 0772 clearAllMacros(); 0773 DoTest("foo", "qcrXql@c", "XXo"); 0774 0775 // Re-recording a macro should only clear that macro. 0776 clearAllMacros(); 0777 DoTest("foo 123", "qaraqqbrbqqbrBqw@a", "Boo a23"); 0778 0779 // Empty macro clears it. 0780 clearAllMacros(); 0781 DoTest("", "qaixyz\\ctrl-cqqaq@a", "xyz"); 0782 0783 // Hold two macros in memory simultanenously so both can be played. 0784 clearAllMacros(); 0785 DoTest("foo 123", "qaraqqbrbqw@al@b", "boo ab3"); 0786 0787 // Do more complex things, including switching modes and using ctrl codes. 0788 clearAllMacros(); 0789 DoTest("foo bar", "qainose\\ctrl-c~qw@a", "nosEfoo nosEbar"); 0790 clearAllMacros(); 0791 DoTest("foo bar", "qayiwinose\\ctrl-r0\\ctrl-c~qw@a", "nosefoOfoo nosebaRbar"); 0792 clearAllMacros(); 0793 DoTest("foo bar", "qavldqw@a", "o r"); 0794 // Make sure we can use "q" in insert mode while recording a macro. 0795 clearAllMacros(); 0796 DoTest("foo bar", "qaiqueequeg\\ctrl-cqw@a", "queequegfoo queequegbar"); 0797 // Can invoke a macro in Visual Mode. 0798 clearAllMacros(); 0799 DoTest("foo bar", "qa~qvlll@a", "FOO Bar"); 0800 // Invoking a macro in Visual Mode does not exit Visual Mode. 0801 clearAllMacros(); 0802 DoTest("foo bar", "qallqggv@a~", "FOO bar"); 0803 ; 0804 // Can record & macros in Visual Mode for playback in Normal Mode. 0805 clearAllMacros(); 0806 DoTest("foo bar", "vqblq\\ctrl-c@b~", "foO bar"); 0807 // Recording a macro in Visual Mode does not exit Visual Mode. 0808 clearAllMacros(); 0809 DoTest("foo bar", "vqblql~", "FOO bar"); 0810 // Recognize correctly numbered registers 0811 clearAllMacros(); 0812 DoTest("foo", "q1iX\\escq@1", "XXfoo"); 0813 0814 { 0815 // Ensure that we can call emulated command bar searches, and that we don't record 0816 // synthetic keypresses. 0817 EmulatedCommandBarSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow); 0818 clearAllMacros(); 0819 DoTest("foo bar\nblank line", "qa/bar\\enterqgg@arX", "foo Xar\nblank line"); 0820 // More complex searching stuff. 0821 clearAllMacros(); 0822 DoTest("foo 123foo123\nbar 123bar123", "qayiw/\\ctrl-r0\\enterrXqggj@a", "foo 123Xoo123\nbar 123Xar123"); 0823 } 0824 0825 // Expand mappings, but don't do *both* original keypresses and executed keypresses. 0826 clearAllMappings(); 0827 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>", Mappings::Recursive); 0828 clearAllMacros(); 0829 DoTest("", "qa'q@a", "hellhelloo"); 0830 // Actually, just do the mapped keypresses, not the executed mappings (like Vim). 0831 clearAllMappings(); 0832 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>", Mappings::Recursive); 0833 clearAllMacros(); 0834 BeginTest(""); 0835 TestPressKey("qa'q"); 0836 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "igoodbye<c-c>", Mappings::Recursive); 0837 TestPressKey("@a"); 0838 FinishTest("hellgoodbyeo"); 0839 // Clear the "stop recording macro keypresses because we're executing a mapping" when the mapping has finished 0840 // executing. 0841 clearAllMappings(); 0842 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>", Mappings::Recursive); 0843 clearAllMacros(); 0844 DoTest("", "qa'ixyz\\ctrl-cq@a", "hellxyhellxyzozo"); 0845 // ... make sure that *all* mappings have finished, though: take into account recursion. 0846 clearAllMappings(); 0847 clearAllMacros(); 0848 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>", Mappings::Recursive); 0849 vi_global->mappings()->add(Mappings::NormalModeMapping, "ihello<c-c>", "irecursive<c-c>", Mappings::Recursive); 0850 DoTest("", "qa'q@a", "recursivrecursivee"); 0851 clearAllMappings(); 0852 clearAllMacros(); 0853 vi_global->mappings()->add(Mappings::NormalModeMapping, "'", "ihello<c-c>ixyz<c-c>", Mappings::Recursive); 0854 vi_global->mappings()->add(Mappings::NormalModeMapping, "ihello<c-c>", "irecursive<c-c>", Mappings::Recursive); 0855 DoTest("", "qa'q@a", "recursivxyrecursivxyzeze"); 0856 0857 clearAllMappings(); 0858 clearAllMacros(); 0859 // Don't save the trailing "q" with macros, and also test that we can call one macro from another, 0860 // without one of the macros being repeated. 0861 DoTest("", "qaixyz\\ctrl-cqqb@aq@b", "xyxyxyzzz"); 0862 clearAllMappings(); 0863 clearAllMacros(); 0864 // More stringent test that macros called from another macro aren't repeated - requires more nesting 0865 // of macros ('a' calls 'b' calls 'c'). 0866 DoTest("", 0867 "qciC\\ctrl-cq" 0868 "qb@ciB\\ctrl-cq" 0869 "qa@biA\\ctrl-cq" 0870 "dd@a", 0871 "ABC"); 0872 // Don't crash if we invoke a non-existent macro. 0873 clearAllMacros(); 0874 DoTest("", "@x", ""); 0875 // Make macros "counted". 0876 clearAllMacros(); 0877 DoTest("XXXX\nXXXX\nXXXX\nXXXX", "qarOljq3@a", "OXXX\nXOXX\nXXOX\nXXXO"); 0878 0879 // A macro can be undone with one undo. 0880 clearAllMacros(); 0881 DoTest("foo bar", "qaciwxyz\\ctrl-ci123\\ctrl-cqw@au", "xy123z bar"); 0882 // As can a counted macro. 0883 clearAllMacros(); 0884 DoTest("XXXX\nXXXX\nXXXX\nXXXX", "qarOljq3@au", "OXXX\nXXXX\nXXXX\nXXXX"); 0885 0886 { 0887 EmulatedCommandBarSetUpAndTearDown vimStyleCommandBarTestsSetUpAndTearDown(vi_input_mode, kate_view, mainWindow); 0888 // Make sure we can macro-ise an interactive sed replace. 0889 clearAllMacros(); 0890 DoTest("foo foo foo foo\nfoo foo foo foo", "qa:s/foo/bar/gc\\enteryynyAdone\\escqggj@a", "bar bar foo bardone\nbar bar foo bardone"); 0891 // Make sure the closing "q" in the interactive sed replace isn't mistaken for a macro's closing "q". 0892 clearAllMacros(); 0893 DoTest("foo foo foo foo\nfoo foo foo foo", "qa:s/foo/bar/gc\\enteryyqAdone\\escqggj@a", "bar bar foo foodone\nbar bar foo foodone"); 0894 clearAllMacros(); 0895 DoTest("foo foo foo foo\nfoo foo foo foo", "qa:s/foo/bar/gc\\enteryyqqAdone\\escggj@aAdone\\esc", "bar bar foo foodone\nbar bar foo foodone"); 0896 } 0897 0898 clearAllMappings(); 0899 clearAllMacros(); 0900 // Expand mapping in an executed macro, if the invocation of the macro "@a" is a prefix of a mapping M, and 0901 // M ends up not being triggered. 0902 vi_global->mappings()->add(Mappings::NormalModeMapping, "@aaaa", "idummy<esc>", Mappings::Recursive); 0903 vi_global->mappings()->add(Mappings::NormalModeMapping, "S", "ixyz<esc>", Mappings::Recursive); 0904 DoTest("", "qaSq@abrX", "Xyxyzz"); 0905 clearAllMappings(); 0906 0907 // Can't play old version of macro while recording new version. 0908 clearAllMacros(); 0909 DoTest("", "qaiaaa\\ctrl-cqqa@aq", "aaa"); 0910 0911 // Can't play the macro while recording it. 0912 clearAllMacros(); 0913 DoTest("", "qaiaaa\\ctrl-c@aq", "aaa"); 0914 0915 // "@@" plays back macro "a" if "a" was the last macro we played back. 0916 clearAllMacros(); 0917 DoTest("", "qaia\\ctrl-cq@adiw@@", "a"); 0918 // "@@" plays back macro "b" if "b" was the last macro we played back. 0919 clearAllMacros(); 0920 DoTest("", "qbib\\ctrl-cq@bdiw@@", "b"); 0921 // "@@" does nothing if no macro was previously played. 0922 clearAllMacros(); 0923 DoTest("", "qaia\\ctrl-cq@@", "a"); 0924 // Nitpick: "@@" replays the last played back macro, even if that macro had not been defined 0925 // when it was first played back. 0926 clearAllMacros(); 0927 DoTest("", "@aqaia\\ctrl-cq@@", "aa"); 0928 // "@@" is counted. 0929 clearAllMacros(); 0930 DoTest("", "qaia\\ctrl-cq@adiw5@@", "aaaaa"); 0931 0932 // Test that we can save and restore a single macro. 0933 const QString viTestKConfigFileName = "vimodetest-katevimoderc"; 0934 { 0935 clearAllMacros(); 0936 KConfig viTestKConfig(viTestKConfigFileName); 0937 BeginTest(""); 0938 TestPressKey("qaia\\ctrl-cq"); 0939 vi_global->writeConfig(&viTestKConfig); 0940 viTestKConfig.sync(); 0941 // Overwrite macro "a", and clear the document. 0942 TestPressKey("qaidummy\\ctrl-cqdd"); 0943 vi_global->readConfig(&viTestKConfig); 0944 TestPressKey("@a"); 0945 FinishTest("a"); 0946 } 0947 0948 { 0949 // Test that we can save and restore several macros. 0950 clearAllMacros(); 0951 const QString viTestKConfigFileName = "vimodetest-katevimoderc"; 0952 KConfig viTestKConfig(viTestKConfigFileName); 0953 BeginTest(""); 0954 TestPressKey("qaia\\ctrl-cqqbib\\ctrl-cq"); 0955 vi_global->writeConfig(&viTestKConfig); 0956 viTestKConfig.sync(); 0957 // Overwrite macros "a" & "b", and clear the document. 0958 TestPressKey("qaidummy\\ctrl-cqqbidummy\\ctrl-cqdd"); 0959 vi_global->readConfig(&viTestKConfig); 0960 TestPressKey("@a@b"); 0961 FinishTest("ba"); 0962 } 0963 0964 // Ensure that we don't crash when a "repeat change" occurs in a macro we execute. 0965 clearAllMacros(); 0966 DoTest("", "qqixyz\\ctrl-c.q@qdd", ""); 0967 // Don't record both the "." *and* the last-change keypresses when recording a macro; 0968 // just record the "." 0969 clearAllMacros(); 0970 DoTest("", "ixyz\\ctrl-cqq.qddi123\\ctrl-c@q", "121233"); 0971 0972 // Test dealing with auto-completion. 0973 FakeCodeCompletionTestModel *fakeCodeCompletionModel = new FakeCodeCompletionTestModel(kate_view); 0974 kate_view->registerCompletionModel(fakeCodeCompletionModel); 0975 // Completion tests require a visible kate_view. 0976 ensureKateViewVisible(); 0977 // Want Vim mode to intercept ctrl-p, ctrl-n shortcuts, etc. 0978 const bool oldStealKeys = KateViewConfig::global()->viInputModeStealKeys(); 0979 KateViewConfig::global()->setValue(KateViewConfig::ViInputModeStealKeys, true); 0980 0981 // Don't invoke completion via ctrl-space when replaying a macro. 0982 clearAllMacros(); 0983 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 0984 fakeCodeCompletionModel->setFailTestOnInvocation(false); 0985 BeginTest(""); 0986 TestPressKey("qqico\\ctrl- \\ctrl-cq"); 0987 fakeCodeCompletionModel->setFailTestOnInvocation(true); 0988 TestPressKey("@q"); 0989 FinishTest("ccoo"); 0990 0991 // Don't invoke completion via ctrl-p when replaying a macro. 0992 clearAllMacros(); 0993 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 0994 fakeCodeCompletionModel->setFailTestOnInvocation(false); 0995 BeginTest(""); 0996 TestPressKey("qqico\\ctrl-p\\ctrl-cq"); 0997 fakeCodeCompletionModel->setFailTestOnInvocation(true); 0998 TestPressKey("@q"); 0999 FinishTest("ccoo"); 1000 1001 // Don't invoke completion via ctrl-n when replaying a macro. 1002 clearAllMacros(); 1003 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1004 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1005 BeginTest(""); 1006 TestPressKey("qqico\\ctrl-n\\ctrl-cq"); 1007 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1008 TestPressKey("@q"); 1009 FinishTest("ccoo"); 1010 1011 // An "enter" in insert mode when no completion is activated (so, a newline) 1012 // is treated as a newline when replayed as a macro, even if completion is 1013 // active when the "enter" is replayed. 1014 clearAllMacros(); 1015 fakeCodeCompletionModel->setCompletions(QStringList()); // Prevent any completions. 1016 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1017 fakeCodeCompletionModel->clearWasInvoked(); 1018 BeginTest(""); 1019 TestPressKey("qqicompl\\enterX\\ctrl-cqdddd"); 1020 QVERIFY(!fakeCodeCompletionModel->wasInvoked()); // Error in test setup! 1021 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1022 fakeCodeCompletionModel->forceInvocationIfDocTextIs("compl"); 1023 fakeCodeCompletionModel->clearWasInvoked(); 1024 TestPressKey("@q"); 1025 QVERIFY(fakeCodeCompletionModel->wasInvoked()); // Error in test setup! 1026 fakeCodeCompletionModel->doNotForceInvocation(); 1027 FinishTest("compl\nX"); 1028 // Same for "return". 1029 clearAllMacros(); 1030 fakeCodeCompletionModel->setCompletions(QStringList()); // Prevent any completions. 1031 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1032 fakeCodeCompletionModel->clearWasInvoked(); 1033 BeginTest(""); 1034 TestPressKey("qqicompl\\returnX\\ctrl-cqdddd"); 1035 QVERIFY(!fakeCodeCompletionModel->wasInvoked()); // Error in test setup! 1036 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1037 fakeCodeCompletionModel->forceInvocationIfDocTextIs("compl"); 1038 fakeCodeCompletionModel->clearWasInvoked(); 1039 TestPressKey("@q"); 1040 QVERIFY(fakeCodeCompletionModel->wasInvoked()); // Error in test setup! 1041 fakeCodeCompletionModel->doNotForceInvocation(); 1042 FinishTest("compl\nX"); 1043 1044 // If we do a plain-text completion in a macro, this should be repeated when we replay it. 1045 clearAllMacros(); 1046 BeginTest(""); 1047 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1048 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1049 TestPressKey("qqicompl\\ctrl- \\enter\\ctrl-cq"); 1050 kate_document->clear(); 1051 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1052 TestPressKey("@q"); 1053 FinishTest("completionA"); 1054 1055 // Should replace only the current word when we repeat the completion. 1056 clearAllMacros(); 1057 BeginTest("compl"); 1058 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1059 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1060 TestPressKey("qqfla\\ctrl- \\enter\\ctrl-cq"); 1061 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1062 kate_document->setText("(compl)"); 1063 TestPressKey("gg@q"); 1064 FinishTest("(completionA)"); 1065 1066 // Tail-clearing completions should be undoable with one undo. 1067 clearAllMacros(); 1068 BeginTest("compl"); 1069 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1070 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1071 TestPressKey("qqfla\\ctrl- \\enter\\ctrl-cq"); 1072 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1073 kate_document->setText("(compl)"); 1074 TestPressKey("gg@qu"); 1075 FinishTest("(compl)"); 1076 1077 // Should be able to store multiple completions. 1078 clearAllMacros(); 1079 BeginTest(""); 1080 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1081 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1082 TestPressKey("qqicom\\ctrl-p\\enter com\\ctrl-p\\ctrl-p\\enter\\ctrl-cq"); 1083 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1084 TestPressKey("dd@q"); 1085 FinishTest("completionC completionB"); 1086 1087 // Clear the completions for a macro when we start recording. 1088 clearAllMacros(); 1089 BeginTest(""); 1090 fakeCodeCompletionModel->setCompletions({"completionOrig"}); 1091 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1092 TestPressKey("qqicom\\ctrl- \\enter\\ctrl-cq"); 1093 fakeCodeCompletionModel->setCompletions({"completionSecond"}); 1094 TestPressKey("ddqqicom\\ctrl- \\enter\\ctrl-cq"); 1095 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1096 TestPressKey("dd@q"); 1097 FinishTest("completionSecond"); 1098 1099 // Completions are per macro. 1100 clearAllMacros(); 1101 BeginTest(""); 1102 fakeCodeCompletionModel->setCompletions({"completionA"}); 1103 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1104 TestPressKey("qaicom\\ctrl- \\enter\\ctrl-cq"); 1105 fakeCodeCompletionModel->setCompletions({"completionB"}); 1106 TestPressKey("ddqbicom\\ctrl- \\enter\\ctrl-cq"); 1107 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1108 TestPressKey("dd@aA\\enter\\ctrl-c@b"); 1109 FinishTest("completionA\ncompletionB"); 1110 1111 // Make sure completions work with recursive macros. 1112 clearAllMacros(); 1113 BeginTest(""); 1114 fakeCodeCompletionModel->setCompletions({"completionA1", "completionA2"}); 1115 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1116 // Record 'a', which calls the (non-yet-existent) macro 'b'. 1117 TestPressKey("qaicom\\ctrl- \\enter\\ctrl-cA\\enter\\ctrl-c@bA\\enter\\ctrl-cicom\\ctrl- \\ctrl-p\\enter\\ctrl-cq"); 1118 // Clear document and record 'b'. 1119 fakeCodeCompletionModel->setCompletions({"completionB"}); 1120 TestPressKey("ggdGqbicom\\ctrl- \\enter\\ctrl-cq"); 1121 TestPressKey("dd@a"); 1122 FinishTest("completionA1\ncompletionB\ncompletionA2"); 1123 1124 // Test that non-tail-removing completions are respected. 1125 // Note that there is no way (in general) to determine if a completion was 1126 // non-tail-removing, so we explicitly set the config to false. 1127 const bool oldRemoveTailOnCompletion = KateViewConfig::global()->wordCompletionRemoveTail(); 1128 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1129 const bool oldReplaceTabsDyn = kate_document->config()->replaceTabsDyn(); 1130 kate_document->config()->setReplaceTabsDyn(false); 1131 fakeCodeCompletionModel->setRemoveTailOnComplete(false); 1132 clearAllMacros(); 1133 BeginTest("compTail"); 1134 fakeCodeCompletionModel->setCompletions({"completionA", "completionB", "completionC"}); 1135 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1136 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1137 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1138 kate_document->setText("compTail"); 1139 TestPressKey("gg@q"); 1140 FinishTest("completionATail"); 1141 1142 // A "word" consists of letters & numbers, plus "_". 1143 clearAllMacros(); 1144 BeginTest("(123_compTail"); 1145 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1146 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1147 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1148 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1149 kate_document->setText("(123_compTail"); 1150 TestPressKey("gg@q"); 1151 FinishTest("(123_completionATail"); 1152 1153 // Correctly remove word if we are set to remove tail. 1154 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1155 clearAllMacros(); 1156 BeginTest("(123_compTail)"); 1157 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1158 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1159 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1160 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1161 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1162 kate_document->setText("(123_compTail)"); 1163 TestPressKey("gg@q"); 1164 FinishTest("(123_completionA)"); 1165 1166 // Again, a "word" consists of letters & numbers & underscores. 1167 clearAllMacros(); 1168 BeginTest("(123_compTail_456)"); 1169 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1170 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1171 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1172 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1173 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1174 kate_document->setText("(123_compTail_456)"); 1175 TestPressKey("gg@q"); 1176 FinishTest("(123_completionA)"); 1177 1178 // Actually, let whether the tail is swallowed or not depend on the value when the 1179 // completion occurred, not when we replay it. 1180 clearAllMacros(); 1181 BeginTest("(123_compTail_456)"); 1182 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1183 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1184 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1185 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1186 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1187 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1188 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1189 kate_document->setText("(123_compTail_456)"); 1190 TestPressKey("gg@q"); 1191 FinishTest("(123_completionA)"); 1192 clearAllMacros(); 1193 BeginTest("(123_compTail_456)"); 1194 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1195 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1196 fakeCodeCompletionModel->setRemoveTailOnComplete(false); 1197 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1198 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-cq"); 1199 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1200 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1201 kate_document->setText("(123_compTail_456)"); 1202 TestPressKey("gg@q"); 1203 FinishTest("(123_completionATail_456)"); 1204 1205 // Can have remove-tail *and* non-remove-tail completions in one macro. 1206 clearAllMacros(); 1207 BeginTest("(123_compTail_456)\n(123_compTail_456)"); 1208 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1209 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1210 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1211 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1212 TestPressKey("qqfTi\\ctrl- \\enter\\ctrl-c"); 1213 fakeCodeCompletionModel->setRemoveTailOnComplete(false); 1214 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1215 TestPressKey("j^fTi\\ctrl- \\enter\\ctrl-cq"); 1216 kate_document->setText("(123_compTail_456)\n(123_compTail_456)"); 1217 TestPressKey("gg@q"); 1218 FinishTest("(123_completionA)\n(123_completionATail_456)"); 1219 1220 // Can repeat plain-text completions when there is no word to the left of the cursor. 1221 clearAllMacros(); 1222 BeginTest(""); 1223 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1224 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1225 TestPressKey("qqi\\ctrl- \\enter\\ctrl-cq"); 1226 kate_document->clear(); 1227 TestPressKey("gg@q"); 1228 FinishTest("123_completionA"); 1229 1230 // Shouldn't swallow the letter under the cursor if we're not swallowing tails. 1231 clearAllMacros(); 1232 BeginTest(""); 1233 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1234 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1235 fakeCodeCompletionModel->setRemoveTailOnComplete(false); 1236 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1237 TestPressKey("qqi\\ctrl- \\enter\\ctrl-cq"); 1238 kate_document->setText("oldwordshouldbeuntouched"); 1239 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1240 TestPressKey("gg@q"); 1241 FinishTest("123_completionAoldwordshouldbeuntouched"); 1242 1243 // ... but do if we are swallowing tails. 1244 clearAllMacros(); 1245 BeginTest(""); 1246 fakeCodeCompletionModel->setCompletions({"123_completionA"}); 1247 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1248 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1249 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1250 TestPressKey("qqi\\ctrl- \\enter\\ctrl-cq"); 1251 kate_document->setText("oldwordshouldbedeleted"); 1252 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1253 TestPressKey("gg@q"); 1254 FinishTest("123_completionA"); 1255 1256 // Completion of functions. 1257 // Currently, not removing the tail on function completion is not supported. 1258 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1259 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1260 // A completed, no argument function "function()" is repeated correctly. 1261 BeginTest(""); 1262 fakeCodeCompletionModel->setCompletions({"function()"}); 1263 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1264 TestPressKey("qqifunc\\ctrl- \\enter\\ctrl-cq"); 1265 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1266 TestPressKey("dd@q"); 1267 FinishTest("function()"); 1268 1269 // Cursor is placed after the closing bracket when completion a no-arg function. 1270 BeginTest(""); 1271 fakeCodeCompletionModel->setCompletions({"function()"}); 1272 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1273 TestPressKey("qqifunc\\ctrl- \\enter.something();\\ctrl-cq"); 1274 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1275 TestPressKey("dd@q"); 1276 FinishTest("function().something();"); 1277 1278 // A function taking some arguments, repeated where there is no opening bracket to 1279 // merge with, is repeated as "function()"). 1280 BeginTest(""); 1281 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1282 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1283 TestPressKey("qqifunc\\ctrl- \\enter\\ctrl-cq"); 1284 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1285 TestPressKey("dd@q"); 1286 FinishTest("function()"); 1287 1288 // A function taking some arguments, repeated where there is no opening bracket to 1289 // merge with, places the cursor after the opening bracket. 1290 BeginTest(""); 1291 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1292 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1293 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1294 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1295 TestPressKey("dd@q"); 1296 FinishTest("function(firstArg)"); 1297 1298 // A function taking some arguments, recorded where there was an opening bracket to merge 1299 // with but repeated where there is no such bracket, is repeated as "function()" and the 1300 // cursor placed appropriately. 1301 BeginTest("(<-Mergeable opening bracket)"); 1302 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1303 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1304 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1305 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1306 TestPressKey("dd@q"); 1307 FinishTest("function(firstArg)"); 1308 1309 // A function taking some arguments, recorded where there was no opening bracket to merge 1310 // with but repeated where there is such a bracket, is repeated as "function" and the 1311 // cursor moved to after the merged opening bracket. 1312 BeginTest(""); 1313 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1314 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1315 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1316 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1317 kate_document->setText("(<-firstArg goes here)"); 1318 TestPressKey("gg@q"); 1319 FinishTest("function(firstArg<-firstArg goes here)"); 1320 1321 // A function taking some arguments, recorded where there was an opening bracket to merge 1322 // with and repeated where there is also such a bracket, is repeated as "function" and the 1323 // cursor moved to after the merged opening bracket. 1324 BeginTest("(<-mergeablebracket)"); 1325 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1326 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1327 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1328 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1329 kate_document->setText("(<-firstArg goes here)"); 1330 TestPressKey("gg@q"); 1331 FinishTest("function(firstArg<-firstArg goes here)"); 1332 1333 // The mergeable bracket can be separated by whitespace; the cursor is still placed after the 1334 // opening bracket. 1335 BeginTest(""); 1336 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1337 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1338 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1339 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1340 kate_document->setText(" \t (<-firstArg goes here)"); 1341 TestPressKey("gg@q"); 1342 FinishTest("function \t (firstArg<-firstArg goes here)"); 1343 1344 // Whitespace only, though! 1345 BeginTest(""); 1346 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1347 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1348 TestPressKey("qqifunc\\ctrl- \\enterfirstArg\\ctrl-cq"); 1349 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1350 kate_document->setText("| \t ()"); 1351 TestPressKey("gg@q"); 1352 FinishTest("function(firstArg)| \t ()"); 1353 1354 // The opening bracket can actually be after the current word (with optional whitespace). 1355 // Note that this wouldn't be the case if we weren't swallowing tails when completion functions, 1356 // but this is not currently supported. 1357 BeginTest("function"); 1358 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1359 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1360 TestPressKey("qqfta\\ctrl- \\enterfirstArg\\ctrl-cq"); 1361 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1362 kate_document->setText("functxyz (<-firstArg goes here)"); 1363 TestPressKey("gg@q"); 1364 FinishTest("function (firstArg<-firstArg goes here)"); 1365 1366 // Regression test for weird issue with replaying completions when the character to the left of the cursor 1367 // is not a word char. 1368 BeginTest(""); 1369 fakeCodeCompletionModel->setCompletions({"completionA"}); 1370 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1371 TestPressKey("qqciw\\ctrl- \\enter\\ctrl-cq"); 1372 TestPressKey("ddi.xyz\\enter123\\enter456\\ctrl-cggl"); // Position cursor just after the "." 1373 TestPressKey("@q"); 1374 FinishTest(".completionA\n123\n456"); 1375 BeginTest(""); 1376 fakeCodeCompletionModel->setCompletions({"completionA"}); 1377 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1378 TestPressKey("qqciw\\ctrl- \\enter\\ctrl-cq"); 1379 TestPressKey("ddi.xyz.abc\\enter123\\enter456\\ctrl-cggl"); // Position cursor just after the "." 1380 TestPressKey("@q"); 1381 FinishTest(".completionA.abc\n123\n456"); 1382 1383 // Functions taking no arguments are never bracket-merged. 1384 BeginTest(""); 1385 fakeCodeCompletionModel->setCompletions({"function()"}); 1386 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1387 TestPressKey("qqifunc\\ctrl- \\enter.something();\\ctrl-cq"); 1388 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1389 kate_document->setText("(<-don't merge this bracket)"); 1390 TestPressKey("gg@q"); 1391 FinishTest("function().something();(<-don't merge this bracket)"); 1392 1393 // Not-removing-tail when completing functions is not currently supported, 1394 // so ignore the "do-not-remove-tail" settings when we try this. 1395 BeginTest("funct"); 1396 fakeCodeCompletionModel->setCompletions({"function(...)"}); 1397 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1398 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1399 TestPressKey("qqfta\\ctrl- \\enterfirstArg\\ctrl-cq"); 1400 kate_document->setText("functxyz"); 1401 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1402 TestPressKey("gg@q"); 1403 FinishTest("function(firstArg)"); 1404 BeginTest("funct"); 1405 fakeCodeCompletionModel->setCompletions({"function()"}); 1406 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1407 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1408 TestPressKey("qqfta\\ctrl- \\enter\\ctrl-cq"); 1409 kate_document->setText("functxyz"); 1410 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1411 TestPressKey("gg@q"); 1412 FinishTest("function()"); 1413 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1414 1415 // Deal with cases where completion ends with ";". 1416 BeginTest(""); 1417 fakeCodeCompletionModel->setCompletions({"function();"}); 1418 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1419 TestPressKey("qqifun\\ctrl- \\enter\\ctrl-cq"); 1420 kate_document->clear(); 1421 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1422 TestPressKey("gg@q"); 1423 FinishTest("function();"); 1424 BeginTest(""); 1425 fakeCodeCompletionModel->setCompletions({"function();"}); 1426 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1427 TestPressKey("qqifun\\ctrl- \\enterX\\ctrl-cq"); 1428 kate_document->clear(); 1429 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1430 TestPressKey("gg@q"); 1431 FinishTest("function();X"); 1432 BeginTest(""); 1433 fakeCodeCompletionModel->setCompletions({"function(...);"}); 1434 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1435 TestPressKey("qqifun\\ctrl- \\enter\\ctrl-cq"); 1436 kate_document->clear(); 1437 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1438 TestPressKey("gg@q"); 1439 FinishTest("function();"); 1440 BeginTest(""); 1441 fakeCodeCompletionModel->setCompletions({"function(...);"}); 1442 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1443 TestPressKey("qqifun\\ctrl- \\enterX\\ctrl-cq"); 1444 kate_document->clear(); 1445 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1446 TestPressKey("gg@q"); 1447 FinishTest("function(X);"); 1448 // Tests for completions ending in ";" where bracket merging should happen on replay. 1449 // NB: bracket merging when recording is impossible with completions that end in ";". 1450 BeginTest(""); 1451 fakeCodeCompletionModel->setCompletions({"function(...);"}); 1452 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1453 TestPressKey("qqifun\\ctrl- \\enter\\ctrl-cq"); 1454 kate_document->setText("(<-mergeable bracket"); 1455 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1456 TestPressKey("gg@q"); 1457 FinishTest("function(<-mergeable bracket"); 1458 BeginTest(""); 1459 fakeCodeCompletionModel->setCompletions({"function(...);"}); 1460 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1461 TestPressKey("qqifun\\ctrl- \\enterX\\ctrl-cq"); 1462 kate_document->setText("(<-mergeable bracket"); 1463 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1464 TestPressKey("gg@q"); 1465 FinishTest("function(X<-mergeable bracket"); 1466 // Don't merge no arg functions. 1467 BeginTest(""); 1468 fakeCodeCompletionModel->setCompletions({"function();"}); 1469 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1470 TestPressKey("qqifun\\ctrl- \\enterX\\ctrl-cq"); 1471 kate_document->setText("(<-mergeable bracket"); 1472 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1473 TestPressKey("gg@q"); 1474 FinishTest("function();X(<-mergeable bracket"); 1475 1476 { 1477 const QString viTestKConfigFileName = "vimodetest-katevimoderc"; 1478 KConfig viTestKConfig(viTestKConfigFileName); 1479 // Test loading and saving of macro completions. 1480 clearAllMacros(); 1481 BeginTest("funct\nnoa\ncomtail\ncomtail\ncom"); 1482 fakeCodeCompletionModel->setCompletions({"completionA", "functionwithargs(...)", "noargfunction()"}); 1483 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1484 // Record 'a'. 1485 TestPressKey("qafta\\ctrl- \\enterfirstArg\\ctrl-c"); // Function with args. 1486 TestPressKey("\\enterea\\ctrl- \\enter\\ctrl-c"); // Function no args. 1487 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1488 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1489 TestPressKey("\\enterfti\\ctrl- \\enter\\ctrl-c"); // Cut off tail. 1490 fakeCodeCompletionModel->setRemoveTailOnComplete(false); 1491 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, false); 1492 TestPressKey("\\enterfti\\ctrl- \\enter\\ctrl-cq"); // Don't cut off tail. 1493 fakeCodeCompletionModel->setRemoveTailOnComplete(true); 1494 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, true); 1495 // Record 'b'. 1496 fakeCodeCompletionModel->setCompletions({"completionB", "semicolonfunctionnoargs();", "semicolonfunctionwithargs(...);"}); 1497 TestPressKey("\\enterqbea\\ctrl- \\enter\\ctrl-cosemicolonfunctionw\\ctrl- \\enterX\\ctrl-cosemicolonfunctionn\\ctrl- \\enterX\\ctrl-cq"); 1498 // Save. 1499 vi_global->writeConfig(&viTestKConfig); 1500 viTestKConfig.sync(); 1501 // Overwrite 'a' and 'b' and their completions. 1502 fakeCodeCompletionModel->setCompletions({"blah1"}); 1503 kate_document->setText(""); 1504 TestPressKey("ggqaiblah\\ctrl- \\enter\\ctrl-cq"); 1505 TestPressKey("ddqbiblah\\ctrl- \\enter\\ctrl-cq"); 1506 // Reload. 1507 vi_global->readConfig(&viTestKConfig); 1508 // Replay reloaded. 1509 fakeCodeCompletionModel->setFailTestOnInvocation(true); 1510 kate_document->setText("funct\nnoa\ncomtail\ncomtail\ncom"); 1511 TestPressKey("gg@a\\enter@b"); 1512 FinishTest( 1513 "functionwithargs(firstArg)\nnoargfunction()\ncompletionA\ncompletionAtail\ncompletionB\nsemicolonfunctionwithargs(X);\nsemicolonfunctionnoargs();" 1514 "X"); 1515 } 1516 1517 // Check that undo/redo operations work properly with macros. 1518 { 1519 clearAllMacros(); 1520 BeginTest(""); 1521 TestPressKey("ihello\\ctrl-cqauq"); 1522 TestPressKey("@a\\enter"); 1523 FinishTest(""); 1524 } 1525 { 1526 clearAllMacros(); 1527 BeginTest(""); 1528 TestPressKey("ihello\\ctrl-cui.bye\\ctrl-cu"); 1529 TestPressKey("qa\\ctrl-r\\enterq"); 1530 TestPressKey("@a\\enter"); 1531 FinishTest(".bye"); 1532 } 1533 1534 // When replaying a last change in the process of replaying a macro, take the next completion 1535 // event from the last change completions log, rather than the macro completions log. 1536 // Ensure that the last change completions log is kept up to date even while we're replaying the macro. 1537 if (false) { // FIXME: test currently fails in newer Qt >= 5.11, but works with Qt 5.10 1538 clearAllMacros(); 1539 BeginTest(""); 1540 fakeCodeCompletionModel->setCompletions({"completionMacro", "completionRepeatLastChange"}); 1541 fakeCodeCompletionModel->setFailTestOnInvocation(false); 1542 TestPressKey("qqicompletionM\\ctrl- \\enter\\ctrl-c"); 1543 TestPressKey("a completionRep\\ctrl- \\enter\\ctrl-c"); 1544 TestPressKey(".q"); 1545 qDebug() << "text: " << kate_document->text(); 1546 kate_document->clear(); 1547 TestPressKey("gg@q"); 1548 FinishTest("completionMacro completionRepeatLastChange completionRepeatLastChange"); 1549 } 1550 1551 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, oldRemoveTailOnCompletion); 1552 kate_document->config()->setReplaceTabsDyn(oldReplaceTabsDyn); 1553 1554 kate_view->unregisterCompletionModel(fakeCodeCompletionModel); 1555 delete fakeCodeCompletionModel; 1556 fakeCodeCompletionModel = nullptr; 1557 // Hide the kate_view for subsequent tests. 1558 kate_view->hide(); 1559 mainWindow->hide(); 1560 KateViewConfig::global()->setValue(KateViewConfig::ViInputModeStealKeys, oldStealKeys); 1561 } 1562 1563 void KeysTest::MarkTests() 1564 { 1565 // Difference between ` and ' 1566 DoTest(" a\n b", "jmak'aii", " a\n ib"); 1567 DoTest(" a\n b", "jmak`aii", " a\ni b"); 1568 1569 // Last edit markers. 1570 DoTest("foo", "ean\\escgg`.r.", "foo."); 1571 DoTest("foo", "ean\\escgg`[r[", "foo["); 1572 DoTest("foo", "ean\\escgg`]r]", "foo]"); 1573 DoTest("foo bar", "ean\\escgg`]r]", "foon]bar"); 1574 DoTest("", "ibar\\escgg`.r.", "ba."); 1575 DoTest("", "ibar\\escgggUiw`.r.", ".AR"); 1576 DoTest("", "2ibar\\escgg`]r]", "barba]"); 1577 DoTest("", "2ibar\\escgg`[r[", "[arbar"); 1578 DoTest("", "3ibar\\escgg`.r.", "barbar.ar"); // Vim is weird. 1579 DoTest("", "abar\\esc.gg`]r]", "barba]"); 1580 DoTest("foo bar", "wgUiwgg`]r]", "foo BA]"); 1581 DoTest("foo bar", "wgUiwgg`.r.", "foo .AR"); 1582 DoTest("foo bar", "gUiwgg`]r.", "FO. bar"); 1583 DoTest("foo bar", "wdiwgg`[r[", "foo["); 1584 DoTest("foo bar", "wdiwgg`]r]", "foo]"); 1585 DoTest("foo bar", "wdiwgg`.r.", "foo."); 1586 DoTest("foo bar", "wciwnose\\escgg`.r.", "foo nos."); 1587 DoTest("foo bar", "wciwnose\\escgg`[r[", "foo [ose"); 1588 DoTest("foo bar", "wciwnose\\escgg`]r]", "foo nos]"); 1589 DoTest("foo", "~ibar\\escgg`[r[", "F[aroo"); 1590 DoTest("foo bar", "lragg`.r.", "f.o bar"); 1591 DoTest("foo bar", "lragg`[r[", "f[o bar"); 1592 DoTest("foo bar", "lragg`]r]", "f]o bar"); 1593 DoTest("", "ifoo\\ctrl-hbar\\esc`[r[", "[obar"); 1594 DoTest("", "ifoo\\ctrl-wbar\\esc`[r[", "[ar"); 1595 DoTest("", "if\\ctrl-hbar\\esc`[r[", "[ar"); 1596 DoTest("", "5ofoo\\escgg`[r[", "\n[oo\nfoo\nfoo\nfoo\nfoo"); 1597 DoTest("", "5ofoo\\escgg`]r]", "\nfoo\nfoo\nfoo\nfoo\nfo]"); 1598 DoTest("", "5ofoo\\escgg`.r.", "\nfoo\nfoo\nfoo\nfoo\n.oo"); 1599 DoTest("foo", "yyp`[r[", "foo\n[oo"); 1600 DoTest("xyz\nfoo", "ja\\returnbar\\esc`[r[", "xyz\n[\nbaroo"); 1601 DoTest("foo", "lrayypgg`[r[", "fao\n[ao"); 1602 DoTest("foo", "l~u`[r[", "[oo"); 1603 DoTest("foo", "l~u`.r.", ".oo"); 1604 DoTest("foo", "l~u`]r]", "]oo"); 1605 DoTest("foo", "lia\\escu`[r[", "[oo"); 1606 DoTest("foo", "lia\\escu`.r.", ".oo"); 1607 DoTest("foo", "lia\\escu`]r]", "]oo"); 1608 DoTest("foo", "l~u~`[r[", "f[o"); 1609 DoTest("foo\nbar\nxyz", "jyypu`[r[", "foo\nbar\n[yz"); 1610 DoTest("foo\nbar\nxyz", "jyypu`.r.", "foo\nbar\n.yz"); 1611 DoTest("foo\nbar\nxyz", "jyypu`]r]", "foo\nbar\n]yz"); 1612 DoTest("foo\nbar\nxyz\n123", "jdju`[r[", "foo\n[ar\nxyz\n123"); 1613 DoTest("foo\nbar\nxyz\n123", "jdju`.r.", "foo\n.ar\nxyz\n123"); 1614 DoTest("foo\nbar\nxyz\n123", "jdju`]r]", "foo\nbar\n]yz\n123"); 1615 DoTest("foo\nbar\nxyz\n123", "jVj~u\\esc`[r[", "foo\n[ar\nxyz\n123", ShouldFail, "Vim is weird."); 1616 } 1617 1618 // END: KeysTest 1619 1620 #include "moc_keys.cpp"