Commit 72ffa498 authored by Simon St James's avatar Simon St James
Browse files

Add some Vim auto-completion tests, and fix a couple of bugs - one especially...

Add some Vim auto-completion tests, and fix a couple of bugs - one especially annoying one is when completion is invoked automatically and we attempt to repeat it via '.' - only the leading portion that we had typed of the completion would be repeated, not the whole thing.

Also, begin work on making the completion list wrap-around: this currently fails as https://git.reviewboard.kde.org/r/109647/ has not yet been committed.

CCBUG:311831
parent 347b1d41
......@@ -33,6 +33,9 @@
#include <katevinormalmode.h>
#include "kateviewhelpers.h"
#include "ktexteditor/attribute.h"
#include <ktexteditor/codecompletionmodel.h>
#include <katewordcompletion.h>
#include <katecompletionwidget.h>
QTEST_KDEMAIN(ViModeTest, GUI)
......@@ -1078,6 +1081,122 @@ void ViModeTest::yankHighlightingTests()
FinishTest("");
}
class VimCodeCompletionTestModel : public CodeCompletionModel
{
public:
VimCodeCompletionTestModel(KTextEditor::View* parent)
: KTextEditor::CodeCompletionModel(parent)
{
setRowCount(3);
cc()->setAutomaticInvocationEnabled(true);
cc()->unregisterCompletionModel(KateGlobal::self()->wordCompletionModel()); //would add additional items, we don't want that in tests
cc()->registerCompletionModel(this);
}
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
// Order is important, here, as the completion widget seems to do its own sorting.
const char* completions[] = { "completion1", "completion2", "completion3" };
if (role == Qt::DisplayRole)
{
if (index.column() == Name)
return QString(completions[index.row()]);
}
return QVariant();
}
KTextEditor::CodeCompletionInterface * cc( ) const
{
return dynamic_cast<KTextEditor::CodeCompletionInterface*>(const_cast<QObject*>(QObject::parent()));
}
};
class FailTestOnInvocationModel : public CodeCompletionModel
{
public:
FailTestOnInvocationModel(KTextEditor::View* parent)
: KTextEditor::CodeCompletionModel(parent)
{
setRowCount(3);
cc()->setAutomaticInvocationEnabled(true);
cc()->unregisterCompletionModel(KateGlobal::self()->wordCompletionModel()); //would add additional items, we don't want that in tests
cc()->registerCompletionModel(this);
}
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
Q_UNUSED(index);
Q_UNUSED(role);
failTest();
return QVariant();
}
void failTest() const
{
QFAIL("Shouldn't be invoking me!");
}
KTextEditor::CodeCompletionInterface * cc( ) const
{
return dynamic_cast<KTextEditor::CodeCompletionInterface*>(const_cast<QObject*>(QObject::parent()));
}
};
void ViModeTest::CompletionTests()
{
KateViewConfig::global()->setViInputModeStealKeys(true); // For Ctrl-P, Ctrl-N etc
ensureKateViewVisible(); // KateView needs to be visible for the completion widget.
VimCodeCompletionTestModel *testModel = new VimCodeCompletionTestModel(kate_view);
BeginTest("");
TestPressKey("i\\ctrl-p");
waitForCompletionWidgetToActivate();
TestPressKey("\n");
FinishTest("completion3");
BeginTest("");
TestPressKey("i\\ctrl- ");
waitForCompletionWidgetToActivate();
TestPressKey("\n");
FinishTest("completion1");
BeginTest("");
TestPressKey("i\\ctrl-n");
waitForCompletionWidgetToActivate();
TestPressKey("\n");
FinishTest("completion1");
// Test wraps around from top to bottom.
BeginTest("");
TestPressKey("i\\ctrl- \\ctrl-p");
waitForCompletionWidgetToActivate();
TestPressKey("\n");
FinishTest("completion3", ShouldFail, "Need to wait for https://git.reviewboard.kde.org/r/109647/ to be committed.");
// Test wraps around from top to bottom.
BeginTest("");
TestPressKey("i\\ctrl- \\ctrl-n\\ctrl-n\\ctrl-n");
waitForCompletionWidgetToActivate();
TestPressKey("\n");
FinishTest("completion1");
// Test does not re-invoke completion when doing a "." repeat.
BeginTest("");
TestPressKey("i\\ctrl- ");
waitForCompletionWidgetToActivate();
TestPressKey("\n\\ctrl-c");
kate_view->unregisterCompletionModel(testModel);
FailTestOnInvocationModel *failsTestOnInvocation = new FailTestOnInvocationModel(kate_view);
TestPressKey(".");
FinishTest("completioncompletion11");
kate_view->unregisterCompletionModel(failsTestOnInvocation);
kate_view->registerCompletionModel(testModel);
// Test that the full completion is repeated when repeat an insert that uses completion,
// where the completion list was not manually invoked.
BeginTest("");
TestPressKey("i");
// Simulate "automatic" invoking of completion.
kate_view->completionWidget()->userInvokedCompletion();
waitForCompletionWidgetToActivate();
TestPressKey("\n\\ctrl-c.");
FinishTest("completioncompletion11");
}
// Special area for tests where you want to set breakpoints etc without all the other tests
// triggering them. Run with ./vimode_test debuggingTests
......@@ -1091,4 +1210,27 @@ QList< Kate::TextRange* > ViModeTest::rangesOnFirstLine()
return kate_document->buffer().rangesForLine(0, kate_view, true);
}
void ViModeTest::ensureKateViewVisible()
{
kate_view->show();
while (QApplication::hasPendingEvents())
{
QApplication::processEvents();
}
QApplication::setActiveWindow(kate_view);
}
void ViModeTest::waitForCompletionWidgetToActivate()
{
const QDateTime start = QDateTime::currentDateTime();
while (start.msecsTo(QDateTime::currentDateTime()) < 1000)
{
if (kate_view->isCompletionActive())
break;
QApplication::processEvents();
}
QVERIFY(kate_view->isCompletionActive());
}
// kate: space-indent on; indent-width 2; replace-tabs on;
......@@ -46,6 +46,7 @@ private Q_SLOTS:
void MappingTests();
void yankHighlightingTests();
void CompletionTests();
void debuggingTests();
private:
......@@ -68,6 +69,8 @@ private:
KateViInputModeManager *vi_input_mode_manager;
QList<Kate::TextRange*> rangesOnFirstLine();
void ensureKateViewVisible();
void waitForCompletionWidgetToActivate();
};
#endif
......
......@@ -25,6 +25,7 @@
#include "kateviewinternal.h"
#include "kateconfig.h"
#include "katecompletionwidget.h"
#include <katecompletiontree.h>
#include "kateglobal.h"
#include "katevikeyparser.h"
......@@ -196,7 +197,14 @@ bool KateViInsertMode::commandCompleteNext()
// inserted text instead of the typed keystrokes.
m_viInputModeManager->setTextualRepeat();
if(m_view->completionWidget()->isCompletionActive()) {
const QModelIndex oldCompletionItem = m_view->completionWidget()->treeView()->selectionModel()->currentIndex();
m_view->completionWidget()->cursorDown();
const QModelIndex newCompletionItem = m_view->completionWidget()->treeView()->selectionModel()->currentIndex();
if (newCompletionItem == oldCompletionItem)
{
// Wrap to top.
m_view->completionWidget()->top();
}
} else {
m_view->userInvokedCompletion();
}
......@@ -207,7 +215,14 @@ bool KateViInsertMode::commandCompletePrevious()
{
m_viInputModeManager->setTextualRepeat();
if(m_view->completionWidget()->isCompletionActive()) {
const QModelIndex oldCompletionItem = m_view->completionWidget()->treeView()->selectionModel()->currentIndex();
m_view->completionWidget()->cursorUp();
const QModelIndex newCompletionItem = m_view->completionWidget()->treeView()->selectionModel()->currentIndex();
if (newCompletionItem == oldCompletionItem)
{
// Wrap to bottom.
m_view->completionWidget()->bottom();
}
} else {
m_view->userInvokedCompletion();
m_view->completionWidget()->bottom();
......
......@@ -31,6 +31,7 @@
#include "kateviewhelpers.h"
#include <kateundomanager.h>
#include <ktexteditor/attribute.h>
#include <katecompletionwidget.h>
#include "kateconfig.h"
#include <QApplication>
......@@ -3502,6 +3503,10 @@ void KateViNormalMode::textInserted(KTextEditor::Document* document, Range range
m_viInputModeManager->addMark(doc(), '.', Cursor(m_viInputModeManager->getMarkPosition('.').line(), 0));
}
}
if (m_view->completionWidget()->isCompletionActive())
{
m_viInputModeManager->setTextualRepeat(true);
}
}
void KateViNormalMode::textRemoved(KTextEditor::Document* document , Range range)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment