Commit 7e7460ad authored by Lukas Holecek's avatar Lukas Holecek Committed by hjk
Browse files

fakevim: Added support for smartcase searching



Change-Id: I85a83aff0886282a6eac2dc9cc4662087c3b0b95
Reviewed-by: default avatarhjk <qthjk@ovi.com>
parent 6544ed2f
......@@ -211,6 +211,13 @@ FakeVimSettings *theFakeVimSettings()
instance->insertItem(ConfigUseCoreSearch, item,
_("usecoresearch"), _("ucs"));
item = new SavedAction(instance);
item->setDefaultValue(false);
item->setValue(false);
item->setSettingsKey(group, _("SmartCase")); item->setCheckable(true);
item->setCheckable(true);
instance->insertItem(ConfigSmartCase, item, _("smartcase"), _("scs"));
item = new SavedAction(instance);
item->setDefaultValue(_("indent,eol,start"));
item->setSettingsKey(group, _("Backspace"));
......
......@@ -55,6 +55,7 @@ enum FakeVimSettingsCode
ConfigSmartIndent,
ConfigIncSearch,
ConfigUseCoreSearch,
ConfigSmartCase,
// indent allow backspacing over autoindent
// eol allow backspacing over line breaks (join lines)
......
......@@ -290,6 +290,122 @@ struct SearchData
bool highlightCursor;
};
static QRegExp vimPatternToQtPattern(QString needle, bool smartcase)
{
/* Trasformations (Vim regexp -> QRegExp):
* \a -> [A-Za-z]
* \A -> [^A-Za-z]
* \h -> [A-Za-z_]
* \H -> [^A-Za-z_]
* \l -> [a-z]
* \L -> [^a-z]
* \o -> [0-7]
* \O -> [^0-7]
* \u -> [A-Z]
* \U -> [^A-Z]
* \x -> [0-9A-Fa-f]
* \X -> [^0-9A-Fa-f]
*
* \< -> \b
* \> -> \b
* [] -> \[\]
* \= -> ?
*
* (...) <-> \(...\)
* {...} <-> \{...\}
* | <-> \|
* ? <-> \?
* + <-> \+
* \{...} -> {...}
*
* \c - set ignorecase for rest
* \C - set noignorecase for rest
*/
bool ignorecase = smartcase && !needle.contains(QRegExp("[A-Z]"));
QString pattern;
pattern.reserve(2 * needle.size());
bool escape = false;
bool brace = false;
bool curly = false;
foreach (const QChar &c, needle) {
if (brace) {
brace = false;
if (c == ']') {
pattern.append(_("\\[\\]"));
continue;
} else {
pattern.append('[');
}
}
if (QString("(){}+|?").indexOf(c) != -1) {
if (c == '{') {
curly = escape;
} else if (c == '}' && curly) {
curly = false;
escape = true;
}
if (escape)
escape = false;
else
pattern.append('\\');
pattern.append(c);
} else if (escape) {
// escape expression
escape = false;
if (c == '<' || c == '>')
pattern.append(_("\\b"));
else if (c == 'a')
pattern.append(_("[a-zA-Z]"));
else if (c == 'A')
pattern.append(_("[^a-zA-Z]"));
else if (c == 'h')
pattern.append(_("[A-Za-z_]"));
else if (c == 'H')
pattern.append(_("[^A-Za-z_]"));
else if (c == 'c' || c == 'C')
ignorecase = (c == 'c');
else if (c == 'l')
pattern.append(_("[a-z]"));
else if (c == 'L')
pattern.append(_("[^a-z]"));
else if (c == 'o')
pattern.append(_("[0-7]"));
else if (c == 'O')
pattern.append(_("[^0-7]"));
else if (c == 'u')
pattern.append(_("[A-Z]"));
else if (c == 'U')
pattern.append(_("[^A-Z]"));
else if (c == 'x')
pattern.append(_("[0-9A-Fa-f]"));
else if (c == 'X')
pattern.append(_("[^0-9A-Fa-f]"));
else if (c == '=')
pattern.append(_("?"));
else
pattern.append('\\' + c);
} else {
// unescaped expression
if (c == '\\')
escape = true;
else if (c == '[')
brace = true;
else if (c.isLetter() && ignorecase)
pattern.append('[' + c.toLower() + c.toUpper() + ']');
else
pattern.append(c);
}
}
if (escape)
pattern.append('\\');
else if (brace)
pattern.append('[');
return QRegExp(pattern);
}
Range::Range()
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
......@@ -3377,7 +3493,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
needle.replace('$', '\n');
needle.replace("\\\n", "\\$");
pattern.setPattern(needle);
pattern = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase));
m_lastSubstituteFlags = flags;
m_lastSubstitutePattern = pattern;
......@@ -3916,123 +4032,6 @@ bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd)
return handled;
}
static QRegExp vimPatternToQtPattern(QString needle)
{
/* Trasformations (Vim regexp -> QRegExp):
* \a -> [A-Za-z]
* \A -> [^A-Za-z]
* \h -> [A-Za-z_]
* \H -> [^A-Za-z_]
* \l -> [a-z]
* \L -> [^a-z]
* \o -> [0-7]
* \O -> [^0-7]
* \u -> [A-Z]
* \U -> [^A-Z]
* \x -> [0-9A-Fa-f]
* \X -> [^0-9A-Fa-f]
*
* \< -> \b
* \> -> \b
* [] -> \[\]
* \= -> ?
*
* (...) <-> \(...\)
* {...} <-> \{...\}
* | <-> \|
* ? <-> \?
* + <-> \+
* \{...} -> {...}
*
* \c - set ignorecase for rest
* \C - set noignorecase for rest
*/
// TODO: Set initial value and handle smartcase option.
bool ignorecase = false;
QString pattern;
pattern.reserve(2 * needle.size());
bool escape = false;
bool brace = false;
bool curly = false;
foreach (const QChar &c, needle) {
if (brace) {
brace = false;
if (c == ']') {
pattern.append(_("\\[\\]"));
continue;
} else {
pattern.append('[');
}
}
if (QString("(){}+|?").indexOf(c) != -1) {
if (c == '{') {
curly = escape;
} else if (c == '}' && curly) {
curly = false;
escape = true;
}
if (escape)
escape = false;
else
pattern.append('\\');
pattern.append(c);
} else if (escape) {
// escape expression
escape = false;
if (c == '<' || c == '>')
pattern.append(_("\\b"));
else if (c == 'a')
pattern.append(_("[a-zA-Z]"));
else if (c == 'A')
pattern.append(_("[^a-zA-Z]"));
else if (c == 'h')
pattern.append(_("[A-Za-z_]"));
else if (c == 'H')
pattern.append(_("[^A-Za-z_]"));
else if (c == 'c' || c == 'C')
ignorecase = (c == 'c');
else if (c == 'l')
pattern.append(_("[a-z]"));
else if (c == 'L')
pattern.append(_("[^a-z]"));
else if (c == 'o')
pattern.append(_("[0-7]"));
else if (c == 'O')
pattern.append(_("[^0-7]"));
else if (c == 'u')
pattern.append(_("[A-Z]"));
else if (c == 'U')
pattern.append(_("[^A-Z]"));
else if (c == 'x')
pattern.append(_("[0-9A-Fa-f]"));
else if (c == 'X')
pattern.append(_("[^0-9A-Fa-f]"));
else if (c == '=')
pattern.append(_("?"));
else
pattern.append('\\' + c);
} else {
// unescaped expression
if (c == '\\')
escape = true;
else if (c == '[')
brace = true;
else if (c.isLetter() && ignorecase)
pattern.append('[' + c.toLower() + c.toUpper() + ']');
else
pattern.append(c);
}
}
if (escape)
pattern.append('\\');
else if (brace)
pattern.append('[');
return QRegExp(pattern);
}
void FakeVimHandler::Private::searchBalanced(bool forward, QChar needle, QChar other)
{
int level = 1;
......@@ -4074,7 +4073,7 @@ void FakeVimHandler::Private::search(const SearchData &sd)
if (!sd.forward)
flags |= QTextDocument::FindBackward;
QRegExp needleExp = vimPatternToQtPattern(sd.needle);
QRegExp needleExp = vimPatternToQtPattern(sd.needle, hasConfig(ConfigSmartCase));
const int oldLine = cursorLine() - cursorLineOnScreen();
......@@ -4135,7 +4134,7 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle)
QTextCursor tc = cursor();
tc.movePosition(StartOfDocument, MoveAnchor);
QRegExp needleExp = vimPatternToQtPattern(needle);
QRegExp needleExp = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase));
if (!needleExp.isValid()) {
QString error = needleExp.errorString();
showRedMessage(
......
......@@ -59,6 +59,13 @@
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="checkBoxSmartCase">
<property name="text">
<string>Use smartcase</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxExpandTab">
<property name="text">
......@@ -66,7 +73,7 @@
</property>
</widget>
</item>
<item row="2" column="2">
<item row="3" column="2">
<widget class="QCheckBox" name="checkBoxShowMarks">
<property name="text">
<string>Show position of text marks</string>
......@@ -80,7 +87,7 @@
</property>
</widget>
</item>
<item row="3" column="2">
<item row="4" column="2">
<widget class="QCheckBox" name="checkBoxPassControlKey">
<property name="toolTip">
<string>Pass key sequences like Ctrl-S to Qt Creator core instead of interpreting them in FakeVim. This gives easier access to Qt Creator core functionality at the price of losing some features of FakeVim.</string>
......
......@@ -245,6 +245,8 @@ QWidget *FakeVimOptionPage::createPage(QWidget *parent)
m_ui.checkBoxIncSearch);
m_group.insert(theFakeVimSetting(ConfigUseCoreSearch),
m_ui.checkBoxUseCoreSearch);
m_group.insert(theFakeVimSetting(ConfigSmartCase),
m_ui.checkBoxSmartCase);
connect(m_ui.pushButtonCopyTextEditorSettings, SIGNAL(clicked()),
SLOT(copyTextEditorSettings()));
......@@ -266,6 +268,7 @@ QWidget *FakeVimOptionPage::createPage(QWidget *parent)
<< sep << m_ui.checkBoxIncSearch->text()
<< sep << m_ui.checkBoxStartOfLine->text()
<< sep << m_ui.checkBoxUseCoreSearch->text()
<< sep << m_ui.checkBoxSmartCase->text()
<< sep << m_ui.checkBoxShowMarks->text()
<< sep << m_ui.checkBoxPassControlKey->text()
<< sep << m_ui.labelShiftWidth->text()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment