mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 14:44:40 +00:00
First pass implementation of a naive argument parser. API is shaping up
This commit is contained in:
parent
2539bc33ce
commit
a06308f673
126
src/argparse.hpp
126
src/argparse.hpp
@ -1,14 +1,134 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <any>
|
||||
|
||||
namespace argparse {
|
||||
|
||||
struct Argument {
|
||||
std::vector<std::string> mNames;
|
||||
std::string mHelp;
|
||||
std::function<std::any()> mDefaultValue;
|
||||
std::function<std::any(const std::string&)> mAction;
|
||||
std::any mValue;
|
||||
std::string mRawValue;
|
||||
|
||||
Argument() :
|
||||
mNames({}),
|
||||
mHelp(""),
|
||||
mDefaultValue(nullptr),
|
||||
mAction(nullptr),
|
||||
mValue(nullptr),
|
||||
mRawValue("") {}
|
||||
|
||||
Argument& help(const std::string& aHelp) {
|
||||
mHelp = aHelp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument& default_value(std::function<std::any()> aDefaultValue) {
|
||||
mDefaultValue = aDefaultValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument& action(std::function<std::any(const std::string&)> aAction) {
|
||||
mAction = aAction;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get() {
|
||||
if (!mValue.has_value()) {
|
||||
if (mDefaultValue != nullptr) {
|
||||
return std::any_cast<T>(mDefaultValue());
|
||||
}
|
||||
else
|
||||
return T();
|
||||
}
|
||||
else {
|
||||
if (mRawValue != "")
|
||||
return std::any_cast<T>(mValue);
|
||||
else {
|
||||
if (mDefaultValue != nullptr)
|
||||
return std::any_cast<T>(mDefaultValue());
|
||||
else
|
||||
return T();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ArgumentParser {
|
||||
public:
|
||||
ArgumentParser(const std::string& program_name) :
|
||||
program_name_(program_name) {}
|
||||
ArgumentParser(const std::string& aProgramName) :
|
||||
mProgramName(aProgramName) {}
|
||||
|
||||
template<typename T, typename... Targs>
|
||||
Argument& add_argument(T value, Targs... Fargs) {
|
||||
std::shared_ptr<Argument> tArgument = std::make_shared<Argument>();
|
||||
tArgument->mNames.push_back(value);
|
||||
add_argument_internal(tArgument, Fargs...);
|
||||
mArguments.push_back(tArgument);
|
||||
return *tArgument;
|
||||
}
|
||||
|
||||
void parse_args(int argc, char * argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
for (auto& tArgument : mArguments) {
|
||||
auto tIndex = std::find(tArgument->mNames.begin(), tArgument->mNames.end(), argv[i]);
|
||||
if (tIndex != tArgument->mNames.end()) {
|
||||
i = i + 1;
|
||||
if (i < argc) {
|
||||
tArgument->mRawValue = argv[i];
|
||||
if (tArgument->mAction != nullptr)
|
||||
tArgument->mValue = tArgument->mAction(argv[i]);
|
||||
else {
|
||||
if (tArgument->mDefaultValue != nullptr)
|
||||
tArgument->mValue = tArgument->mDefaultValue();
|
||||
else
|
||||
tArgument->mValue = std::string(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Argument& operator[](const char * key) {
|
||||
for (auto& tArgument : mArguments) {
|
||||
auto tIndex = std::find(tArgument->mNames.begin(), tArgument->mNames.end(), key);
|
||||
if (tIndex != tArgument->mNames.end()) {
|
||||
return *tArgument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T = std::string>
|
||||
T get(const char * aArgumentName) {
|
||||
for (auto& tArgument : mArguments) {
|
||||
auto tIndex = std::find(tArgument->mNames.begin(), tArgument->mNames.end(), aArgumentName);
|
||||
if (tIndex != tArgument->mNames.end()) {
|
||||
return tArgument->get<T>();
|
||||
}
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string program_name_;
|
||||
Argument& add_argument_internal(std::shared_ptr<Argument> aArgument) {
|
||||
return *aArgument;
|
||||
}
|
||||
|
||||
template<typename T, typename... Targs>
|
||||
Argument& add_argument_internal(std::shared_ptr<Argument> aArgument, T aArgumentName, Targs... Fargs) {
|
||||
aArgument->mNames.push_back(aArgumentName);
|
||||
add_argument_internal(aArgument, Fargs...);
|
||||
return *aArgument;
|
||||
}
|
||||
|
||||
std::string mProgramName;
|
||||
std::vector<std::shared_ptr<Argument>> mArguments;
|
||||
};
|
||||
|
||||
}
|
@ -1,5 +1,29 @@
|
||||
#include <iostream>
|
||||
#include <argparse.hpp>
|
||||
using namespace argparse;
|
||||
|
||||
int main() {
|
||||
int main(int argc, char * argv[]) {
|
||||
ArgumentParser program("test");
|
||||
|
||||
program.add_argument("--config")
|
||||
.help("Path to input file")
|
||||
.default_value([]() { return std::string{"config.yml"}; });
|
||||
|
||||
program.add_argument("-n", "--num_iterations")
|
||||
.help("Number of iterations")
|
||||
.action([](const std::string& value) { return std::stoi(value); });
|
||||
|
||||
program.add_argument("-v", "--verbose", "VERBOSE")
|
||||
.default_value([]() { return true; });
|
||||
|
||||
program.parse_args(argc, argv);
|
||||
|
||||
auto config_file = program.get<std::string>("--config");
|
||||
auto num_iters = program.get<int>("-n");
|
||||
auto verbose = program.get<bool>("-v");
|
||||
|
||||
std::cout << config_file << std::endl;
|
||||
std::cout << num_iters << std::endl;
|
||||
std::cout << verbose << std::endl;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user