ulib/3party/argagg/examples/joinargs.cpp

146 lines
4.5 KiB
C++
Raw Permalink Normal View History

2024-01-22 21:16:50 +08:00
#include <argagg/argagg.hpp>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
static std::ofstream g_dev_null;
int main(
int argc,
const char** argv)
{
using argagg::parser_results;
using argagg::parser;
using std::cerr;
using std::cout;
using std::endl;
using std::ofstream;
using std::ostream;
using std::ostringstream;
using std::string;
// Use an initializer list to define the argument parser. The first brace
// starts the initializer list, the second brace starts the initializer list
// for the definitions vector in the argagg::parser struct.
parser argparser {{
// Each entry here is an initializer list for an `argagg::definition`
// struct.
{
// Name of the option. This is the key used to retrieve the flag parser
// results.
"help",
// The strings ("flags") that must be matched to activate this option.
{"-h", "--help"},
// The help string that is streamed out when the argagg::parser object
// itself is streamed out.
"displays help information",
// Number of arguments needed by this option. Should be 0 or 1.
0},
{
"verbose", {"-v", "--verbose"},
"increases verbosity", 0},
{
"lorem-ipsum", {"--lorem-ipsum"},
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
"ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
"aliquip ex ea commodo consequat. Duis aute irure dolor in "
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
"culpa qui officia deserunt mollit anim id est laborum.", 0},
{
"sep", {"-s", "--sep"},
"separator (default ',')", 1},
{
"output", {"-o", "--output"},
"output filename (stdout if not specified)", 1},
}};
// Define our usage text.
ostringstream usage;
usage
<< "Joins all positional arguments together with a separator" << endl
<< endl
<< "Usage: " << argv[0] << " [options] ARG [ARG...]" << endl
<< endl;
// Use our argument parser to... parse the command line arguments. If there
// are any problems then just spit out the usage and help text and exit.
argagg::parser_results args;
try {
args = argparser.parse(argc, argv);
} catch (const std::exception& e) {
argagg::fmt_ostream help(cerr);
help << usage.str() << argparser << endl
<< "Encountered exception while parsing arguments: " << e.what()
<< endl;
return EXIT_FAILURE;
}
// If the help flag was specified then spit out the usage and help text and
// exit.
if (args["help"]) {
argagg::fmt_ostream help(cerr);
help << usage.str() << argparser;
return EXIT_SUCCESS;
}
// Respect verbosity. Okay, the logging here is a little ludicrous. The point
// I want to show here is that you can quickly get the number of times an
// option shows up.
int verbose_level = args["verbose"].count();
// Set up our verbose log output stream selector that selects stderr if the
// requested log level is lower than or equal to the currently set verbose
// level.
g_dev_null.open("/dev/null"); // portable? eh... simple? yes!
auto vlog = [&](int level) -> ostream& {
return verbose_level >= level ? cerr : g_dev_null;
};
vlog(1) << "verbose log level: " << verbose_level << endl;
// Use comma as the separator unless one was specified.
auto sep = args["sep"].as<string>(",");
vlog(1) << "set separator to '" << sep << "'" << endl;
// Determine output stream.
ofstream output_file;
ostream* output = &std::cout;
if (args["output"]) {
string filename = args["output"];
output_file.open(filename);
output = &output_file;
vlog(1) << "outputting to file at '" << filename << "'" << endl;
} else {
vlog(1) << "outputting to stdout" << endl;
}
// Join the arguments.
if (args.count() < 1) {
vlog(0) << usage.str() << argparser << endl
<< "Not enough arguments" << endl;
return EXIT_FAILURE;
}
for (auto& arg : args.pos) {
vlog(2) << "writing argument" << endl;
vlog(4) << "argument is '" << arg << "'" << endl;
*output << arg;
if (arg != args.pos.back()) {
vlog(3) << "writing separator" << endl;
*output << sep;
}
}
vlog(4) << "writing endl" << endl;
*output << endl;
vlog(4) << "everything a-okay" << endl;
return EXIT_SUCCESS;
}