forked from qt-creator/qt-creator
FakeVim: Add emulation of vim-exchange plugin
Change-Id: I844c9bf11231ab842cee020a0e7a29af8ed209eb Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -128,6 +128,7 @@
|
|||||||
\li \c [count]["x]gr{motion} to replace \c {motion} with the contents of
|
\li \c [count]["x]gr{motion} to replace \c {motion} with the contents of
|
||||||
register \c x.
|
register \c x.
|
||||||
\li ["x]grr to replace the current line.
|
\li ["x]grr to replace the current line.
|
||||||
|
\l{https://github.com/tommcdo/vim-exchange}{vim-exchange}
|
||||||
\endlist
|
\endlist
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
|||||||
@@ -4289,6 +4289,34 @@ void FakeVimPlugin::test_vim_replace_with_register_emulation()
|
|||||||
KEYS("v4lgr", "abc abci");
|
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()
|
void FakeVimPlugin::test_macros()
|
||||||
{
|
{
|
||||||
TestData data;
|
TestData data;
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ FakeVimSettings::FakeVimSettings()
|
|||||||
// Emulated plugins
|
// Emulated plugins
|
||||||
createAction(ConfigEmulateVimCommentary, false, "commentary");
|
createAction(ConfigEmulateVimCommentary, false, "commentary");
|
||||||
createAction(ConfigEmulateReplaceWithRegister, false, "ReplaceWithRegister");
|
createAction(ConfigEmulateReplaceWithRegister, false, "ReplaceWithRegister");
|
||||||
|
createAction(ConfigEmulateExchange, false, "exchange");
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeVimSettings::~FakeVimSettings()
|
FakeVimSettings::~FakeVimSettings()
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ enum FakeVimSettingsCode
|
|||||||
// Plugin emulation
|
// Plugin emulation
|
||||||
ConfigEmulateVimCommentary,
|
ConfigEmulateVimCommentary,
|
||||||
ConfigEmulateReplaceWithRegister,
|
ConfigEmulateReplaceWithRegister,
|
||||||
|
ConfigEmulateExchange,
|
||||||
|
|
||||||
ConfigBlinkingCursor
|
ConfigBlinkingCursor
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ enum SubMode
|
|||||||
NoSubMode,
|
NoSubMode,
|
||||||
ChangeSubMode, // Used for c
|
ChangeSubMode, // Used for c
|
||||||
DeleteSubMode, // Used for d
|
DeleteSubMode, // Used for d
|
||||||
|
ExchangeSubMode, // Used for cx
|
||||||
FilterSubMode, // Used for !
|
FilterSubMode, // Used for !
|
||||||
IndentSubMode, // Used for =
|
IndentSubMode, // Used for =
|
||||||
RegisterSubMode, // Used for "
|
RegisterSubMode, // Used for "
|
||||||
@@ -1346,6 +1347,8 @@ QString dotCommandFromSubMode(SubMode submode)
|
|||||||
return QLatin1String("d");
|
return QLatin1String("d");
|
||||||
if (submode == CommentSubMode)
|
if (submode == CommentSubMode)
|
||||||
return QLatin1String("gc");
|
return QLatin1String("gc");
|
||||||
|
if (submode == ExchangeSubMode)
|
||||||
|
return QLatin1String("cx");
|
||||||
if (submode == ReplaceWithRegisterSubMode)
|
if (submode == ReplaceWithRegisterSubMode)
|
||||||
return QLatin1String("gr");
|
return QLatin1String("gr");
|
||||||
if (submode == InvertCaseSubMode)
|
if (submode == InvertCaseSubMode)
|
||||||
@@ -1830,6 +1833,7 @@ public:
|
|||||||
bool handleReplaceSubMode(const Input &);
|
bool handleReplaceSubMode(const Input &);
|
||||||
bool handleCommentSubMode(const Input &);
|
bool handleCommentSubMode(const Input &);
|
||||||
bool handleReplaceWithRegisterSubMode(const Input &);
|
bool handleReplaceWithRegisterSubMode(const Input &);
|
||||||
|
bool handleExchangeSubMode(const Input &);
|
||||||
bool handleFilterSubMode(const Input &);
|
bool handleFilterSubMode(const Input &);
|
||||||
bool handleRegisterSubMode(const Input &);
|
bool handleRegisterSubMode(const Input &);
|
||||||
bool handleShiftSubMode(const Input &);
|
bool handleShiftSubMode(const Input &);
|
||||||
@@ -2092,6 +2096,7 @@ public:
|
|||||||
bool isOperatorPending() const {
|
bool isOperatorPending() const {
|
||||||
return g.submode == ChangeSubMode
|
return g.submode == ChangeSubMode
|
||||||
|| g.submode == DeleteSubMode
|
|| g.submode == DeleteSubMode
|
||||||
|
|| g.submode == ExchangeSubMode
|
||||||
|| g.submode == CommentSubMode
|
|| g.submode == CommentSubMode
|
||||||
|| g.submode == ReplaceWithRegisterSubMode
|
|| g.submode == ReplaceWithRegisterSubMode
|
||||||
|| g.submode == FilterSubMode
|
|| g.submode == FilterSubMode
|
||||||
@@ -2171,6 +2176,8 @@ public:
|
|||||||
|
|
||||||
void toggleComment(const Range &range);
|
void toggleComment(const Range &range);
|
||||||
|
|
||||||
|
void exchangeRange(const Range &range);
|
||||||
|
|
||||||
void replaceWithRegister(const Range &range);
|
void replaceWithRegister(const Range &range);
|
||||||
|
|
||||||
void upCase(const Range &range);
|
void upCase(const Range &range);
|
||||||
@@ -2409,6 +2416,10 @@ public:
|
|||||||
QString recorded;
|
QString recorded;
|
||||||
int currentRegister = 0;
|
int currentRegister = 0;
|
||||||
int lastExecutedRegister = 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;
|
} g;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3597,6 +3608,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
|
|||||||
if (g.submode == ChangeSubMode
|
if (g.submode == ChangeSubMode
|
||||||
|| g.submode == DeleteSubMode
|
|| g.submode == DeleteSubMode
|
||||||
|| g.submode == CommentSubMode
|
|| g.submode == CommentSubMode
|
||||||
|
|| g.submode == ExchangeSubMode
|
||||||
|| g.submode == ReplaceWithRegisterSubMode
|
|| g.submode == ReplaceWithRegisterSubMode
|
||||||
|| g.submode == YankSubMode
|
|| g.submode == YankSubMode
|
||||||
|| g.submode == InvertCaseSubMode
|
|| g.submode == InvertCaseSubMode
|
||||||
@@ -3629,6 +3641,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
|
|||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
toggleComment(currentRange());
|
toggleComment(currentRange());
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
|
} else if (g.submode == ExchangeSubMode) {
|
||||||
|
exchangeRange(currentRange());
|
||||||
} else if (g.submode == ReplaceWithRegisterSubMode
|
} else if (g.submode == ReplaceWithRegisterSubMode
|
||||||
&& hasConfig(ConfigEmulateReplaceWithRegister)) {
|
&& hasConfig(ConfigEmulateReplaceWithRegister)) {
|
||||||
pushUndoState(false);
|
pushUndoState(false);
|
||||||
@@ -4281,6 +4295,12 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
|
|||||||
handled = handleCommandSubSubMode(input);
|
handled = handleCommandSubSubMode(input);
|
||||||
} else if (g.submode == NoSubMode) {
|
} else if (g.submode == NoSubMode) {
|
||||||
handled = handleNoSubMode(input);
|
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
|
} else if (g.submode == ChangeSubMode
|
||||||
|| g.submode == DeleteSubMode
|
|| g.submode == DeleteSubMode
|
||||||
|| g.submode == YankSubMode) {
|
|| g.submode == YankSubMode) {
|
||||||
@@ -4842,6 +4862,30 @@ bool FakeVimHandler::Private::handleReplaceWithRegisterSubMode(const Input &inpu
|
|||||||
return true;
|
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 &)
|
bool FakeVimHandler::Private::handleFilterSubMode(const Input &)
|
||||||
{
|
{
|
||||||
return false;
|
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)
|
void FakeVimHandler::Private::replaceWithRegister(const Range &range)
|
||||||
{
|
{
|
||||||
replaceText(range, registerContents(m_register));
|
replaceText(range, registerContents(m_register));
|
||||||
|
|||||||
@@ -165,7 +165,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="checkBoxVimCommentary">
|
<widget class="QCheckBox" name="checkBoxVimCommentary">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Vim-commentary</string>
|
<string>vim-commentary</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@@ -179,6 +179,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxExchange">
|
||||||
|
<property name="text">
|
||||||
|
<string>vim-exchange</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -431,6 +431,7 @@ QWidget *FakeVimOptionPage::widget()
|
|||||||
|
|
||||||
m_group.insert(theFakeVimSetting(ConfigEmulateVimCommentary), m_ui.checkBoxVimCommentary);
|
m_group.insert(theFakeVimSetting(ConfigEmulateVimCommentary), m_ui.checkBoxVimCommentary);
|
||||||
m_group.insert(theFakeVimSetting(ConfigEmulateReplaceWithRegister), m_ui.checkBoxReplaceWithRegister);
|
m_group.insert(theFakeVimSetting(ConfigEmulateReplaceWithRegister), m_ui.checkBoxReplaceWithRegister);
|
||||||
|
m_group.insert(theFakeVimSetting(ConfigEmulateExchange), m_ui.checkBoxExchange);
|
||||||
|
|
||||||
connect(m_ui.pushButtonCopyTextEditorSettings, &QAbstractButton::clicked,
|
connect(m_ui.pushButtonCopyTextEditorSettings, &QAbstractButton::clicked,
|
||||||
this, &FakeVimOptionPage::copyTextEditorSettings);
|
this, &FakeVimOptionPage::copyTextEditorSettings);
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ private slots:
|
|||||||
void test_vim_commentary_emulation();
|
void test_vim_commentary_emulation();
|
||||||
void test_vim_commentary_file_names();
|
void test_vim_commentary_file_names();
|
||||||
void test_vim_replace_with_register_emulation();
|
void test_vim_replace_with_register_emulation();
|
||||||
|
void test_vim_exchange_emulation();
|
||||||
|
|
||||||
void test_macros();
|
void test_macros();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user