aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Praschan <tom@praschan.de>2021-01-30 12:29:14 +0100
committerTom Praschan <tom@praschan.de>2021-02-10 16:11:50 +0000
commitf83eeb0548e2d57446bdf2a533ce75a9819a53aa (patch)
treeea65d2ea057b9125ed09a7b300dd7dce4ec12349
parent3b1bc1d0534ed2ec65490afa5b3723b2cc8e2d3d (diff)
FakeVim: Add emulation of vim-exchange plugin
Change-Id: I844c9bf11231ab842cee020a0e7a29af8ed209eb Reviewed-by: hjk <hjk@qt.io>
-rw-r--r--doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc1
-rw-r--r--src/plugins/fakevim/fakevim_test.cpp28
-rw-r--r--src/plugins/fakevim/fakevimactions.cpp1
-rw-r--r--src/plugins/fakevim/fakevimactions.h1
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp70
-rw-r--r--src/plugins/fakevim/fakevimoptions.ui9
-rw-r--r--src/plugins/fakevim/fakevimplugin.cpp1
-rw-r--r--src/plugins/fakevim/fakevimplugin.h1
8 files changed, 111 insertions, 1 deletions
diff --git a/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc b/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
index 7ac4bea02d0..a35b0f7e19c 100644
--- a/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
+++ b/doc/qtcreator/src/editors/creator-only/creator-fakevim.qdoc
@@ -128,6 +128,7 @@
\li \c [count]["x]gr{motion} to replace \c {motion} with the contents of
register \c x.
\li ["x]grr to replace the current line.
+ \l{https://github.com/tommcdo/vim-exchange}{vim-exchange}
\endlist
\endlist
diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp
index 14f8d7dd315..a5bf90cf563 100644
--- a/src/plugins/fakevim/fakevim_test.cpp
+++ b/src/plugins/fakevim/fakevim_test.cpp
@@ -4289,6 +4289,34 @@ void FakeVimPlugin::test_vim_replace_with_register_emulation()
KEYS("v4lgr", "abc abci");
}
+void FakeVimPlugin::test_vim_exchange_emulation()
+{
+ TestData data;
+ setup(&data);
+ data.doCommand("set exchange");
+
+ // Simple exchange
+ data.setText("abc def");
+ KEYS("cxiw", "abc def");
+ KEYS("W", "abc " X "def");
+ KEYS(".", "def abc");
+
+ // Clearing pending exchange
+ data.setText("abc def ghi");
+ KEYS("cxiw", "abc def ghi");
+ KEYS("cxc", "abc def ghi");
+ KEYS("W", "abc " X "def ghi");
+ KEYS("cxiw", "abc def" X " ghi");
+ KEYS("W", "abc def " X "ghi");
+ KEYS(".", "abc ghi def");
+
+ // Exchange line
+ data.setText("abc" N "def");
+ KEYS("cxx", "abc" N "def");
+ KEYS("j", "abc" N "def");
+ KEYS(".", "def" N "abc");
+}
+
void FakeVimPlugin::test_macros()
{
TestData data;
diff --git a/src/plugins/fakevim/fakevimactions.cpp b/src/plugins/fakevim/fakevimactions.cpp
index c32ca25a57b..51377387833 100644
--- a/src/plugins/fakevim/fakevimactions.cpp
+++ b/src/plugins/fakevim/fakevimactions.cpp
@@ -118,6 +118,7 @@ FakeVimSettings::FakeVimSettings()
// Emulated plugins
createAction(ConfigEmulateVimCommentary, false, "commentary");
createAction(ConfigEmulateReplaceWithRegister, false, "ReplaceWithRegister");
+ createAction(ConfigEmulateExchange, false, "exchange");
}
FakeVimSettings::~FakeVimSettings()
diff --git a/src/plugins/fakevim/fakevimactions.h b/src/plugins/fakevim/fakevimactions.h
index 828ad5204d3..b1de54a60e4 100644
--- a/src/plugins/fakevim/fakevimactions.h
+++ b/src/plugins/fakevim/fakevimactions.h
@@ -112,6 +112,7 @@ enum FakeVimSettingsCode
// Plugin emulation
ConfigEmulateVimCommentary,
ConfigEmulateReplaceWithRegister,
+ ConfigEmulateExchange,
ConfigBlinkingCursor
};
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index fe3f2262e51..5c393a714c4 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -168,6 +168,7 @@ enum SubMode
NoSubMode,
ChangeSubMode, // Used for c
DeleteSubMode, // Used for d
+ ExchangeSubMode, // Used for cx
FilterSubMode, // Used for !
IndentSubMode, // Used for =
RegisterSubMode, // Used for "
@@ -1346,6 +1347,8 @@ QString dotCommandFromSubMode(SubMode submode)
return QLatin1String("d");
if (submode == CommentSubMode)
return QLatin1String("gc");
+ if (submode == ExchangeSubMode)
+ return QLatin1String("cx");
if (submode == ReplaceWithRegisterSubMode)
return QLatin1String("gr");
if (submode == InvertCaseSubMode)
@@ -1830,6 +1833,7 @@ public:
bool handleReplaceSubMode(const Input &);
bool handleCommentSubMode(const Input &);
bool handleReplaceWithRegisterSubMode(const Input &);
+ bool handleExchangeSubMode(const Input &);
bool handleFilterSubMode(const Input &);
bool handleRegisterSubMode(const Input &);
bool handleShiftSubMode(const Input &);
@@ -2092,6 +2096,7 @@ public:
bool isOperatorPending() const {
return g.submode == ChangeSubMode
|| g.submode == DeleteSubMode
+ || g.submode == ExchangeSubMode
|| g.submode == CommentSubMode
|| g.submode == ReplaceWithRegisterSubMode
|| g.submode == FilterSubMode
@@ -2171,6 +2176,8 @@ public:
void toggleComment(const Range &range);
+ void exchangeRange(const Range &range);
+
void replaceWithRegister(const Range &range);
void upCase(const Range &range);
@@ -2409,6 +2416,10 @@ public:
QString recorded;
int currentRegister = 0;
int lastExecutedRegister = 0;
+
+ // If empty, cx{motion} will store the range defined by {motion} here.
+ // If non-empty, cx{motion} replaces the {motion} with selectText(*exchangeData)
+ std::optional<Range> exchangeRange;
} g;
};
@@ -3597,6 +3608,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
if (g.submode == ChangeSubMode
|| g.submode == DeleteSubMode
|| g.submode == CommentSubMode
+ || g.submode == ExchangeSubMode
|| g.submode == ReplaceWithRegisterSubMode
|| g.submode == YankSubMode
|| g.submode == InvertCaseSubMode
@@ -3629,6 +3641,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
beginEditBlock();
toggleComment(currentRange());
endEditBlock();
+ } else if (g.submode == ExchangeSubMode) {
+ exchangeRange(currentRange());
} else if (g.submode == ReplaceWithRegisterSubMode
&& hasConfig(ConfigEmulateReplaceWithRegister)) {
pushUndoState(false);
@@ -4281,6 +4295,12 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
handled = handleCommandSubSubMode(input);
} else if (g.submode == NoSubMode) {
handled = handleNoSubMode(input);
+ } else if (g.submode == ExchangeSubMode) {
+ handled = handleExchangeSubMode(input);
+ } else if (g.submode == ChangeSubMode && input.is('x') && hasConfig(ConfigEmulateExchange)) {
+ // Exchange submode is "cx", so we need to switch over from ChangeSubMode here
+ g.submode = ExchangeSubMode;
+ handled = true;
} else if (g.submode == ChangeSubMode
|| g.submode == DeleteSubMode
|| g.submode == YankSubMode) {
@@ -4842,6 +4862,30 @@ bool FakeVimHandler::Private::handleReplaceWithRegisterSubMode(const Input &inpu
return true;
}
+bool FakeVimHandler::Private::handleExchangeSubMode(const Input &input)
+{
+ if (input.is('c')) { // cxc
+ g.exchangeRange.reset();
+ g.submode = NoSubMode;
+ return true;
+ }
+
+ if (input.is('x')) { // cxx
+ setAnchorAndPosition(firstPositionInLine(cursorLine() + 1),
+ lastPositionInLine(cursorLine() + 1) + 1);
+
+ setDotCommand("cxx");
+
+ finishMovement();
+
+ g.submode = NoSubMode;
+
+ return true;
+ }
+
+ return false;
+}
+
bool FakeVimHandler::Private::handleFilterSubMode(const Input &)
{
return false;
@@ -7484,6 +7528,32 @@ void FakeVimHandler::Private::toggleComment(const Range &range)
});
}
+void FakeVimHandler::Private::exchangeRange(const Range &range)
+{
+ if (g.exchangeRange) {
+ pushUndoState(false);
+ beginEditBlock();
+
+ Range leftRange = *g.exchangeRange;
+ Range rightRange = range;
+ if (leftRange.beginPos > rightRange.beginPos)
+ std::swap(leftRange, rightRange);
+
+ // First replace the right range, then left one
+ // If we did it the other way around, we would invalidate the positions
+ // of the right range
+ const QString rightText = selectText(rightRange);
+ replaceText(rightRange, selectText(leftRange));
+ replaceText(leftRange, rightText);
+
+ g.exchangeRange.reset();
+
+ endEditBlock();
+ } else {
+ g.exchangeRange = range;
+ }
+}
+
void FakeVimHandler::Private::replaceWithRegister(const Range &range)
{
replaceText(range, registerContents(m_register));
diff --git a/src/plugins/fakevim/fakevimoptions.ui b/src/plugins/fakevim/fakevimoptions.ui
index d8e26e2c509..c7d2d2e688a 100644
--- a/src/plugins/fakevim/fakevimoptions.ui
+++ b/src/plugins/fakevim/fakevimoptions.ui
@@ -165,7 +165,7 @@
<item row="0" column="0">
<widget class="QCheckBox" name="checkBoxVimCommentary">
<property name="text">
- <string>Vim-commentary</string>
+ <string>vim-commentary</string>
</property>
<property name="checked">
<bool>false</bool>
@@ -179,6 +179,13 @@
</property>
</widget>
</item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="checkBoxExchange">
+ <property name="text">
+ <string>vim-exchange</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp
index e11310d7de6..a2f34d268bd 100644
--- a/src/plugins/fakevim/fakevimplugin.cpp
+++ b/src/plugins/fakevim/fakevimplugin.cpp
@@ -431,6 +431,7 @@ QWidget *FakeVimOptionPage::widget()
m_group.insert(theFakeVimSetting(ConfigEmulateVimCommentary), m_ui.checkBoxVimCommentary);
m_group.insert(theFakeVimSetting(ConfigEmulateReplaceWithRegister), m_ui.checkBoxReplaceWithRegister);
+ m_group.insert(theFakeVimSetting(ConfigEmulateExchange), m_ui.checkBoxExchange);
connect(m_ui.pushButtonCopyTextEditorSettings, &QAbstractButton::clicked,
this, &FakeVimOptionPage::copyTextEditorSettings);
diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h
index ad5d64fb2fb..37950c37d40 100644
--- a/src/plugins/fakevim/fakevimplugin.h
+++ b/src/plugins/fakevim/fakevimplugin.h
@@ -161,6 +161,7 @@ private slots:
void test_vim_commentary_emulation();
void test_vim_commentary_file_names();
void test_vim_replace_with_register_emulation();
+ void test_vim_exchange_emulation();
void test_macros();