forked from qt-creator/qt-creator
fakevim: Added support for smartcase searching
Change-Id: I85a83aff0886282a6eac2dc9cc4662087c3b0b95 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -211,6 +211,13 @@ FakeVimSettings *theFakeVimSettings()
|
|||||||
instance->insertItem(ConfigUseCoreSearch, item,
|
instance->insertItem(ConfigUseCoreSearch, item,
|
||||||
_("usecoresearch"), _("ucs"));
|
_("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 = new SavedAction(instance);
|
||||||
item->setDefaultValue(_("indent,eol,start"));
|
item->setDefaultValue(_("indent,eol,start"));
|
||||||
item->setSettingsKey(group, _("Backspace"));
|
item->setSettingsKey(group, _("Backspace"));
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ enum FakeVimSettingsCode
|
|||||||
ConfigSmartIndent,
|
ConfigSmartIndent,
|
||||||
ConfigIncSearch,
|
ConfigIncSearch,
|
||||||
ConfigUseCoreSearch,
|
ConfigUseCoreSearch,
|
||||||
|
ConfigSmartCase,
|
||||||
|
|
||||||
// indent allow backspacing over autoindent
|
// indent allow backspacing over autoindent
|
||||||
// eol allow backspacing over line breaks (join lines)
|
// eol allow backspacing over line breaks (join lines)
|
||||||
|
|||||||
@@ -290,6 +290,122 @@ struct SearchData
|
|||||||
bool highlightCursor;
|
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()
|
Range::Range()
|
||||||
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
|
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
|
||||||
@@ -3377,7 +3493,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
|
|||||||
|
|
||||||
needle.replace('$', '\n');
|
needle.replace('$', '\n');
|
||||||
needle.replace("\\\n", "\\$");
|
needle.replace("\\\n", "\\$");
|
||||||
pattern.setPattern(needle);
|
pattern = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase));
|
||||||
|
|
||||||
m_lastSubstituteFlags = flags;
|
m_lastSubstituteFlags = flags;
|
||||||
m_lastSubstitutePattern = pattern;
|
m_lastSubstitutePattern = pattern;
|
||||||
@@ -3916,123 +4032,6 @@ bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd)
|
|||||||
return handled;
|
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)
|
void FakeVimHandler::Private::searchBalanced(bool forward, QChar needle, QChar other)
|
||||||
{
|
{
|
||||||
int level = 1;
|
int level = 1;
|
||||||
@@ -4074,7 +4073,7 @@ void FakeVimHandler::Private::search(const SearchData &sd)
|
|||||||
if (!sd.forward)
|
if (!sd.forward)
|
||||||
flags |= QTextDocument::FindBackward;
|
flags |= QTextDocument::FindBackward;
|
||||||
|
|
||||||
QRegExp needleExp = vimPatternToQtPattern(sd.needle);
|
QRegExp needleExp = vimPatternToQtPattern(sd.needle, hasConfig(ConfigSmartCase));
|
||||||
|
|
||||||
const int oldLine = cursorLine() - cursorLineOnScreen();
|
const int oldLine = cursorLine() - cursorLineOnScreen();
|
||||||
|
|
||||||
@@ -4135,7 +4134,7 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle)
|
|||||||
QTextCursor tc = cursor();
|
QTextCursor tc = cursor();
|
||||||
tc.movePosition(StartOfDocument, MoveAnchor);
|
tc.movePosition(StartOfDocument, MoveAnchor);
|
||||||
|
|
||||||
QRegExp needleExp = vimPatternToQtPattern(needle);
|
QRegExp needleExp = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase));
|
||||||
if (!needleExp.isValid()) {
|
if (!needleExp.isValid()) {
|
||||||
QString error = needleExp.errorString();
|
QString error = needleExp.errorString();
|
||||||
showRedMessage(
|
showRedMessage(
|
||||||
|
|||||||
@@ -59,6 +59,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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">
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="checkBoxExpandTab">
|
<widget class="QCheckBox" name="checkBoxExpandTab">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -66,7 +73,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QCheckBox" name="checkBoxShowMarks">
|
<widget class="QCheckBox" name="checkBoxShowMarks">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show position of text marks</string>
|
<string>Show position of text marks</string>
|
||||||
@@ -80,7 +87,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QCheckBox" name="checkBoxPassControlKey">
|
<widget class="QCheckBox" name="checkBoxPassControlKey">
|
||||||
<property name="toolTip">
|
<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>
|
<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_ui.checkBoxIncSearch);
|
||||||
m_group.insert(theFakeVimSetting(ConfigUseCoreSearch),
|
m_group.insert(theFakeVimSetting(ConfigUseCoreSearch),
|
||||||
m_ui.checkBoxUseCoreSearch);
|
m_ui.checkBoxUseCoreSearch);
|
||||||
|
m_group.insert(theFakeVimSetting(ConfigSmartCase),
|
||||||
|
m_ui.checkBoxSmartCase);
|
||||||
|
|
||||||
connect(m_ui.pushButtonCopyTextEditorSettings, SIGNAL(clicked()),
|
connect(m_ui.pushButtonCopyTextEditorSettings, SIGNAL(clicked()),
|
||||||
SLOT(copyTextEditorSettings()));
|
SLOT(copyTextEditorSettings()));
|
||||||
@@ -266,6 +268,7 @@ QWidget *FakeVimOptionPage::createPage(QWidget *parent)
|
|||||||
<< sep << m_ui.checkBoxIncSearch->text()
|
<< sep << m_ui.checkBoxIncSearch->text()
|
||||||
<< sep << m_ui.checkBoxStartOfLine->text()
|
<< sep << m_ui.checkBoxStartOfLine->text()
|
||||||
<< sep << m_ui.checkBoxUseCoreSearch->text()
|
<< sep << m_ui.checkBoxUseCoreSearch->text()
|
||||||
|
<< sep << m_ui.checkBoxSmartCase->text()
|
||||||
<< sep << m_ui.checkBoxShowMarks->text()
|
<< sep << m_ui.checkBoxShowMarks->text()
|
||||||
<< sep << m_ui.checkBoxPassControlKey->text()
|
<< sep << m_ui.checkBoxPassControlKey->text()
|
||||||
<< sep << m_ui.labelShiftWidth->text()
|
<< sep << m_ui.labelShiftWidth->text()
|
||||||
|
|||||||
Reference in New Issue
Block a user