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();
|
const int cursorPosition = widget->textCursor().position();
|
||||||
if (cursorPosition < position || cursorPosition > position + charsAdded)
|
if (cursorPosition < position || cursorPosition > position + charsAdded)
|
||||||
return;
|
return;
|
||||||
scheduleRequest(textEditor->editorWidget());
|
scheduleRequest(widget);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5197,7 +5197,7 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input)
|
|||||||
moveDown();
|
moveDown();
|
||||||
} else if (input.isKey(Key_Insert)) {
|
} else if (input.isKey(Key_Insert)) {
|
||||||
g.mode = InsertMode;
|
g.mode = InsertMode;
|
||||||
q->modeChanged();
|
q->modeChanged(isInsertMode());
|
||||||
} else if (input.isControl('o')) {
|
} else if (input.isControl('o')) {
|
||||||
enterCommandMode(ReplaceMode);
|
enterCommandMode(ReplaceMode);
|
||||||
} else {
|
} else {
|
||||||
@@ -5395,7 +5395,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
removeText(range);
|
removeText(range);
|
||||||
} else if (input.isKey(Key_Insert)) {
|
} else if (input.isKey(Key_Insert)) {
|
||||||
g.mode = ReplaceMode;
|
g.mode = ReplaceMode;
|
||||||
q->modeChanged();
|
q->modeChanged(isInsertMode());
|
||||||
} else if (input.isKey(Key_Left)) {
|
} else if (input.isKey(Key_Left)) {
|
||||||
moveLeft();
|
moveLeft();
|
||||||
} else if (input.isShift(Key_Left) || input.isControl(Key_Left)) {
|
} else if (input.isShift(Key_Left) || input.isControl(Key_Left)) {
|
||||||
@@ -8578,7 +8578,7 @@ void FakeVimHandler::Private::enterInsertOrReplaceMode(Mode mode)
|
|||||||
clearLastInsertion();
|
clearLastInsertion();
|
||||||
}
|
}
|
||||||
|
|
||||||
q->modeChanged();
|
q->modeChanged(isInsertMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::enterVisualInsertMode(QChar command)
|
void FakeVimHandler::Private::enterVisualInsertMode(QChar command)
|
||||||
@@ -8655,7 +8655,7 @@ void FakeVimHandler::Private::enterCommandMode(Mode returnToMode)
|
|||||||
m_positionPastEnd = false;
|
m_positionPastEnd = false;
|
||||||
m_anchorPastEnd = false;
|
m_anchorPastEnd = false;
|
||||||
|
|
||||||
q->modeChanged();
|
q->modeChanged(isInsertMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::enterExMode(const QString &contents)
|
void FakeVimHandler::Private::enterExMode(const QString &contents)
|
||||||
@@ -8671,7 +8671,7 @@ void FakeVimHandler::Private::enterExMode(const QString &contents)
|
|||||||
g.subsubmode = NoSubSubMode;
|
g.subsubmode = NoSubSubMode;
|
||||||
unfocus();
|
unfocus();
|
||||||
|
|
||||||
q->modeChanged();
|
q->modeChanged(isInsertMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::recordJump(int position)
|
void FakeVimHandler::Private::recordJump(int position)
|
||||||
|
@@ -157,7 +157,7 @@ public:
|
|||||||
Signal<void()> completionRequested;
|
Signal<void()> completionRequested;
|
||||||
Signal<void()> tabPreviousRequested;
|
Signal<void()> tabPreviousRequested;
|
||||||
Signal<void()> tabNextRequested;
|
Signal<void()> tabNextRequested;
|
||||||
Signal<void()> modeChanged;
|
Signal<void(bool insertMode)> modeChanged;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Private;
|
class Private;
|
||||||
|
@@ -539,7 +539,22 @@ signals:
|
|||||||
void delayedQuitAllRequested(bool forced);
|
void delayedQuitAllRequested(bool forced);
|
||||||
|
|
||||||
public:
|
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);
|
void setActionChecked(Id id, bool check);
|
||||||
|
|
||||||
@@ -1253,7 +1268,7 @@ void FakeVimPluginPrivate::initialize()
|
|||||||
void FakeVimPluginPrivate::userActionTriggered(int key)
|
void FakeVimPluginPrivate::userActionTriggered(int key)
|
||||||
{
|
{
|
||||||
IEditor *editor = EditorManager::currentEditor();
|
IEditor *editor = EditorManager::currentEditor();
|
||||||
FakeVimHandler *handler = m_editorToHandler[editor];
|
FakeVimHandler *handler = m_editorToHandler[editor].handler;
|
||||||
if (handler) {
|
if (handler) {
|
||||||
// If disabled, enable FakeVim mode just for single user command.
|
// If disabled, enable FakeVim mode just for single user command.
|
||||||
bool enableFakeVim = !fakeVimSettings()->useFakeVim.value();
|
bool enableFakeVim = !fakeVimSettings()->useFakeVim.value();
|
||||||
@@ -1569,14 +1584,14 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
|||||||
// the handler might have triggered the deletion of the editor:
|
// the handler might have triggered the deletion of the editor:
|
||||||
// make sure that it can return before being deleted itself
|
// make sure that it can return before being deleted itself
|
||||||
new DeferredDeleter(widget, handler);
|
new DeferredDeleter(widget, handler);
|
||||||
m_editorToHandler[editor] = handler;
|
m_editorToHandler[editor].handler = handler;
|
||||||
|
|
||||||
handler->extraInformationChanged.connect([this](const QString &text) {
|
handler->extraInformationChanged.connect([this](const QString &text) {
|
||||||
EditorManager::splitSideBySide();
|
EditorManager::splitSideBySide();
|
||||||
QString title = "stdout.txt";
|
QString title = "stdout.txt";
|
||||||
IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8());
|
IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8());
|
||||||
EditorManager::activateEditor(iedit);
|
EditorManager::activateEditor(iedit);
|
||||||
FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr);
|
FakeVimHandler *handler = m_editorToHandler.value(iedit, {}).handler;
|
||||||
QTC_ASSERT(handler, return);
|
QTC_ASSERT(handler, return);
|
||||||
handler->handleCommand("0");
|
handler->handleCommand("0");
|
||||||
});
|
});
|
||||||
@@ -1591,7 +1606,13 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
|||||||
tew->setExtraSelections(TextEditorWidget::FakeVimSelection, selection);
|
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)
|
if (tew)
|
||||||
tew->clearSuggestion();
|
tew->clearSuggestion();
|
||||||
});
|
});
|
||||||
@@ -1840,7 +1861,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
|||||||
handler->requestJumpToGlobalMark.connect(
|
handler->requestJumpToGlobalMark.connect(
|
||||||
[this](QChar mark, bool backTickMode, const QString &fileName) {
|
[this](QChar mark, bool backTickMode, const QString &fileName) {
|
||||||
if (IEditor *iedit = EditorManager::openEditor(FilePath::fromString(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);
|
handler->jumpToLocalMark(mark, backTickMode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1887,7 +1908,7 @@ void FakeVimPluginPrivate::editorAboutToClose(IEditor *editor)
|
|||||||
|
|
||||||
void FakeVimPluginPrivate::currentEditorAboutToChange(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();
|
handler->enterCommandMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1905,9 +1926,9 @@ void FakeVimPluginPrivate::documentRenamed(
|
|||||||
|
|
||||||
void FakeVimPluginPrivate::renameFileNameInEditors(const FilePath &oldPath, const FilePath &newPath)
|
void FakeVimPluginPrivate::renameFileNameInEditors(const FilePath &oldPath, const FilePath &newPath)
|
||||||
{
|
{
|
||||||
for (FakeVimHandler *handler : m_editorToHandler) {
|
for (const HandlerAndData &handlerAndData : m_editorToHandler) {
|
||||||
if (handler->currentFileName() == oldPath.toString())
|
if (handlerAndData.handler->currentFileName() == oldPath.toString())
|
||||||
handler->setCurrentFileName(newPath.toString());
|
handlerAndData.handler->setCurrentFileName(newPath.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1926,16 +1947,19 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on)
|
|||||||
//ICore *core = ICore::instance();
|
//ICore *core = ICore::instance();
|
||||||
//core->updateAdditionalContexts(Context(FAKEVIM_CONTEXT),
|
//core->updateAdditionalContexts(Context(FAKEVIM_CONTEXT),
|
||||||
// Context());
|
// Context());
|
||||||
for (FakeVimHandler *handler : m_editorToHandler)
|
for (const HandlerAndData &handlerAndData : m_editorToHandler)
|
||||||
handler->setupWidget();
|
handlerAndData.handler->setupWidget();
|
||||||
} else {
|
} else {
|
||||||
//ICore *core = ICore::instance();
|
//ICore *core = ICore::instance();
|
||||||
//core->updateAdditionalContexts(Context(),
|
//core->updateAdditionalContexts(Context(),
|
||||||
// Context(FAKEVIM_CONTEXT));
|
// Context(FAKEVIM_CONTEXT));
|
||||||
resetCommandBuffer();
|
resetCommandBuffer();
|
||||||
for (auto it = m_editorToHandler.constBegin(); it != m_editorToHandler.constEnd(); ++it) {
|
for (auto it = m_editorToHandler.begin(); it != m_editorToHandler.end(); ++it) {
|
||||||
if (auto textDocument = qobject_cast<const TextDocument *>(it.key()->document()))
|
if (auto textDocument = qobject_cast<const TextDocument *>(it.key()->document())) {
|
||||||
it.value()->restoreWidget(textDocument->tabSettings().m_tabSize);
|
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)
|
if (editor)
|
||||||
editor->setFocus();
|
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;
|
*handled = true;
|
||||||
if ((cmd.matches("w", "write") || cmd.cmd == "wq") && cmd.args.isEmpty()) {
|
if ((cmd.matches("w", "write") || cmd.cmd == "wq") && cmd.args.isEmpty()) {
|
||||||
// :w[rite]
|
// :w[rite]
|
||||||
bool saved = false;
|
bool saved = false;
|
||||||
IEditor *editor = m_editorToHandler.key(handler);
|
IEditor *editor = editorFromHandler();
|
||||||
const QString fileName = handler->currentFileName();
|
const QString fileName = handler->currentFileName();
|
||||||
if (editor && editor->document()->filePath().toString() == fileName) {
|
if (editor && editor->document()->filePath().toString() == fileName) {
|
||||||
triggerAction(Core::Constants::SAVE);
|
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")
|
handler->showMessage(MessageInfo, Tr::tr("\"%1\" %2 %3L, %4C written")
|
||||||
.arg(fileName).arg(' ').arg(ba.count('\n')).arg(ba.size()));
|
.arg(fileName).arg(' ').arg(ba.count('\n')).arg(ba.size()));
|
||||||
if (cmd.cmd == "wq")
|
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);
|
emit delayedQuitAllRequested(cmd.hasBang);
|
||||||
} else if (cmd.matches("q", "quit")) {
|
} else if (cmd.matches("q", "quit")) {
|
||||||
// :q[uit]
|
// :q[uit]
|
||||||
emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
|
emit delayedQuitRequested(cmd.hasBang, editorFromHandler());
|
||||||
} else if (cmd.matches("qa", "qall")) {
|
} else if (cmd.matches("qa", "qall")) {
|
||||||
// :qa[ll]
|
// :qa[ll]
|
||||||
emit delayedQuitAllRequested(cmd.hasBang);
|
emit delayedQuitAllRequested(cmd.hasBang);
|
||||||
@@ -2167,7 +2202,7 @@ void FakeVimPlugin::setupTest(QString *title, FakeVimHandler **handler, QWidget
|
|||||||
IEditor *iedit = EditorManager::openEditorWithContents(Id(), title);
|
IEditor *iedit = EditorManager::openEditorWithContents(Id(), title);
|
||||||
EditorManager::activateEditor(iedit);
|
EditorManager::activateEditor(iedit);
|
||||||
*edit = iedit->widget();
|
*edit = iedit->widget();
|
||||||
*handler = dd->m_editorToHandler.value(iedit, 0);
|
*handler = dd->m_editorToHandler.value(iedit, {}).handler;
|
||||||
(*handler)->setupWidget();
|
(*handler)->setupWidget();
|
||||||
(*handler)->handleCommand("set startofline");
|
(*handler)->handleCommand("set startofline");
|
||||||
|
|
||||||
|
@@ -657,6 +657,7 @@ public:
|
|||||||
uint m_optionalActionMask = TextEditorActionHandler::None;
|
uint m_optionalActionMask = TextEditorActionHandler::None;
|
||||||
bool m_contentsChanged = false;
|
bool m_contentsChanged = false;
|
||||||
bool m_lastCursorChangeWasInteresting = false;
|
bool m_lastCursorChangeWasInteresting = false;
|
||||||
|
std::shared_ptr<void> m_suggestionBlocker;
|
||||||
|
|
||||||
QSharedPointer<TextDocument> m_document;
|
QSharedPointer<TextDocument> m_document;
|
||||||
QList<QMetaObject::Connection> m_documentConnections;
|
QList<QMetaObject::Connection> m_documentConnections;
|
||||||
@@ -905,6 +906,7 @@ void TextEditorWidgetFind::cancelCurrentSelectAll()
|
|||||||
|
|
||||||
TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
|
TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
|
||||||
: q(parent)
|
: q(parent)
|
||||||
|
, m_suggestionBlocker((void *) this, [](void *) {})
|
||||||
, m_overlay(new TextEditorOverlay(q))
|
, m_overlay(new TextEditorOverlay(q))
|
||||||
, m_snippetOverlay(new SnippetOverlay(q))
|
, m_snippetOverlay(new SnippetOverlay(q))
|
||||||
, m_searchResultOverlay(new TextEditorOverlay(q))
|
, m_searchResultOverlay(new TextEditorOverlay(q))
|
||||||
@@ -1654,6 +1656,10 @@ void TextEditorWidgetPrivate::handleMoveBlockSelection(QTextCursor::MoveOperatio
|
|||||||
void TextEditorWidgetPrivate::insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion)
|
void TextEditorWidgetPrivate::insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion)
|
||||||
{
|
{
|
||||||
clearCurrentSuggestion();
|
clearCurrentSuggestion();
|
||||||
|
|
||||||
|
if (m_suggestionBlocker.use_count() > 1)
|
||||||
|
return;
|
||||||
|
|
||||||
auto cursor = q->textCursor();
|
auto cursor = q->textCursor();
|
||||||
cursor.setPosition(suggestion->position());
|
cursor.setPosition(suggestion->position());
|
||||||
m_suggestionBlock = cursor.block();
|
m_suggestionBlock = cursor.block();
|
||||||
@@ -6017,6 +6023,18 @@ bool TextEditorWidget::suggestionVisible() const
|
|||||||
return currentSuggestion();
|
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
|
#ifdef WITH_TESTS
|
||||||
void TextEditorWidget::processTooltipRequest(const QTextCursor &c)
|
void TextEditorWidget::processTooltipRequest(const QTextCursor &c)
|
||||||
{
|
{
|
||||||
|
@@ -475,6 +475,11 @@ public:
|
|||||||
void clearSuggestion();
|
void clearSuggestion();
|
||||||
TextSuggestion *currentSuggestion() const;
|
TextSuggestion *currentSuggestion() const;
|
||||||
bool suggestionVisible() 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
|
#ifdef WITH_TESTS
|
||||||
void processTooltipRequest(const QTextCursor &c);
|
void processTooltipRequest(const QTextCursor &c);
|
||||||
|
Reference in New Issue
Block a user