FakeVim: Add emulation for ReplaceWithRegister plugin

Change-Id: Iaaeef6ff51fe858b759c10adaac582f5858b6210
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Tom Praschan
2021-02-06 19:22:26 +01:00
parent e124ca962d
commit b6f26ed67a
8 changed files with 142 additions and 24 deletions

View File

@@ -120,6 +120,13 @@
\list
\li \l{https://github.com/tpope/vim-commentary}{vim-commentary}: \c gc
action to comment code regions. For example, \c gcc, \c gc2j, \c gcip
\li
\l{https://github.com/vim-scripts/ReplaceWithRegister}{ReplaceWithRegister}:
\list
\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.
\endlist
\endlist
\section2 Insert Mode

View File

@@ -4231,6 +4231,53 @@ void FakeVimPlugin::test_vim_commentary_file_names()
KEYS("gcc", X "// abc");
}
void FakeVimPlugin::test_vim_replace_with_register_emulation()
{
TestData data;
setup(&data);
data.doCommand("set replacewithregister");
// Simple replace
data.setText("abc def ghi");
KEYS("yw", "abc def ghi");
KEYS("w", "abc " X "def ghi");
KEYS("grw", "abc " X "abc ghi");
KEYS("w", "abc abc " X "ghi");
KEYS(".", "abc abc " X "abc ");
// Registers
data.setText("abc def ghi jkl mno");
KEYS("\"xyiw", "abc def ghi jkl mno");
KEYS("w", "abc " X "def ghi jkl mno");
KEYS("yiw", "abc " X "def ghi jkl mno");
KEYS("w", "abc def " X "ghi jkl mno");
KEYS("griw", "abc def " X "def jkl mno");
KEYS("w", "abc def def " X "jkl mno");
KEYS("\"xgriw", "abc def def " X "abc mno");
KEYS("w", "abc def def abc " X "mno");
KEYS(".", "abc def def abc " X "abc");
// Replace entire line
data.setText("abc" N "def" N "ghi" N "jkhl");
KEYS("yyj", "abc" N X "def" N "ghi" N "jkhl");
KEYS("grr", "abc" N X "abc" N "ghi" N "jkhl");
KEYS("j", "abc" N "abc" N X "ghi" N "jkhl");
KEYS(".", "abc" N "abc" N X "abc" N "jkhl");
// Visual line mode
data.setText("abc" N "def" N "ghi" N "jkhl");
KEYS("yyj", "abc" N X "def" N "ghi" N "jkhl");
KEYS("Vgr", "abc" N X "abc" N "ghi" N "jkhl");
KEYS("j", "abc" N "abc" N X "ghi" N "jkhl");
KEYS(".", "abc" N "abc" N X "abc" N "jkhl");
// Visual char mode
data.setText("abc defghi");
KEYS("yiw", "abc defghi");
KEYS("w", "abc defghi");
KEYS("v4lgr", "abc abci");
}
void FakeVimPlugin::test_macros()
{
TestData data;

View File

@@ -116,6 +116,7 @@ FakeVimSettings::FakeVimSettings()
// Emulated plugins
createAction(ConfigEmulateVimCommentary, false, "commentary");
createAction(ConfigEmulateReplaceWithRegister, false, "ReplaceWithRegister");
}
FakeVimSettings::~FakeVimSettings()

View File

@@ -110,6 +110,7 @@ enum FakeVimSettingsCode
// Plugin emulation
ConfigEmulateVimCommentary,
ConfigEmulateReplaceWithRegister,
ConfigBlinkingCursor
};

View File

