FakeVim: Add emulation for argtextobj.vim plugin

Change-Id: I319d2b9fe9f0d145c2560cf03fecc50629c99006
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Tom Praschan
2021-02-07 19:24:56 +01:00
parent 480220a7e7
commit d7acee920d
8 changed files with 127 additions and 3 deletions

View File

@@ -130,6 +130,9 @@
\li ["x]grr to replace the current line.
\l{https://github.com/tommcdo/vim-exchange}{vim-exchange}
\endlist
\li \l{https://github.com/vim-scripts/argtextobj.vim}{argtextobj.vim}:
Defines the \c ia and \c aa text objects for function parameters.
\endlist
\endlist
\section2 Insert Mode

View File

@@ -4317,6 +4317,30 @@ void FakeVimPlugin::test_vim_exchange_emulation()
KEYS(".", "def" N "abc");
}
void FakeVimPlugin::test_vim_arg_text_obj_emulation()
{
TestData data;
setup(&data);
data.doCommand("set argtextobj");
data.setText("foo(int" X " i, double d, float f)");
KEYS("dia", "foo(" X ", double d, float f)");
KEYS("wdia", "foo(, " X ", float f)");
KEYS("wdia", "foo(, , " X ")");
data.setText("foo(int" X " i, double d, float f, long l)");
KEYS("daa", "foo(" X "double d, float f, long l)");
KEYS("WWdaa", "foo(double d" X ", long l)");
KEYS("Wdaa", "foo(double d)");
KEYS("daa", "foo()");
data.setText("foo(std::map<int" X ", double> map)");
KEYS("dia", "foo()");
data.setText("foo(const C c" X " = C(bar, baz))");
KEYS("dia", "foo()");
}
void FakeVimPlugin::test_macros()
{
TestData data;

View File

@@ -119,6 +119,7 @@ FakeVimSettings::FakeVimSettings()
createAction(ConfigEmulateVimCommentary, false, "commentary");
createAction(ConfigEmulateReplaceWithRegister, false, "ReplaceWithRegister");
createAction(ConfigEmulateExchange, false, "exchange");
createAction(ConfigEmulateArgTextObj, false, "argtextobj");
}
FakeVimSettings::~FakeVimSettings()

View File

@@ -113,6 +113,7 @@ enum FakeVimSettingsCode
ConfigEmulateVimCommentary,
ConfigEmulateReplaceWithRegister,
ConfigEmulateExchange,
ConfigEmulateArgTextObj,
ConfigBlinkingCursor
};

View File

@@ -2127,6 +2127,7 @@ public:
// return true only if cursor is in a block delimited with correct characters
bool selectBlockTextObject(bool inner, QChar left, QChar right);
bool selectQuotedStringTextObject(bool inner, const QString &quote);
bool selectArgumentTextObject(bool inner);
void commitInsertState();
void invalidateInsertState();
@@ -3925,6 +3926,8 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input)
handled = selectBlockTextObject(g.subsubdata.is('i'), '{', '}');
else if (input.is('"') || input.is('\'') || input.is('`'))
handled = selectQuotedStringTextObject(g.subsubdata.is('i'), input.asChar());
else if (input.is('a') && hasConfig(ConfigEmulateArgTextObj))
handled = selectArgumentTextObject(g.subsubdata.is('i'));
else
handled = false;
g.subsubmode = NoSubSubMode;
@@ -8847,6 +8850,89 @@ bool FakeVimHandler::Private::selectQuotedStringTextObject(bool inner,
return true;
}
bool FakeVimHandler::Private::selectArgumentTextObject(bool inner)
{
// We are just interested whether we're currently inside angled brackets,
// but selectBlockTextObject also moves the cursor, so set it back to
// its original position afterwards
QTextCursor prevCursor = m_cursor;
const bool insideTemplateParameter = selectBlockTextObject(true, '<', '>');
m_cursor = prevCursor;
int openAngleBracketCount = insideTemplateParameter ? 1 : 0;
QTextCursor tcStart(m_cursor);
while (true) {
if (tcStart.atStart())
return true;
const QChar currentChar = characterAt(tcStart.position());
if (openAngleBracketCount == 0
&& (currentChar == '(' || currentChar == ','))
break;
if (currentChar == '<')
openAngleBracketCount--;
else if (currentChar == '>')
openAngleBracketCount++;
tcStart.setPosition(tcStart.position() - 1);
}
QTextCursor tcEnd(m_cursor);
openAngleBracketCount = insideTemplateParameter ? 1 : 0;
int openParanthesisCount = 0;
while (true) {
if (tcEnd.atEnd()) {
return true;
}
const QChar currentChar = characterAt(tcEnd.position());
if (openAngleBracketCount == 0
&& openParanthesisCount == 0
&& (currentChar == ')' || currentChar == ','))
break;
if (currentChar == '<')
openAngleBracketCount++;
else if (currentChar == '>')
openAngleBracketCount--;
else if (currentChar == '(')
openParanthesisCount++;
else if (currentChar == ')')
openParanthesisCount--;
tcEnd.setPosition(tcEnd.position() + 1);
}
if (!inner && characterAt(tcEnd.position()) == ',' && characterAt(tcStart.position()) == '(') {
tcEnd.setPosition(tcEnd.position() + 1);
if (characterAt(tcEnd.position()) == ' ')
tcEnd.setPosition(tcEnd.position() + 1);
}
// Never include the opening paranthesis
if (characterAt(tcStart.position()) == '(') {
tcStart.setPosition(tcStart.position() + 1);
} else if (inner) {
tcStart.setPosition(tcStart.position() + 1);
if (characterAt(tcStart.position()) == ' ')
tcStart.setPosition(tcStart.position() + 1);
}
if (isVisualMode())
tcEnd.setPosition(tcEnd.position() - 1);
g.movetype = MoveExclusive;
setAnchorAndPosition(tcStart.position(), tcEnd.position());
return true;
}
Mark FakeVimHandler::Private::mark(QChar code) const
{
if (isVisualMode()) {

View File

@@ -162,6 +162,13 @@
<string>Plugin Emulation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxReplaceWithRegister">
<property name="text">
<string>ReplaceWithRegister</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBoxVimCommentary">
<property name="text">
@@ -172,10 +179,10 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxReplaceWithRegister">
<item row="2" column="0">
<widget class="QCheckBox" name="checkBoxArgTextObj">
<property name="text">
<string>ReplaceWithRegister</string>
<string>argtextobj.vim</string>
</property>
</widget>
</item>

View File

@@ -432,6 +432,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);
m_group.insert(theFakeVimSetting(ConfigEmulateArgTextObj), m_ui.checkBoxArgTextObj);
connect(m_ui.pushButtonCopyTextEditorSettings, &QAbstractButton::clicked,
this, &FakeVimOptionPage::copyTextEditorSettings);

View File

@@ -162,6 +162,7 @@ private slots:
void test_vim_commentary_file_names();
void test_vim_replace_with_register_emulation();
void test_vim_exchange_emulation();
void test_vim_arg_text_obj_emulation();
void test_macros();