8#include "emulatedcommandbar.h"
10using namespace KateVi;
12#include "activemode.h"
14#include "vimode/definitions.h"
15#include <ktexteditor/document.h>
17#include <QAbstractItemView>
21#include <QRegularExpression>
22#include <QStringListModel>
39 m_completer->setWidget(edit);
40 m_completer->setObjectName(QStringLiteral(
"completer"));
42 m_completer->setModel(m_completionModel);
44 m_completer->popup()->installEventFilter(emulatedCommandBar);
47void Completer::startCompletion(
const CompletionStartParams &completionStartParams)
49 if (completionStartParams.completionType != CompletionStartParams::None) {
50 m_completionModel->setStringList(completionStartParams.completions);
51 const QString completionPrefix = m_edit->text().mid(completionStartParams.wordStartPos, m_edit->cursorPosition() - completionStartParams.wordStartPos);
52 m_completer->setCompletionPrefix(completionPrefix);
53 m_completer->complete();
54 m_currentCompletionStartParams = completionStartParams;
55 m_currentCompletionType = completionStartParams.completionType;
59void Completer::deactivateCompletion()
61 m_completer->popup()->hide();
62 m_currentCompletionType = CompletionStartParams::None;
65bool Completer::isCompletionActive()
const
67 return m_currentCompletionType != CompletionStartParams::None;
70bool Completer::isNextTextChangeDueToCompletionChange()
const
72 return m_isNextTextChangeDueToCompletionChange;
75bool Completer::completerHandledKeypress(
const QKeyEvent *keyEvent)
77 if (!m_edit->isVisible()) {
82 if (m_currentCompletionType != CompletionStartParams::None && m_completer->popup()->isVisible()) {
83 abortCompletionAndResetToPreCompletion();
88 CompletionStartParams completionStartParams = activateWordFromDocumentCompletion();
89 startCompletion(completionStartParams);
93 if (!m_completer->popup()->isVisible()) {
94 const CompletionStartParams completionStartParams = m_currentMode->completionInvoked(CompletionInvocation::ExtraContext);
95 startCompletion(completionStartParams);
96 if (m_currentCompletionType != CompletionStartParams::None) {
97 setCompletionIndex(0);
101 if (m_completer->currentRow() + 1 == m_completer->completionCount()) {
102 setCompletionIndex(0);
104 setCompletionIndex(m_completer->currentRow() + 1);
110 if (!m_completer->popup()->isVisible()) {
111 const CompletionStartParams completionStartParams = m_currentMode->completionInvoked(CompletionInvocation::NormalContext);
112 startCompletion(completionStartParams);
113 setCompletionIndex(m_completer->completionCount() - 1);
116 if (m_completer->currentRow() == 0) {
117 setCompletionIndex(m_completer->completionCount() - 1);
119 setCompletionIndex(m_completer->currentRow() - 1);
125 if (!m_completer->popup()->isVisible() || m_currentCompletionType != CompletionStartParams::WordFromDocument) {
126 m_currentMode->completionChosen();
128 deactivateCompletion();
134void Completer::editTextChanged(
const QString &newText)
136 if (!m_isNextTextChangeDueToCompletionChange) {
137 m_textToRevertToIfCompletionAborted = newText;
138 m_cursorPosToRevertToIfCompletionAborted = m_edit->cursorPosition();
142 if (!m_isNextTextChangeDueToCompletionChange && m_completer->popup()->currentIndex().row() != -1) {
143 deactivateCompletion();
146 if (m_currentCompletionType != CompletionStartParams::None && !m_isNextTextChangeDueToCompletionChange) {
147 updateCompletionPrefix();
151void Completer::setCurrentMode(ActiveMode *currentMode)
153 m_currentMode = currentMode;
156void Completer::setCompletionIndex(
int index)
158 const QModelIndex modelIndex = m_completer->popup()->model()->index(index, 0);
160 m_completer->popup()->setCurrentIndex(modelIndex);
161 m_completer->setCurrentRow(index);
163 m_completer->popup()->scrollTo(modelIndex);
165 currentCompletionChanged();
168void Completer::currentCompletionChanged()
170 const QString newCompletion = m_completer->currentCompletion();
174 QString transformedCompletion = newCompletion;
175 if (m_currentCompletionStartParams.completionTransform) {
176 transformedCompletion = m_currentCompletionStartParams.completionTransform(newCompletion);
179 m_isNextTextChangeDueToCompletionChange =
true;
180 m_edit->setSelection(m_currentCompletionStartParams.wordStartPos, m_edit->cursorPosition() - m_currentCompletionStartParams.wordStartPos);
181 m_edit->
insert(transformedCompletion);
182 m_isNextTextChangeDueToCompletionChange =
false;
185void Completer::updateCompletionPrefix()
187 const QString completionPrefix =
188 m_edit->text().
mid(m_currentCompletionStartParams.wordStartPos, m_edit->cursorPosition() - m_currentCompletionStartParams.wordStartPos);
189 m_completer->setCompletionPrefix(completionPrefix);
191 m_completer->complete();
194CompletionStartParams Completer::activateWordFromDocumentCompletion()
197 QRegularExpressionMatch
match;
199 QStringList foundWords;
201 const int startLine = qMax(0, m_view->cursorPosition().line() - 4096);
202 const int endLine = qMin(m_view->document()->lines(), m_view->cursorPosition().line() + 4096);
203 for (
int lineNum = startLine; lineNum < endLine; lineNum++) {
204 const QString line = m_view->document()->line(lineNum);
205 int wordSearchBeginPos = 0;
206 while ((match = wordRegEx.match(line, wordSearchBeginPos)).hasMatch()) {
207 const QString foundWord =
match.captured();
208 foundWords << foundWord;
209 wordSearchBeginPos =
match.capturedEnd();
213 std::sort(foundWords.
begin(), foundWords.
end(), caseInsensitiveLessThan);
214 CompletionStartParams completionStartParams;
215 completionStartParams.completionType = CompletionStartParams::WordFromDocument;
216 completionStartParams.completions = foundWords;
217 completionStartParams.wordStartPos = wordBeforeCursorBegin();
218 return completionStartParams;
221QString Completer::wordBeforeCursor()
223 const int wordBeforeCursorBegin = this->wordBeforeCursorBegin();
224 return m_edit->text().mid(wordBeforeCursorBegin, m_edit->cursorPosition() - wordBeforeCursorBegin);
227int Completer::wordBeforeCursorBegin()
229 int wordBeforeCursorBegin = m_edit->cursorPosition() - 1;
230 while (wordBeforeCursorBegin >= 0
231 && (m_edit->text()[wordBeforeCursorBegin].isLetterOrNumber() || m_edit->text()[wordBeforeCursorBegin] == QLatin1Char(
'_'))) {
232 wordBeforeCursorBegin--;
234 wordBeforeCursorBegin++;
235 return wordBeforeCursorBegin;
238void Completer::abortCompletionAndResetToPreCompletion()
240 deactivateCompletion();
241 m_isNextTextChangeDueToCompletionChange =
true;
242 m_edit->setText(m_textToRevertToIfCompletionAborted);
243 m_edit->setCursorPosition(m_cursorPosToRevertToIfCompletionAborted);
244 m_isNextTextChangeDueToCompletionChange =
false;
A KateViewBarWidget that attempts to emulate some of the features of Vim's own command bar,...
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
UseUnicodePropertiesOption
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
QString toLower() const const
qsizetype removeDuplicates()
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)