Added option to search in tags, titles, descriptions and full texts.

This commit is contained in:
tastytea 2019-05-19 10:55:45 +02:00
parent 843871d97d
commit 896d0e7734
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
5 changed files with 76 additions and 10 deletions

View File

@ -78,6 +78,10 @@ int main(const int argc, const char *argv[])
{
entries = search_tags(entries, opts.search_tags);
}
else if (!opts.search_all.empty())
{
entries = search_all(entries, opts.search_all);
}
switch (opts.format)
{

View File

@ -38,6 +38,7 @@ const options parse_options(const int argc, const char *argv[])
string file;
string span;
string search_tags;
string search_all;
options opts;
try
@ -56,6 +57,9 @@ const options parse_options(const int argc, const char *argv[])
("s", "search-tags",
"Search for tags. Format: tag1 AND tag2 OR tag3.",
"", &search_tags);
op.add<popl::Value<string>>
("", "search-all",
"", "Search tags, title, description and full text.", &search_all);
auto option_help = op.add<popl::Switch>
("h", "help", "Show this help message.");
auto option_version = op.add<popl::Switch>
@ -136,6 +140,8 @@ const options parse_options(const int argc, const char *argv[])
opts.search_tags = search_tags;
opts.search_all = search_all;
if (op.non_option_args().size() > 0)
{
opts.uri = op.non_option_args().front();

View File

@ -40,6 +40,7 @@ typedef struct options
array<time_point, 2> span = {{ time_point(), system_clock::now() }};
string uri;
string search_tags;
string search_all;
uint8_t status_code = 0;
options();

View File

@ -14,26 +14,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <regex>
#include <algorithm>
#include "search.hpp"
using std::cerr;
using std::endl;
using std::regex;
using std::regex_search;
using std::smatch;
using std::find;
const vector<Database::entry>
search_tags(const vector<Database::entry> &entries, string expression)
const vector<vector<string>> parse_expression(string expression)
{
vector<vector<string>> searchlist;
const regex re_or("(.+?) (OR|\\|\\|) ");
const regex re_and("(.+?) (AND|&&) ");
smatch match;
vector<Database::entry> result;
vector<string> subexpressions;
{ // Split expression at OR.
@ -48,17 +43,26 @@ search_tags(const vector<Database::entry> &entries, string expression)
{
for (string sub : subexpressions)
{ // Split each OR-slice at AND.
vector<string> tags;
vector<string> terms;
while (regex_search(sub, match, re_and))
{
tags.push_back(match[1].str());
terms.push_back(match[1].str());
sub = match.suffix().str();
}
tags.push_back(sub);
searchlist.push_back(tags);
terms.push_back(sub);
searchlist.push_back(terms);
}
}
return searchlist;
}
const vector<Database::entry>
search_tags(const vector<Database::entry> &entries, string expression)
{
vector<vector<string>> searchlist = parse_expression(expression);
vector<Database::entry> result;
for (const vector<string> &tags_or : searchlist)
{
for (const Database::entry &entry : entries)
@ -81,3 +85,48 @@ search_tags(const vector<Database::entry> &entries, string expression)
return result;
}
const vector<Database::entry>
search_all(const vector<Database::entry> &entries, string expression)
{
vector<vector<string>> searchlist = parse_expression(expression);
vector<Database::entry> result = search_tags(entries, expression);
for (const vector<string> &terms_or : searchlist)
{
for (const Database::entry &entry : entries)
{
// Add entry to result if all terms in an OR-slice match title,
// description or full text.
bool matched_title = true;
bool matched_description = true;
bool matched_fulltext = true;
for (const string &term : terms_or)
{
if (entry.title.find(term) == std::string::npos)
{
matched_title = false;
}
if (entry.description.find(term) == std::string::npos)
{
matched_description = false;
}
if (entry.fulltext.find(term) == std::string::npos)
{
matched_fulltext = false;
}
}
if (matched_title == true
|| matched_description == true
|| matched_fulltext == true)
{
result.push_back(entry);
}
}
}
return result;
}

View File

@ -24,8 +24,14 @@
using std::vector;
using std::string;
const vector<vector<string>> parse_expression(string expression);
//! Seach database entries for tags.
const vector<Database::entry>
search_tags(const vector<Database::entry> &entries, string expression);
//! Search tags, title, description and full text.
const vector<Database::entry>
search_all(const vector<Database::entry> &entries, string expression);
#endif // REMWHAREAD_SEARCH_HPP