From ef145b2b003440ec234fce5d3083c068eec540ec Mon Sep 17 00:00:00 2001 From: tastytea Date: Sun, 19 May 2019 09:42:52 +0200 Subject: [PATCH] Added option to search for tags. --- src/main.cpp | 60 ++++++++++++++++++------------- src/parse_options.cpp | 7 ++++ src/parse_options.hpp | 1 + src/search.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++ src/search.hpp | 31 ++++++++++++++++ 5 files changed, 157 insertions(+), 25 deletions(-) create mode 100644 src/search.cpp create mode 100644 src/search.hpp diff --git a/src/main.cpp b/src/main.cpp index bbec243..15038a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ #include "parse_options.hpp" #include "uri.hpp" #include "export.hpp" +#include "search.hpp" using std::cout; using std::cerr; @@ -69,39 +70,48 @@ int main(const int argc, const char *argv[]) return 3; } } - switch (opts.format) + if (opts.format != export_format::undefined) { - case export_format::csv: - { - if (file.is_open()) + vector entries = + db.retrieve(opts.span[0], opts.span[1]); + if (!opts.search_tags.empty()) { - export_csv(db.retrieve(opts.span[0], opts.span[1]), file); - file.close(); + entries = search_tags(entries, opts.search_tags); } - else + + switch (opts.format) { - export_csv(db.retrieve(opts.span[0], opts.span[1])); - } - break; - } - case export_format::asciidoc: - { - if (file.is_open()) + case export_format::csv: { - export_adoc(db.retrieve(opts.span[0], opts.span[1]), file); - file.close(); + if (file.is_open()) + { + export_csv(entries, file); + file.close(); + } + else + { + export_csv(entries); + } + break; } - else + case export_format::asciidoc: { - export_adoc(db.retrieve(opts.span[0], opts.span[1])); + if (file.is_open()) + { + export_adoc(entries, file); + file.close(); + } + else + { + export_adoc(entries); + } + break; + } + default: + { + break; + } } - break; - } - default: - { - // Do nothing. - break; - } } return 0; diff --git a/src/parse_options.cpp b/src/parse_options.cpp index 3390f6e..22c4c87 100644 --- a/src/parse_options.cpp +++ b/src/parse_options.cpp @@ -37,6 +37,7 @@ const options parse_options(const int argc, const char *argv[]) string format; string file; string span; + string search_tags; options opts; try @@ -51,6 +52,10 @@ const options parse_options(const int argc, const char *argv[]) op.add> ("S", "span", "Only export entries between YYYY-MM-DD,YYYY-MM-DD.", "", &span); + op.add> + ("s", "search-tags", + "Search for tags. Format: tag1 AND tag2 OR tag3.", + "", &search_tags); auto option_help = op.add ("h", "help", "Show this help message."); auto option_version = op.add @@ -129,6 +134,8 @@ const options parse_options(const int argc, const char *argv[]) } } + opts.search_tags = search_tags; + if (op.non_option_args().size() > 0) { opts.uri = op.non_option_args().front(); diff --git a/src/parse_options.hpp b/src/parse_options.hpp index 9b831cf..2b85b2e 100644 --- a/src/parse_options.hpp +++ b/src/parse_options.hpp @@ -39,6 +39,7 @@ typedef struct options string file; array span = {{ time_point(), system_clock::now() }}; string uri; + string search_tags; uint8_t status_code = 0; options(); diff --git a/src/search.cpp b/src/search.cpp new file mode 100644 index 0000000..91bd455 --- /dev/null +++ b/src/search.cpp @@ -0,0 +1,83 @@ +/* This file is part of remwharead. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "search.hpp" + +using std::cerr; +using std::endl; +using std::regex; +using std::regex_search; +using std::smatch; +using std::find; + +const vector +search_tags(const vector &entries, string expression) +{ + vector> searchlist; + const regex re_or("(.+?) (OR|\\|\\|) "); + const regex re_and("(.+?) (AND|&&) "); + smatch match; + vector result; + + vector subexpressions; + { // Split expression at OR. + while (regex_search(expression, match, re_or)) + { + subexpressions.push_back(match[1].str()); + expression = match.suffix().str(); + } + subexpressions.push_back(expression); + } + + { + for (string sub : subexpressions) + { // Split each OR-slice at AND. + vector tags; + while (regex_search(sub, match, re_and)) + { + tags.push_back(match[1].str()); + sub = match.suffix().str(); + } + tags.push_back(sub); + searchlist.push_back(tags); + } + } + + for (const vector &tags_or : searchlist) + { + for (const Database::entry &entry : entries) + { // Add entry to result if all tags in an OR-slice match. + bool matched = true; + for (const string &tag : tags_or) + { + const auto it = find(entry.tags.begin(), entry.tags.end(), tag); + if (it == entry.tags.end()) + { + matched = false; + } + } + if (matched == true) + { + result.push_back(entry); + } + } + } + + return result; +} diff --git a/src/search.hpp b/src/search.hpp new file mode 100644 index 0000000..90d6b05 --- /dev/null +++ b/src/search.hpp @@ -0,0 +1,31 @@ +/* This file is part of remwharead. + * Copyright © 2019 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef REMWHAREAD_SEARCH_HPP +#define REMWHAREAD_SEARCH_HPP + +#include +#include +#include "sqlite.hpp" + +using std::vector; +using std::string; + +//! Seach database entries for tags. +const vector +search_tags(const vector &entries, string expression); + +#endif // REMWHAREAD_SEARCH_HPP