forked from qt-creator/qt-creator
FakeVim: Block Suggestions
Block suggestions when FakeVim is enabled and the mode is not "Insert" or "Replace". Change-Id: I778eb25d9570b76e42652f9d938a8c580033c462 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -92,7 +92,7 @@ void CopilotClient::openDocument(TextDocument *document)
|
||||
const int cursorPosition = widget->textCursor().position();
|
||||
if (cursorPosition < position || cursorPosition > position + charsAdded)
|
||||
return;
|
||||
scheduleRequest(textEditor->editorWidget());
|
||||
scheduleRequest(widget);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -5197,7 +5197,7 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input)
|
||||
moveDown();
|
||||
} else if (input.isKey(Key_Insert)) {
|
||||
g.mode = InsertMode;
|
||||
q->modeChanged();
|
||||
q->modeChanged(isInsertMode());
|
||||
} else if (input.isControl('o')) {
|
||||
enterCommandMode(ReplaceMode);
|
||||
} else {
|
||||
@@ -5395,7 +5395,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
||||
removeText(range);
|
||||
} else if (input.isKey(Key_Insert)) {
|
||||
g.mode = ReplaceMode;
|
||||
q->modeChanged();
|
||||
q->modeChanged(isInsertMode());
|
||||
} else if (input.isKey(Key_Left)) {
|
||||
moveLeft();
|
||||
} else if (input.isShift(Key_Left) || input.isControl(Key_Left)) {
|
||||
@@ -8578,7 +8578,7 @@ void FakeVimHandler::Private::enterInsertOrReplaceMode(Mode mode)
|
||||
clearLastInsertion();
|
||||
}
|
||||
|
||||
q->modeChanged();
|
||||
q->modeChanged(isInsertMode());
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::enterVisualInsertMode(QChar command)
|
||||
@@ -8655,7 +8655,7 @@ void FakeVimHandler::Private::enterCommandMode(Mode returnToMode)
|
||||
m_positionPastEnd = false;
|
||||
m_anchorPastEnd = false;
|
||||
|
||||
q->modeChanged();
|
||||
q->modeChanged(isInsertMode());
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::enterExMode(const QString &contents)
|
||||
@@ -8671,7 +8671,7 @@ void FakeVimHandler::Private::enterExMode(const QString &contents)
|
||||
g.subsubmode = NoSubSubMode;
|
||||
unfocus();
|
||||
|
||||
q->modeChanged();
|
||||
q->modeChanged(isInsertMode());
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::recordJump(int position)
|
||||
|
@@ -157,7 +157,7 @@ public:
|
||||
Signal<void()> completionRequested;
|
||||
Signal<void()> tabPreviousRequested;
|
||||
Signal<void()> tabNextRequested;
|
||||
Signal<void()> modeChanged;
|
||||
Signal<void(bool insertMode)> modeChanged;
|
||||
|
||||
public:
|
||||
class Private;
|
||||
|
@@ -539,7 +539,22 @@ signals:
|
||||
void delayedQuitAllRequested(bool forced);
|
||||
|
||||
public:
|
||||
QHash<IEditor *, FakeVimHandler *> m_editorToHandler;
|
||||
struct HandlerAndData
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// We need to declare a constructor here, otherwise the MSVC 17.5.x compiler fails to parse
|
||||
// the "{nullptr}" initializer in the definition below.
|
||||
// This seems to be a compiler bug,
|
||||
// see: https://developercommunity.visualstudio.com/t/10351118
|
||||
HandlerAndData()
|
||||
: handler(nullptr)
|
||||
{}
|
||||
#endif
|
||||
FakeVimHandler *handler{nullptr};
|
||||
TextEditorWidget::SuggestionBlocker suggestionBlocker;
|
||||
};
|
||||
|
||||
QHash<IEditor *, HandlerAndData> m_editorToHandler;
|
||||
|
||||
void setActionChecked(Id id, bool check);
|
||||
|
||||
@@ -1253,7 +1268,7 @@ void FakeVimPluginPrivate::initialize()
|
||||
void FakeVimPluginPrivate::userActionTriggered(int key)
|
||||
{
|
||||
IEditor *editor = EditorManager::currentEditor();
|
||||
FakeVimHandler *handler = m_editorToHandler[editor];
|
||||
FakeVimHandler *handler = m_editorToHandler[editor].handler;
|
||||
if (handler) {
|
||||
// If disabled, enable FakeVim mode just for single user command.
|
||||
bool enableFakeVim = !fakeVimSettings()->useFakeVim.value();
|
||||
@@ -1569,14 +1584,14 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||
// the handler might have triggered the deletion of the editor:
|
||||
// make sure that it can return before being deleted itself
|
||||
new DeferredDeleter(widget, handler);
|
||||
m_editorToHandler[editor] = handler;
|
||||
m_editorToHandler[editor].handler = handler;
|
||||
|
||||
handler->extraInformationChanged.connect([this](const QString &text) {
|
||||
EditorManager::splitSideBySide();
|
||||
QString title = "stdout.txt";
|
||||
IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8());
|
||||
EditorManager::activateEditor(iedit);
|
||||
FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr);
|
||||
FakeVimHandler *handler = m_editorToHandler.value(iedit, {}).handler;
|
||||
QTC_ASSERT(handler, return);
|
||||
handler->handleCommand("0");
|
||||
});
|
||||
@@ -1591,7 +1606,13 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||
tew->setExtraSelections(TextEditorWidget::FakeVimSelection, selection);
|
||||
});
|
||||
|
||||
handler->modeChanged.connect([tew]() {
|
||||
handler->modeChanged.connect([tew, this, editor](bool insertMode) {
|
||||
HandlerAndData &handlerAndData = m_editorToHandler[editor];
|
||||
|
||||
// We don't want to show suggestions unless we are in insert mode.
|
||||
if (insertMode != (handlerAndData.suggestionBlocker == nullptr))
|
||||
handlerAndData.suggestionBlocker = insertMode ? nullptr : tew->blockSuggestions();
|
||||
|
||||
if (tew)
|
||||
tew->clearSuggestion();
|
||||
});
|
||||
@@ -1840,7 +1861,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||
handler->requestJumpToGlobalMark.connect(
|
||||
[this](QChar mark, bool backTickMode, const QString &fileName) {
|
||||
if (IEditor *iedit = EditorManager::openEditor(FilePath::fromString(fileName))) {
|
||||
if (FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr))
|
||||
if (FakeVimHandler *handler = m_editorToHandler.value(iedit, {}).handler)
|
||||
handler->jumpToLocalMark(mark, backTickMode);
|
||||
}
|
||||
});
|
||||
@@ -1887,7 +1908,7 @@ void FakeVimPluginPrivate::editorAboutToClose(IEditor *editor)
|
||||
|
||||
void FakeVimPluginPrivate::currentEditorAboutToChange(IEditor *editor)
|
||||
{
|
||||
if (FakeVimHandler *handler = m_editorToHandler.value(editor, 0))
|
||||
if (FakeVimHandler *handler = m_editorToHandler.value(editor, {}).handler)
|
||||
handler->enterCommandMode();
|
||||
}
|
||||
|
||||
@@ -1905,9 +1926,9 @@ void FakeVimPluginPrivate::documentRenamed(
|
||||
|
||||
void FakeVimPluginPrivate::renameFileNameInEditors(const FilePath &oldPath, const FilePath &newPath)
|
||||
{
|
||||
for (FakeVimHandler *handler : m_editorToHandler) {
|
||||
if (handler->currentFileName() == oldPath.toString())
|
||||
handler->setCurrentFileName(newPath.toString());
|
||||
for (const HandlerAndData &handlerAndData : m_editorToHandler) {
|
||||
if (handlerAndData.handler->currentFileName() == oldPath.toString())
|
||||
handlerAndData.handler->setCurrentFileName(newPath.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1926,16 +1947,19 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on)
|
||||
//ICore *core = ICore::instance();
|
||||
//core->updateAdditionalContexts(Context(FAKEVIM_CONTEXT),
|
||||
// Context());
|
||||
for (FakeVimHandler *handler : m_editorToHandler)
|
||||
handler->setupWidget();
|
||||
for (const HandlerAndData &handlerAndData : m_editorToHandler)
|
||||
handlerAndData.handler->setupWidget();
|
||||
} else {
|
||||
//ICore *core = ICore::instance();
|
||||
//core->updateAdditionalContexts(Context(),
|
||||
// Context(FAKEVIM_CONTEXT));
|
||||
resetCommandBuffer();
|
||||
for (auto it = m_editorToHandler.constBegin(); it != m_editorToHandler.constEnd(); ++it) {
|
||||
if (auto textDocument = qobject_cast<const TextDocument *>(it.key()->document()))
|
||||
it.value()->restoreWidget(textDocument->tabSettings().m_tabSize);
|
||||
for (auto it = m_editorToHandler.begin(); it != m_editorToHandler.end(); ++it) {
|
||||
if (auto textDocument = qobject_cast<const TextDocument *>(it.key()->document())) {
|
||||
HandlerAndData &handlerAndData = it.value();
|
||||
handlerAndData.handler->restoreWidget(textDocument->tabSettings().m_tabSize);
|
||||
handlerAndData.suggestionBlocker.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1970,11 +1994,22 @@ void FakeVimPluginPrivate::handleExCommand(FakeVimHandler *handler, bool *handle
|
||||
if (editor)
|
||||
editor->setFocus();
|
||||
|
||||
auto editorFromHandler = [this, handler]() -> Core::IEditor * {
|
||||
auto itEditor = std::find_if(m_editorToHandler.cbegin(),
|
||||
m_editorToHandler.cend(),
|
||||
[handler](const HandlerAndData &handlerAndData) {
|
||||
return handlerAndData.handler == handler;
|
||||
});
|
||||
if (itEditor != m_editorToHandler.cend())
|
||||
return itEditor.key();
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
*handled = true;
|
||||
if ((cmd.matches("w", "write") || cmd.cmd == "wq") && cmd.args.isEmpty()) {
|
||||
// :w[rite]
|
||||
bool saved = false;
|
||||
IEditor *editor = m_editorToHandler.key(handler);
|
||||
IEditor *editor = editorFromHandler();
|
||||
const QString fileName = handler->currentFileName();
|
||||
if (editor && editor->document()->filePath().toString() == fileName) {
|
||||
triggerAction(Core::Constants::SAVE);
|
||||
@@ -1986,7 +2021,7 @@ void FakeVimPluginPrivate::handleExCommand(FakeVimHandler *handler, bool *handle
|
||||
handler->showMessage(MessageInfo, Tr::tr("\"%1\" %2 %3L, %4C written")
|
||||
.arg(fileName).arg(' ').arg(ba.count('\n')).arg(ba.size()));
|
||||
if (cmd.cmd == "wq")
|
||||
emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
|
||||
emit delayedQuitRequested(cmd.hasBang, editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2005,7 +2040,7 @@ void FakeVimPluginPrivate::handleExCommand(FakeVimHandler *handler, bool *handle
|
||||
emit delayedQuitAllRequested(cmd.hasBang);
|
||||
} else if (cmd.matches("q", "quit")) {
|
||||
// :q[uit]
|
||||
emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
|
||||
emit delayedQuitRequested(cmd.hasBang, editorFromHandler());
|
||||
} else if (cmd.matches("qa", "qall")) {
|
||||
// :qa[ll]
|
||||
emit delayedQuitAllRequested(cmd.hasBang);
|
||||
@@ -2167,7 +2202,7 @@ void FakeVimPlugin::setupTest(QString *title, FakeVimHandler **handler, QWidget
|
||||
IEditor *iedit = EditorManager::openEditorWithContents(Id(), title);
|
||||
EditorManager::activateEditor(iedit);
|
||||
*edit = iedit->widget();
|
||||
*handler = dd->m_editorToHandler.value(iedit, 0);
|
||||
*handler = dd->m_editorToHandler.value(iedit, {}).handler;
|
||||
(*handler)->setupWidget();
|
||||
(*handler)->handleCommand("set startofline");
|
||||
|
||||
|
@@ -657,6 +657,7 @@ public:
|
||||
uint m_optionalActionMask = TextEditorActionHandler::None;
|
||||
bool m_contentsChanged = false;
|
||||
bool m_lastCursorChangeWasInteresting = false;
|
||||
std::shared_ptr<void> m_suggestionBlocker;
|
||||
|
||||
QSharedPointer<TextDocument> m_document;
|
||||
QList<QMetaObject::Connection> m_documentConnections;
|
||||
@@ -905,6 +906,7 @@ void TextEditorWidgetFind::cancelCurrentSelectAll()
|
||||
|
||||
TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
|
||||
: q(parent)
|
||||
, m_suggestionBlocker((void *) this, [](void *) {})
|
||||
, m_overlay(new TextEditorOverlay(q))
|
||||
, m_snippetOverlay(new SnippetOverlay(q))
|
||||
, m_searchResultOverlay(new TextEditorOverlay(q))
|
||||
@@ -1654,6 +1656,10 @@ void TextEditorWidgetPrivate::handleMoveBlockSelection(QTextCursor::MoveOperatio
|
||||
void TextEditorWidgetPrivate::insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion)
|
||||
{
|
||||
clearCurrentSuggestion();
|
||||
|
||||
if (m_suggestionBlocker.use_count() > 1)
|
||||
return;
|
||||
|
||||
auto cursor = q->textCursor();
|
||||
cursor.setPosition(suggestion->position());
|
||||
m_suggestionBlock = cursor.block();
|
||||
@@ -6017,6 +6023,18 @@ bool TextEditorWidget::suggestionVisible() const
|
||||
return currentSuggestion();
|
||||
}
|
||||
|
||||
bool TextEditorWidget::suggestionsBlocked() const
|
||||
{
|
||||
return d->m_suggestionBlocker.use_count() > 1;
|
||||
}
|
||||
|
||||
TextEditorWidget::SuggestionBlocker TextEditorWidget::blockSuggestions()
|
||||
{
|
||||
if (!suggestionsBlocked())
|
||||
clearSuggestion();
|
||||
return d->m_suggestionBlocker;
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
void TextEditorWidget::processTooltipRequest(const QTextCursor &c)
|
||||
{
|
||||
|
@@ -475,6 +475,11 @@ public:
|
||||
void clearSuggestion();
|
||||
TextSuggestion *currentSuggestion() const;
|
||||
bool suggestionVisible() const;
|
||||
bool suggestionsBlocked() const;
|
||||
|
||||
using SuggestionBlocker = std::shared_ptr<void>;
|
||||
// Returns an object that blocks suggestions until it is destroyed.
|
||||
SuggestionBlocker blockSuggestions();
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
void processTooltipRequest(const QTextCursor &c);
|
||||
|
Reference in New Issue
Block a user