Add --status and --status-interval.

--status prints a status message to stderr at regular intervals.
--status-interval sets the interval for status messages.

Closes: #10
This commit is contained in:
tastytea 2021-06-24 18:06:11 +02:00
parent 1cf6306f4b
commit 961deff41d
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
4 changed files with 54 additions and 6 deletions

View File

@ -38,6 +38,12 @@ epubgrep -PiC2 '(Apple|Orange)s?' file.epub
epubgrep -PC0 --raw --no-filename=all '"http[^"]+"' file.epub | tr -d '"'
--------------------------------------------------------------------------------
.Save the search results to an HTML file and output a status message every 20 seconds
[source,shell]
--------------------------------------------------------------------------------
epubgrep -C2 --status --status-interval=20 --html 'Apples' file.epub > result.html
--------------------------------------------------------------------------------
== OPTIONS
*-h*, *--help*::
@ -109,6 +115,12 @@ in an array named `matches`. I will try not to break the API. 😊
Output HTML instead of plain text. HTML will only be output at the end of the
program.
*--status*::
Output status message every *--status-interval* seconds to standard error.
*--status-interval* _NUMBER_::
Set status message interval to _NUMBER_ seconds.
== USAGE
[source,shellsession]

View File

@ -28,6 +28,7 @@
#include <fmt/format.h>
#include <fmt/ostream.h> // For compatibility with fmt 4.
#include <chrono>
#include <clocale>
#include <cmath>
#include <cstdint>
@ -141,6 +142,7 @@ int main(int argc, char *argv[])
vector<vector<search::match>> matches_all;
std::mutex mutex_matches_all;
vector<std::future<int>> futurepool;
std::atomic<size_t> books_searched{0};
auto search_file{
[&opts, &matches_all, &mutex_matches_all,
@ -188,7 +190,7 @@ int main(int argc, char *argv[])
}};
auto futures_cleanup{
[&futurepool, &return_code](const bool wait = false)
[&futurepool, &return_code, &books_searched](const bool wait = false)
{
using namespace std::chrono_literals;
@ -208,6 +210,7 @@ int main(int argc, char *argv[])
}
}
futurepool.erase(it);
++books_searched;
}
}};
@ -219,6 +222,26 @@ int main(int argc, char *argv[])
}()};
DEBUGLOG << "max_threads = " << max_threads;
const auto print_status{
[&opts, &books_searched, &input_files](std::future<bool> cancel)
{
if (!opts.status)
{
return;
}
while (cancel.wait_for(std::chrono::seconds(opts.status_interval))
!= std::future_status::ready)
{
std::cerr
<< format(translate("{0:d} of {1:d} books searched.").str(),
books_searched, input_files.size())
<< '\n';
}
std::cerr << translate("All books searched.") << '\n';
}};
std::promise<bool> promise_status;
std::thread thread_status{print_status, promise_status.get_future()};
for (const auto &filepath : input_files)
{
while (futurepool.size() >= max_threads)
@ -244,6 +267,8 @@ int main(int argc, char *argv[])
}
DEBUGLOG << "Waiting for remaining threads to finish";
futures_cleanup(true);
promise_status.set_value(true);
thread_status.join();
if (return_code == EXIT_FATAL)
{
return EXIT_FATAL;

View File

@ -97,6 +97,13 @@ options parse_options(int argc, char *argv[])
translate("Output JSON instead of plain text.").str().data())
("html",
translate("Output HTML instead of plain text.").str().data())
("status",
translate("Output status message every STATUS-INTERVAL seconds")
.str().data())
("status-interval", po::value<std::uint64_t>()
->value_name(translate("NUMBER"))->default_value(30),
translate("Set status message interval to NUMBER seconds.")
.str().data())
;
po::options_description options_hidden("Hidden options");
@ -238,6 +245,8 @@ options parse_again(const po::variables_map &vm)
opts.debug = vm.count("debug") > 0;
opts.json = vm.count("json") > 0;
opts.html = vm.count("html") > 0;
opts.status = vm.count("status") > 0;
opts.status_interval = vm["status-interval"].as<std::uint64_t>();
if (vm.count("regexp") > 0)
{

View File

@ -59,6 +59,8 @@ struct options
bool debug{false};
bool json{false};
bool html{false};
bool status{false};
uint64_t status_interval{0};
//! For the debug output.
friend std::ostream &operator<<(std::ostream &out, const options &opts);