Allow abbreviation of search field names

This allows `t:word` instead of `title:word` and `p:word` instead of `password:word`, and so on.  The rule is that an abbreviated name expands to the first field name that starts with it, with exceptions
`u:` expanding to `username:` instead of `url:` and `pw:` expanding to `password:`.
This commit is contained in:
Akinori MUSHA 2019-08-12 23:33:31 +09:00 committed by Jonathan White
parent 0a3b19edf2
commit 41131ae48d
3 changed files with 43 additions and 25 deletions

View File

@ -173,6 +173,17 @@ bool EntrySearcher::searchEntryImpl(Entry* entry)
void EntrySearcher::parseSearchTerms(const QString& searchString)
{
static const QList<QPair<QString, Field>> fieldnames{
{QStringLiteral("attachment"), Field::Attachment},
{QStringLiteral("attribute"), Field::AttributeKey},
{QStringLiteral("notes"), Field::Notes},
{QStringLiteral("pw"), Field::Password},
{QStringLiteral("password"), Field::Password},
{QStringLiteral("title"), Field::Title},
{QStringLiteral("u"), Field::Username}, // u: stands for username rather than url
{QStringLiteral("url"), Field::Url},
{QStringLiteral("username"), Field::Username}};
m_searchTerms.clear();
auto results = m_termParser.globalMatch(searchString);
while (results.hasNext()) {
@ -201,32 +212,24 @@ void EntrySearcher::parseSearchTerms(const QString& searchString)
term->exclude = mods.contains("-") || mods.contains("!");
// Determine the field to search
term->field = Field::Undefined;
QString field = result.captured(2);
if (!field.isEmpty()) {
auto cs = Qt::CaseInsensitive;
if (field.compare("title", cs) == 0) {
term->field = Field::Title;
} else if (field.startsWith("user", cs)) {
term->field = Field::Username;
} else if (field.startsWith("pass", cs)) {
term->field = Field::Password;
} else if (field.compare("url", cs) == 0) {
term->field = Field::Url;
} else if (field.compare("notes", cs) == 0) {
term->field = Field::Notes;
} else if (field.startsWith("attr", cs)) {
term->field = Field::AttributeKey;
} else if (field.startsWith("attach", cs)) {
term->field = Field::Attachment;
} else if (field.startsWith("_", cs)) {
if (field.startsWith("_", Qt::CaseInsensitive)) {
term->field = Field::AttributeValue;
// searching a custom attribute
// in this case term->word is the attribute key (removing the leading "_")
// and term->regex is used to match attribute value
term->word = field.mid(1);
} else {
for (const auto& pair : fieldnames) {
if (pair.first.startsWith(field, Qt::CaseInsensitive)) {
term->field = pair.second;
break;
}
}
}
} else {
term->field = Field::Undefined;
}
m_searchTerms.append(term);

View File

@ -237,21 +237,21 @@
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string notr="true">username</string>
<string notr="true">username (u)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string notr="true">password</string>
<string notr="true">password (p, pw)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string notr="true">title</string>
<string notr="true">title (t)</string>
</property>
</widget>
</item>
@ -265,21 +265,21 @@
<item row="0" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string notr="true">notes</string>
<string notr="true">notes (n)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_12">
<property name="text">
<string notr="true">attribute</string>
<string notr="true">attribute (attr)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string notr="true">attachment</string>
<string notr="true">attachment (attach)</string>
</property>
</widget>
</item>

View File

@ -96,7 +96,7 @@ void TestEntrySearcher::testSearch()
e3->setGroup(group3);
Entry* e3b = new Entry();
e3b->setTitle("test search test");
e3b->setTitle("test search test 123");
e3b->setUsername("test@email.com");
e3b->setPassword("realpass");
e3b->setGroup(group3);
@ -108,16 +108,31 @@ void TestEntrySearcher::testSearch()
m_searchResult = m_entrySearcher.search("search term", m_rootGroup);
QCOMPARE(m_searchResult.count(), 3);
m_searchResult = m_entrySearcher.search("123", m_rootGroup);
QCOMPARE(m_searchResult.count(), 2);
m_searchResult = m_entrySearcher.search("search term", group211);
QCOMPARE(m_searchResult.count(), 1);
// Test advanced search terms
m_searchResult = m_entrySearcher.search("title:123", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
m_searchResult = m_entrySearcher.search("t:123", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
m_searchResult = m_entrySearcher.search("password:testpass", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
m_searchResult = m_entrySearcher.search("pw:testpass", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
m_searchResult = m_entrySearcher.search("!user:email.com", m_rootGroup);
QCOMPARE(m_searchResult.count(), 5);
m_searchResult = m_entrySearcher.search("!u:email.com", m_rootGroup);
QCOMPARE(m_searchResult.count(), 5);
m_searchResult = m_entrySearcher.search("*user:\".*@.*\\.com\"", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);