2022-05-03 12:21:01 +00:00
|
|
|
#include <qpdf/assert_test.h>
|
|
|
|
|
2021-12-30 20:50:31 +00:00
|
|
|
#include <qpdf/QPDFArgParser.hh>
|
2022-01-28 12:46:04 +00:00
|
|
|
#include <qpdf/QPDFUsage.hh>
|
2021-12-30 20:50:31 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <iostream>
|
2022-03-07 13:46:53 +00:00
|
|
|
|
2021-12-30 20:50:31 +00:00
|
|
|
class ArgParser
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ArgParser(int argc, char* argv[]);
|
|
|
|
void parseArgs();
|
|
|
|
|
|
|
|
void test_exceptions();
|
|
|
|
|
|
|
|
private:
|
|
|
|
void handlePotato();
|
2022-02-01 18:37:31 +00:00
|
|
|
void handleSalad(std::string const& p);
|
|
|
|
void handleMoo(std::string const& p);
|
|
|
|
void handleOink(std::string const& p);
|
|
|
|
void handleQuack(std::string const& p);
|
2021-12-30 20:50:31 +00:00
|
|
|
void startQuack();
|
2022-02-01 18:37:31 +00:00
|
|
|
void getQuack(std::string const& p);
|
2021-12-30 20:50:31 +00:00
|
|
|
void endQuack();
|
|
|
|
void finalChecks();
|
|
|
|
|
|
|
|
void initOptions();
|
|
|
|
void output(std::string const&);
|
|
|
|
|
|
|
|
QPDFArgParser ap;
|
|
|
|
int quacks;
|
|
|
|
};
|
|
|
|
|
|
|
|
ArgParser::ArgParser(int argc, char* argv[]) :
|
|
|
|
ap(QPDFArgParser(argc, argv, "TEST_ARG_PARSER")),
|
|
|
|
quacks(0)
|
|
|
|
{
|
|
|
|
initOptions();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::initOptions()
|
|
|
|
{
|
|
|
|
auto b = [this](void (ArgParser::*f)()) { return QPDFArgParser::bindBare(f, this); };
|
2022-02-01 18:37:31 +00:00
|
|
|
auto p = [this](void (ArgParser::*f)(std::string const&)) {
|
2021-12-30 20:50:31 +00:00
|
|
|
return QPDFArgParser::bindParam(f, this);
|
|
|
|
};
|
|
|
|
|
|
|
|
ap.addBare("potato", b(&ArgParser::handlePotato));
|
|
|
|
ap.addRequiredParameter("salad", p(&ArgParser::handleSalad), "tossed");
|
|
|
|
ap.addOptionalParameter("moo", p(&ArgParser::handleMoo));
|
2023-05-20 11:46:50 +00:00
|
|
|
char const* choices[] = {"pig", "boar", "sow", nullptr};
|
2022-01-07 20:29:27 +00:00
|
|
|
ap.addChoices("oink", p(&ArgParser::handleOink), true, choices);
|
2021-12-30 20:50:31 +00:00
|
|
|
ap.selectHelpOptionTable();
|
|
|
|
ap.addBare("version", [this]() { output("3.14159"); });
|
|
|
|
ap.selectMainOptionTable();
|
|
|
|
ap.addBare("quack", b(&ArgParser::startQuack));
|
|
|
|
ap.registerOptionTable("quack", b(&ArgParser::endQuack));
|
|
|
|
ap.addPositional(p(&ArgParser::getQuack));
|
|
|
|
ap.addFinalCheck(b(&ArgParser::finalChecks));
|
|
|
|
ap.selectMainOptionTable();
|
|
|
|
ap.addBare("baaa", [this]() { this->ap.selectOptionTable("baaa"); });
|
|
|
|
ap.registerOptionTable("baaa", nullptr);
|
|
|
|
ap.addBare("ewe", [this]() { output("you"); });
|
|
|
|
ap.addBare("ram", [this]() { output("ram"); });
|
2022-01-06 19:26:32 +00:00
|
|
|
ap.selectMainOptionTable();
|
|
|
|
ap.addBare("sheep", [this]() { this->ap.selectOptionTable("sheep"); });
|
|
|
|
ap.registerOptionTable("sheep", nullptr);
|
2022-01-07 22:01:10 +00:00
|
|
|
|
|
|
|
ap.addHelpFooter("For more help, read the manual.\n");
|
|
|
|
ap.addHelpTopic(
|
|
|
|
"quack", "Quack Options", "Just put stuff after quack to get a count at the end.\n");
|
|
|
|
ap.addHelpTopic(
|
|
|
|
"baaa",
|
|
|
|
"Baaa Options",
|
|
|
|
"Ewe can do sheepish things.\n"
|
|
|
|
"For example, ewe can add more ram to your computer.\n");
|
|
|
|
ap.addOptionHelp("--ewe", "baaa", "just for ewe", "You are not a ewe.\n");
|
|
|
|
ap.addOptionHelp("--ram", "baaa", "curly horns", "");
|
2021-12-30 20:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::output(std::string const& msg)
|
|
|
|
{
|
|
|
|
if (!this->ap.isCompleting()) {
|
|
|
|
std::cout << msg << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::handlePotato()
|
|
|
|
{
|
|
|
|
output("got potato");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-02-01 18:37:31 +00:00
|
|
|
ArgParser::handleSalad(std::string const& p)
|
2021-12-30 20:50:31 +00:00
|
|
|
{
|
|
|
|
output(std::string("got salad=") + p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-02-01 18:37:31 +00:00
|
|
|
ArgParser::handleMoo(std::string const& p)
|
2021-12-30 20:50:31 +00:00
|
|
|
{
|
2022-02-01 18:37:31 +00:00
|
|
|
output(std::string("got moo=") + (p.empty() ? "(none)" : p));
|
2021-12-30 20:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-02-01 18:37:31 +00:00
|
|
|
ArgParser::handleOink(std::string const& p)
|
2021-12-30 20:50:31 +00:00
|
|
|
{
|
|
|
|
output(std::string("got oink=") + p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::parseArgs()
|
|
|
|
{
|
|
|
|
this->ap.parseArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::startQuack()
|
|
|
|
{
|
|
|
|
this->ap.selectOptionTable("quack");
|
|
|
|
if (this->ap.isCompleting()) {
|
|
|
|
if (this->ap.isCompleting() && (this->ap.argsLeft() == 0)) {
|
|
|
|
this->ap.insertCompletion("something");
|
|
|
|
this->ap.insertCompletion("anything");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-02-01 18:37:31 +00:00
|
|
|
ArgParser::getQuack(std::string const& p)
|
2021-12-30 20:50:31 +00:00
|
|
|
{
|
|
|
|
++this->quacks;
|
|
|
|
if (this->ap.isCompleting() && (this->ap.argsLeft() == 0)) {
|
2022-09-21 16:49:21 +00:00
|
|
|
this->ap.insertCompletion(std::string("thing-") + std::to_string(this->quacks));
|
2021-12-30 20:50:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
output(std::string("got quack: ") + p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::endQuack()
|
|
|
|
{
|
2022-09-21 16:49:21 +00:00
|
|
|
output("total quacks so far: " + std::to_string(this->quacks));
|
2021-12-30 20:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::finalChecks()
|
|
|
|
{
|
2022-09-21 16:49:21 +00:00
|
|
|
output("total quacks: " + std::to_string(this->quacks));
|
2021-12-30 20:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ArgParser::test_exceptions()
|
|
|
|
{
|
2022-01-07 22:01:10 +00:00
|
|
|
auto err = [](char const* msg, std::function<void()> fn) {
|
|
|
|
try {
|
|
|
|
fn();
|
|
|
|
assert(msg == nullptr);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cout << msg << ": " << e.what() << std::endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
err("duplicate handler", [this]() {
|
2021-12-30 20:50:31 +00:00
|
|
|
ap.selectMainOptionTable();
|
|
|
|
ap.addBare("potato", []() {});
|
2022-01-07 22:01:10 +00:00
|
|
|
});
|
|
|
|
err("duplicate handler", [this]() {
|
2021-12-30 20:50:31 +00:00
|
|
|
ap.selectOptionTable("baaa");
|
2022-01-07 22:01:10 +00:00
|
|
|
ap.addBare("ram", []() {});
|
|
|
|
});
|
2021-12-30 20:50:31 +00:00
|
|
|
err("duplicate table", [this]() { ap.registerOptionTable("baaa", nullptr); });
|
|
|
|
err("unknown table", [this]() { ap.selectOptionTable("aardvark"); });
|
2022-01-07 22:01:10 +00:00
|
|
|
err("add existing help topic", [this]() { ap.addHelpTopic("baaa", "potato", "salad"); });
|
|
|
|
err("add reserved help topic", [this]() { ap.addHelpTopic("all", "potato", "salad"); });
|
|
|
|
err("add to unknown topic", [this]() { ap.addOptionHelp("--new", "oops", "potato", "salad"); });
|
|
|
|
err("bad option for help", [this]() { ap.addOptionHelp("nodash", "baaa", "potato", "salad"); });
|
|
|
|
err("bad topic for help", [this]() { ap.addHelpTopic("--dashes", "potato", "salad"); });
|
|
|
|
err("duplicate option help",
|
|
|
|
[this]() { ap.addOptionHelp("--ewe", "baaa", "potato", "salad"); });
|
|
|
|
err("invalid choice handler to unknown",
|
2022-02-01 18:37:31 +00:00
|
|
|
[this]() { ap.addInvalidChoiceHandler("elephant", [](std::string const&) {}); });
|
2021-12-30 20:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
ArgParser ap(argc, argv);
|
|
|
|
if ((argc == 2) && (strcmp(argv[1], "exceptions") == 0)) {
|
|
|
|
ap.test_exceptions();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
ap.parseArgs();
|
2022-01-28 12:46:04 +00:00
|
|
|
} catch (QPDFUsage& e) {
|
2021-12-30 20:50:31 +00:00
|
|
|
std::cerr << "usage: " << e.what() << std::endl;
|
|
|
|
exit(2);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cerr << "exception: " << e.what() << std::endl;
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|