Prints a simple HTML document with tables wrapped in articles to stdout. Closes: #9
This commit is contained in:
parent
a77b90c8b1
commit
37c2fe1bb1
@ -2,7 +2,7 @@
|
||||
:doctype: manpage
|
||||
:Author: tastytea
|
||||
:Email: tastytea@tastytea.de
|
||||
:Date: 2021-06-07
|
||||
:Date: 2021-06-08
|
||||
:Revision: 0.0.0
|
||||
:man source: epubgrep
|
||||
:man manual: General Commands Manual
|
||||
@ -88,6 +88,10 @@ program. There will be an object named `generator` with the property
|
||||
`epubgrep`. The value is the version of the program, as string. The matches are
|
||||
in an array named `matches`. I will try not to break the API. 😊
|
||||
|
||||
*--html*::
|
||||
Output HTML instead of plain text. HTML will only be output at the end of the
|
||||
program.
|
||||
|
||||
== USAGE
|
||||
|
||||
[source,shellsession]
|
||||
|
@ -223,7 +223,7 @@ int main(int argc, char *argv[])
|
||||
std::async(std::launch::async, search_file, filepath));
|
||||
DEBUGLOG << "Launched new thread";
|
||||
|
||||
if (!matches_all.empty() && !opts.json)
|
||||
if (!matches_all.empty() && !opts.json && !opts.html)
|
||||
{
|
||||
output::print_matches(matches_all[0], opts,
|
||||
input_files.size() == 1);
|
||||
@ -238,6 +238,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
output::json_all(matches_all);
|
||||
}
|
||||
else if (opts.html)
|
||||
{
|
||||
output::html_all(matches_all, opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &matches : matches_all)
|
||||
|
@ -95,6 +95,8 @@ options parse_options(int argc, char *argv[])
|
||||
translate("Enable debug output.") .str().data())
|
||||
("json",
|
||||
translate("Output JSON instead of plain text.") .str().data())
|
||||
("html",
|
||||
translate("Output HTML instead of plain text.") .str().data())
|
||||
;
|
||||
|
||||
po::options_description options_hidden("Hidden options");
|
||||
@ -235,6 +237,7 @@ options parse_again(const po::variables_map &vm)
|
||||
opts.ignore_archive_errors = vm.count("ignore-archive-errors") > 0;
|
||||
opts.debug = vm.count("debug") > 0;
|
||||
opts.json = vm.count("json") > 0;
|
||||
opts.html = vm.count("html") > 0;
|
||||
|
||||
if (vm.count("regexp") > 0)
|
||||
{
|
||||
|
@ -58,6 +58,7 @@ struct options
|
||||
bool ignore_archive_errors{false};
|
||||
bool debug{false};
|
||||
bool json{false};
|
||||
bool html{false};
|
||||
|
||||
//! For the debug output.
|
||||
friend std::ostream &operator<<(std::ostream &out, const options &opts);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <termcolor/termcolor.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
@ -131,4 +132,79 @@ void json_all(const std::vector<std::vector<search::match>> &matches_all)
|
||||
cout << json.dump() << '\n';
|
||||
}
|
||||
|
||||
void html_all(const std::vector<std::vector<search::match>> &matches_all,
|
||||
const options::options &opts)
|
||||
{
|
||||
std::uint64_t count{1};
|
||||
|
||||
cout << "<!DOCTYPE html>\n"
|
||||
<< "<html><head><title>epubgrep output</title>"
|
||||
"<style>article { margin: 1em; }</style>"
|
||||
"</head><body>\n\n";
|
||||
|
||||
for (const auto &matches : matches_all)
|
||||
{
|
||||
const auto identifier{
|
||||
[&opts, count, &matches]
|
||||
{
|
||||
if (opts.no_fn_fs)
|
||||
{
|
||||
return format(translate("File {0:d}").str(), count);
|
||||
}
|
||||
return fs::relative(matches[0].filepath_epub).string();
|
||||
}()};
|
||||
|
||||
// Start article, table and print table header.
|
||||
cout << format(R"(<article aria-labelledby="file_{0:d}">)", count)
|
||||
<< "\n <table>\n"
|
||||
<< format(R"( <caption id="file_{0:d}">{1:s}</caption>)", count,
|
||||
identifier)
|
||||
<< '\n'
|
||||
<< " <tr>\n";
|
||||
if (!opts.no_fn_epub)
|
||||
{
|
||||
cout << format(R"( <th id="file_path_{0:d}">{1:s}</th>)",
|
||||
count, translate("File path (in EPUB file)"))
|
||||
<< '\n';
|
||||
}
|
||||
cout << format(R"( <th id="headline_{0:d}">{1:s}</th>)", count,
|
||||
translate("Last headline"))
|
||||
<< '\n'
|
||||
<< format(R"( <th id="page_{0:d}">{1:s}</th>)", count,
|
||||
translate("Page number"))
|
||||
<< '\n'
|
||||
<< format(R"( <th id="match_{0:d}">{1:s}</th>)", count,
|
||||
translate("Match"))
|
||||
<< "\n </tr>\n";
|
||||
|
||||
for (const auto &match : matches)
|
||||
{
|
||||
cout << " <tr>\n";
|
||||
if (!opts.no_fn_epub)
|
||||
{
|
||||
cout << format(
|
||||
R"( <td headers="file_path_{0:d}">{1:s}</td>)", count,
|
||||
match.filepath_inside)
|
||||
<< '\n';
|
||||
}
|
||||
cout << format(R"( <td headers="headline_{0:d}">{1:s}</td>)",
|
||||
count, match.headline)
|
||||
<< '\n';
|
||||
cout << format(R"( <td headers="page_{0:d}">{1:s}</td>)",
|
||||
count, match.page)
|
||||
<< '\n';
|
||||
cout << format(R"( <td headers="match_{0:d}">{1:s})"
|
||||
R"(<strong>{2:s}</strong>{3:s}</td>)",
|
||||
count, match.context.first, match.text,
|
||||
match.context.second)
|
||||
<< '\n';
|
||||
cout << " </tr>\n";
|
||||
}
|
||||
cout << " </table>\n</article>\n\n";
|
||||
++count;
|
||||
}
|
||||
|
||||
cout << "</body></html>\n";
|
||||
}
|
||||
|
||||
} // namespace epubgrep::output
|
||||
|
@ -32,6 +32,10 @@ void print_matches(const std::vector<search::match> &matches,
|
||||
//! Print all matches as JSON.
|
||||
void json_all(const std::vector<std::vector<search::match>> &matches_all);
|
||||
|
||||
//! Print all matches as HTML.
|
||||
void html_all(const std::vector<std::vector<search::match>> &matches_all,
|
||||
const options::options &opts);
|
||||
|
||||
} // namespace epubgrep::output
|
||||
|
||||
#endif // EPUBGREP_OUTPUT_HPP
|
||||
|
Loading…
x
Reference in New Issue
Block a user