void UndoManagerTest::testSelectionUndo() { TestDocument doc; KateView *view = static_cast<KateView*>(doc.createView(0)); doc.setText("aaaa bbbb cccc\n" "dddd eeee ffff"); view->setCursorPosition(KTextEditor::Cursor(1, 9)); KTextEditor::Range selectionRange(KTextEditor::Cursor(0, 5), KTextEditor::Cursor(1, 9)); view->setSelection(selectionRange); doc.typeChars(view, "eeee"); // cursor position: "aaaa eeee| ffff", no selection anymore QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9)); QCOMPARE(view->selection(), false); // undo to remove "eeee" and add selection and text again doc.undo(); QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); QCOMPARE(view->selection(), true); QCOMPARE(view->selectionRange(), selectionRange); // redo to insert "eeee" again and remove selection // cursor position: "aaaa eeee| ffff", no selection anymore doc.redo(); QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9)); QCOMPARE(view->selection(), false); delete view; }
void UndoManagerTest::testCursorPosition() { TestDocument doc; KateView *view = static_cast<KateView*>(doc.createView(0)); doc.setText("aaaa bbbb cccc\n" "dddd ffff"); view->setCursorPosition(KTextEditor::Cursor(1, 5)); doc.typeChars(view, "eeee"); // cursor position: "dddd eeee| ffff" QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); // undo once to remove "eeee", cursor position: "dddd | ffff" doc.undo(); QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 5)); // redo once to insert "eeee" again. cursor position: "dddd eeee| ffff" doc.redo(); QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); delete view; }
// tests: // - RangeFeedback::caretEnteredRange // - RangeFeedback::caretExitedRange void MovingRangeTest::testFeedbackCaret() { KateDocument doc (false, false, false); // the range created below will span the 'x' characters QString text("..xxxx\n" "xxxx.."); doc.setText(text); KateView* view = static_cast<KateView*>(doc.createView(0)); // create range feedback RangeFeedback rf; // first test: with ExpandLeft | ExpandRight { view->setCursorPosition(Cursor(1, 6)); MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), KTextEditor::MovingRange::ExpandLeft | KTextEditor::MovingRange::ExpandRight, KTextEditor::MovingRange::InvalidateIfEmpty); rf.reset(); range->setFeedback(&rf); rf.verifyReset(); // left view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 5)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 4)); QVERIFY(rf.caretEnteredRangeCalled()); // ExpandRight: include cursor already now QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 3)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->up(); QCOMPARE(view->cursorPosition(), Cursor(0, 3)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(0, 2)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(0, 1)); // ExpandLeft: now we left it, not before QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(rf.caretExitedRangeCalled()); delete range; } // second test: with DoNotExpand { view->setCursorPosition(Cursor(1, 6)); MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::InvalidateIfEmpty); rf.reset(); range->setFeedback(&rf); rf.verifyReset(); // left view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 5)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 4)); QVERIFY(!rf.caretEnteredRangeCalled()); // DoNotExpand: does not include cursor QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(1, 3)); QVERIFY(rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->up(); QCOMPARE(view->cursorPosition(), Cursor(0, 3)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(0, 2)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(rf.caretExitedRangeCalled()); // DoNotExpand: that's why we leave already now rf.reset(); view->cursorLeft(); QCOMPARE(view->cursorPosition(), Cursor(0, 1)); QVERIFY(!rf.caretEnteredRangeCalled()); QVERIFY(!rf.caretExitedRangeCalled()); delete range; } }
bool KateCommands::CoreCommands::exec(KTextEditor::View *view, const QString &_cmd, QString &errorMsg, const KTextEditor::Range& range) { #define KCC_ERR(s) { errorMsg=s; return false; } // cast it hardcore, we know that it is really a kateview :) KateView *v = static_cast<KateView*>(view); if ( ! v ) KCC_ERR( i18n("Could not access view") ); //create a list of args QStringList args(_cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ; QString cmd ( args.takeFirst() ); // ALL commands that takes no arguments. if ( cmd == "indent" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->indent( KTextEditor::Range(line, 0, line, 0), 1 ); } v->doc()->editEnd(); } else { v->indent(); } return true; } else if ( cmd == "unindent" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->indent( KTextEditor::Range(line, 0, line, 0), -1 ); } v->doc()->editEnd(); } else { v->unIndent(); } return true; } else if ( cmd == "cleanindent" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->indent( KTextEditor::Range(line, 0, line, 0), 0 ); } v->doc()->editEnd(); } else { v->cleanIndent(); } return true; } else if ( cmd == "comment" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->comment( v, line, 0, 1 ); } v->doc()->editEnd(); } else { v->comment(); } return true; } else if ( cmd == "uncomment" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->comment( v, line, 0, -1 ); } v->doc()->editEnd(); } else { v->uncomment(); } return true; } else if ( cmd == "kill-line" ) { if ( range.isValid() ) { v->doc()->editStart(); for ( int line = range.start().line(); line <= range.end().line(); line++ ) { v->doc()->removeLine( range.start().line() ); } v->doc()->editEnd(); } else { v->killLine(); } return true; } else if ( cmd == "print" ) { v->doc()->printDialog(); return true; } // ALL commands that take a string argument else if ( cmd == "set-indent-mode" || cmd == "set-highlight" || cmd == "set-mode" ) { // need at least one item, otherwise args.first() crashes if ( ! args.count() ) KCC_ERR( i18n("Missing argument. Usage: %1 <value>", cmd ) ); if ( cmd == "set-indent-mode" ) { v->doc()->config()->setIndentationMode( args.join(" ") ); v->doc()->rememberUserDidSetIndentationMode (); return true; } else if ( cmd == "set-highlight" ) { if ( v->doc()->setHighlightingMode( args.first()) ) { static_cast<KateDocument*>(v->doc())->setDontChangeHlOnSave (); return true; } KCC_ERR( i18n("No such highlighting '%1'", args.first() ) ); } else if ( cmd == "set-mode" ) { if ( v->doc()->setMode( args.first()) ) return true; KCC_ERR( i18n("No such mode '%1'", args.first() ) ); } } // ALL commands that takes exactly one integer argument. else if ( cmd == "set-tab-width" || cmd == "set-indent-width" || cmd == "set-word-wrap-column" || cmd == "goto" ) { // find a integer value > 0 if ( ! args.count() ) KCC_ERR( i18n("Missing argument. Usage: %1 <value>", cmd ) ); bool ok; int val ( args.first().toInt( &ok, 10 ) ); // use base 10 even if the string starts with '0' if ( !ok ) KCC_ERR( i18n("Failed to convert argument '%1' to integer.", args.first() ) ); if ( cmd == "set-tab-width" ) { if ( val < 1 ) KCC_ERR( i18n("Width must be at least 1.") ); v->doc()->config()->setTabWidth( val ); } else if ( cmd == "set-indent-width" ) { if ( val < 1 ) KCC_ERR( i18n("Width must be at least 1.") ); v->doc()->config()->setIndentationWidth( val ); } else if ( cmd == "set-word-wrap-column" ) { if ( val < 2 ) KCC_ERR( i18n("Column must be at least 1.") ); v->doc()->setWordWrapAt( val ); } else if ( cmd == "goto" ) { if ( args.first().at(0) == '-' || args.first().at(0) == '+' ) { // if the number starts with a minus or plus sign, add/subract the number val = v->cursorPosition().line() + val; } else { val--; // convert given line number to the internal representation of line numbers } // constrain cursor to the range [0, number of lines] if ( val < 0 ) { val = 0; } else if ( val > v->doc()->lines()-1 ) { val = v->doc()->lines()-1; } v->setCursorPosition( KTextEditor::Cursor( val, 0 ) ); return true; } return true; } // ALL commands that takes 1 boolean argument. else if ( cmd == "set-icon-border" || cmd == "set-folding-markers" || cmd == "set-line-numbers" || cmd == "set-replace-tabs" || cmd == "set-show-tabs" || cmd == "set-word-wrap" || cmd == "set-wrap-cursor" || cmd == "set-replace-tabs-save" || cmd == "set-show-indent" ) { if ( ! args.count() ) KCC_ERR( i18n("Usage: %1 on|off|1|0|true|false", cmd ) ); bool enable = false; KateDocumentConfig * const config = v->doc()->config(); if ( getBoolArg( args.first(), &enable ) ) { if ( cmd == "set-icon-border" ) v->setIconBorder( enable ); else if (cmd == "set-folding-markers") v->setFoldingMarkersOn( enable ); else if ( cmd == "set-line-numbers" ) v->setLineNumbersOn( enable ); else if ( cmd == "set-show-indent" ) v->renderer()->setShowIndentLines( enable ); else if ( cmd == "set-replace-tabs" ) config->setReplaceTabsDyn( enable ); else if ( cmd == "set-show-tabs" ) config->setShowTabs( enable ); else if ( cmd == "set-show-trailing-spaces" ) config->setShowSpaces( enable ); else if ( cmd == "set-word-wrap" ) v->doc()->setWordWrap( enable ); return true; } else KCC_ERR( i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false", args.first() , cmd ) ); } else if ( cmd == "set-remove-trailing-spaces" ) { // need at least one item, otherwise args.first() crashes if ( args.count() != 1 ) KCC_ERR( i18n("Usage: set-remove-trailing-spaces 0|-|none or 1|+|mod|modified or 2|*|all") ); QString tmp = args.first().toLower().trimmed(); if (tmp == "1" || tmp == "modified" || tmp == "mod" || tmp == "+") { v->doc()->config()->setRemoveSpaces(1); } else if (tmp == "2" || tmp == "all" || tmp == "*") { v->doc()->config()->setRemoveSpaces(2); } else { v->doc()->config()->setRemoveSpaces(0); } } // unlikely.. KCC_ERR( i18n("Unknown command '%1'", cmd) ); }