@@ -166,26 +166,27 @@ enum BlockInsertMode
enum SubMode
{
NoSubMode,
ChangeSubMode, // Used for c
DeleteSubMode, // Used for d
FilterSubMode, // Used for !
IndentSubMode, // Used for =
RegisterSubMode, // Used for "
ShiftLeftSubMode, // Used for <
ShiftRightSubMode, // Used for >
CommentSubMode, // Used for gc
InvertCaseSubMode, // Used for g~
DownCaseSubMode, // Used for gu
UpCaseSubMode, // Used for gU
WindowSubMode, // Used for Ctrl-w
YankSubMode, // Used for y
ZSubMode, // Used for z
CapitalZSubMode, // Used for Z
ReplaceSubMode, // Used for r
MacroRecordSubMode, // Used for q
MacroExecuteSubMode, // Used for @
CtrlVSubMode, // Used for Ctrl-v in insert mode
CtrlRSubMode // Used for Ctrl-r in insert mode
ChangeSubMode, // Used for c
DeleteSubMode, // Used for d
FilterSubMode, // Used for !
IndentSubMode, // Used for =
RegisterSubMode, // Used for "
ShiftLeftSubMode, // Used for <
ShiftRightSubMode, // Used for >
CommentSubMode, // Used for gc
ReplaceWithRegisterSubMode, // Used for gr
InvertCaseSubMode, // Used for g~
DownCaseSubMode, // Used for gu
UpCaseSubMode, // Used for gU
WindowSubMode, // Used for Ctrl-w
YankSubMode, // Used for y
ZSubMode, // Used for z
CapitalZSubMode, // Used for Z
ReplaceSubMode, // Used for r
MacroRecordSubMode, // Used for q
MacroExecuteSubMode, // Used for @
CtrlVSubMode, // Used for Ctrl-v in insert mode
CtrlRSubMode // Used for Ctrl-r in insert mode
};
/*! A \e SubSubMode is used for things that require one more data item
@@ -1345,6 +1346,8 @@ QString dotCommandFromSubMode(SubMode submode)
return QLatin1String("d");
if (submode == CommentSubMode)
return QLatin1String("gc");
if (submode == ReplaceWithRegisterSubMode)
return QLatin1String("gr");
if (submode == InvertCaseSubMode)
return QLatin1String("g~");
if (submode == DownCaseSubMode)
@@ -1826,6 +1829,7 @@ public:
void handleChangeDeleteYankSubModes();
bool handleReplaceSubMode(const Input &);
bool handleCommentSubMode(const Input &);
bool handleReplaceWithRegisterSubMode(const Input &);
bool handleFilterSubMode(const Input &);
bool handleRegisterSubMode(const Input &);
bool handleShiftSubMode(const Input &);
@@ -2089,6 +2093,7 @@ public:
return g.submode == ChangeSubMode
|| g.submode == DeleteSubMode
|| g.submode == CommentSubMode
|| g.submode == ReplaceWithRegisterSubMode
|| g.submode == FilterSubMode
|| g.submode == IndentSubMode
|| g.submode == ShiftLeftSubMode
@@ -2166,6 +2171,8 @@ public:
void toggleComment(const Range &range);
void replaceWithRegister(const Range &range);
void upCase(const Range &range);
void downCase(const Range &range);
@@ -3590,6 +3597,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
if (g.submode == ChangeSubMode
|| g.submode == DeleteSubMode
|| g.submode == CommentSubMode
|| g.submode == ReplaceWithRegisterSubMode
|| g.submode == YankSubMode
|| g.submode == InvertCaseSubMode
|| g.submode == DownCaseSubMode
@@ -3621,6 +3629,12 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
beginEditBlock();
toggleComment(currentRange());
endEditBlock();
} else if (g.submode == ReplaceWithRegisterSubMode
&& hasConfig(ConfigEmulateReplaceWithRegister)) {
pushUndoState(false);
beginEditBlock();
replaceWithRegister(currentRange());
endEditBlock();
} else if (g.submode == DeleteSubMode) {
pushUndoState(false);
beginEditBlock();
@@ -3679,9 +3693,13 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
}
if (!dotCommandMovement.isEmpty()) {
const QString dotCommand = dotCommandFromSubMode(g.submode);
if (!dotCommand.isEmpty())
QString dotCommand = dotCommandFromSubMode(g.submode);
if (!dotCommand.isEmpty()) {
if (g.submode == ReplaceWithRegisterSubMode)
dotCommand = QString("\"%1%2").arg(QChar(m_register)).arg(dotCommand);
setDotCommand(dotCommand + dotCommandMovement);
}
}
// Change command continues in insert mode.
@@ -4269,6 +4287,9 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
handled = handleChangeDeleteYankSubModes(input);
} else if (g.submode == CommentSubMode && hasConfig(ConfigEmulateVimCommentary)) {
handled = handleCommentSubMode(input);
} else if (g.submode == ReplaceWithRegisterSubMode
&& hasConfig(ConfigEmulateReplaceWithRegister)) {
handled = handleReplaceWithRegisterSubMode(input);
} else if (g.submode == ReplaceSubMode) {
handled = handleReplaceSubMode(input);
} else if (g.submode == FilterSubMode) {
@@ -4435,6 +4456,14 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
pushUndoState();
setAnchor();
}
} else if (g.gflag && input.is('r') && hasConfig(ConfigEmulateReplaceWithRegister)) {
g.submode = ReplaceWithRegisterSubMode;
if (isVisualMode()) {
dotCommand = visualDotCommand() + QString::number(count()) + "gr";
pasteText(true);
} else {
setAnchor();
}
} else if ((input.is('c') || input.is('d') || input.is('y')) && isNoVisualMode()) {
setAnchor();
g.opcount = g.mvcount;
@@ -4794,6 +4823,25 @@ bool FakeVimHandler::Private::handleCommentSubMode(const Input &input)
return true;
}
bool FakeVimHandler::Private::handleReplaceWithRegisterSubMode(const Input &input)
{
if (!input.is('r'))
return false;
pushUndoState(false);
beginEditBlock();
const QString movement = (count() == 1)
? QString() : (QString::number(count() - 1) + "j");
g.dotCommand = "V" + movement + "gr";
replay(g.dotCommand);
endEditBlock();
return true;
}
bool FakeVimHandler::Private::handleFilterSubMode(const Input &)
{
return false;
@@ -7436,6 +7484,11 @@ void FakeVimHandler::Private::toggleComment(const Range &range)
});
}
void FakeVimHandler::Private::replaceWithRegister(const Range &range)
{
replaceText(range, registerContents(m_register));
}
void FakeVimHandler::Private::replaceText(const Range &range, const QString &str)
{
transformText(range, [&str](const QString &) { return str; } );
@@ -7452,7 +7505,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
bool pasteAfter = isVisualMode() ? false : afterCursor;
if (isVisualMode())
cutSelectedText('"');
cutSelectedText(g.submode == ReplaceWithRegisterSubMode ? '-' : '"');
switch (rangeMode) {
case RangeCharMode: {

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>580</width>
<height>531</height>
<height>543</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -172,6 +172,13 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxReplaceWithRegister">
<property name="text">
<string>ReplaceWithRegister</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -430,6 +430,7 @@ QWidget *FakeVimOptionPage::widget()
m_group.insert(theFakeVimSetting(ConfigBlinkingCursor), m_ui.checkBoxBlinkingCursor);
m_group.insert(theFakeVimSetting(ConfigEmulateVimCommentary), m_ui.checkBoxVimCommentary);
m_group.insert(theFakeVimSetting(ConfigEmulateReplaceWithRegister), m_ui.checkBoxReplaceWithRegister);
connect(m_ui.pushButtonCopyTextEditorSettings, &QAbstractButton::clicked,
this, &FakeVimOptionPage::copyTextEditorSettings);

View File

@@ -160,6 +160,7 @@ private slots:
// Plugin emulation
void test_vim_commentary_emulation();
void test_vim_commentary_file_names();
void test_vim_replace_with_register_emulation();
void test_macros();