feat(convention) add windows style argument conventions.
This commit is contained in:
@@ -24,4 +24,5 @@ namespace argument_parser {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <base_convention.hpp>
|
#include <base_convention.hpp>
|
||||||
#include <gnu_argument_convention.hpp>
|
#include <gnu_argument_convention.hpp>
|
||||||
|
#include <windows_argument_convention.hpp>
|
||||||
@@ -9,6 +9,8 @@ namespace argument_parser::conventions {
|
|||||||
enum class argument_type {
|
enum class argument_type {
|
||||||
SHORT,
|
SHORT,
|
||||||
LONG,
|
LONG,
|
||||||
|
POSITIONAL,
|
||||||
|
INTERCHANGABLE,
|
||||||
ERROR
|
ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "base_convention.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#ifndef WINDOWS_ARGUMENT_CONVENTION_HPP
|
||||||
|
#define WINDOWS_ARGUMENT_CONVENTION_HPP
|
||||||
|
|
||||||
|
namespace argument_parser::conventions::implementations {
|
||||||
|
class windows_argument_convention : public base_convention {
|
||||||
|
public:
|
||||||
|
// Windows style options are prefixed with a slash ('/'). And there's no difference for short vs long options.
|
||||||
|
parsed_argument get_argument(std::string const& raw) const override {
|
||||||
|
if (raw.starts_with(long_prec()))
|
||||||
|
return { argument_type::INTERCHANGABLE, raw.substr(1) };
|
||||||
|
else
|
||||||
|
return { argument_type::ERROR, "Windows standard requires non-positional arguments with a preceeding slash ('\\')." };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string extract_value(std::string const& /*raw*/) const override {
|
||||||
|
// In non-equal GNU, value comes in next token
|
||||||
|
throw std::runtime_error("No inline value in standard GNU convention.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requires_next_token() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() const override {
|
||||||
|
return "Windows style options";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string short_prec() const override {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string long_prec() const override {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
static windows_argument_convention instance;
|
||||||
|
private:
|
||||||
|
windows_argument_convention() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class windows_equal_argument_convention : public base_convention {
|
||||||
|
public:
|
||||||
|
// Windows style options are prefixed with a slash ('/'). And there's no difference for short vs long options.
|
||||||
|
parsed_argument get_argument(std::string const& raw) const override {
|
||||||
|
auto pos = raw.find('=');
|
||||||
|
auto arg = pos != std::string::npos ? raw.substr(0, pos) : raw;
|
||||||
|
if (arg.starts_with(long_prec()))
|
||||||
|
return { argument_type::INTERCHANGABLE, arg.substr(1) };
|
||||||
|
else
|
||||||
|
return { argument_type::ERROR, "Windows standard requires non-positional arguments with a preceeding slash ('\\')." };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string extract_value(std::string const& raw) const override {
|
||||||
|
auto pos = raw.find('=');
|
||||||
|
if (pos == std::string::npos || pos + 1 >= raw.size())
|
||||||
|
throw std::runtime_error("Expected value after '='.");
|
||||||
|
return raw.substr(pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requires_next_token() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() const override {
|
||||||
|
return "Windows style options (equal signed form)";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string short_prec() const override {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string long_prec() const override {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
static windows_equal_argument_convention instance;
|
||||||
|
private:
|
||||||
|
windows_equal_argument_convention() = default;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace argument_parser::conventions {
|
||||||
|
static inline const implementations::windows_argument_convention windows_argument_convention = implementations::windows_argument_convention::instance;
|
||||||
|
static inline const implementations::windows_equal_argument_convention windows_equal_argument_convention = implementations::windows_equal_argument_convention::instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WINDOWS_ARGUMENT_CONVENTION_HPP
|
||||||
@@ -194,12 +194,18 @@ namespace argument_parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
argument& get_argument(conventions::parsed_argument const& arg) {
|
argument& get_argument(conventions::parsed_argument const& arg) {
|
||||||
|
|
||||||
if (arg.first == conventions::argument_type::LONG) {
|
if (arg.first == conventions::argument_type::LONG) {
|
||||||
auto long_pos = long_arguments.find(arg.second);
|
auto long_pos = long_arguments.find(arg.second);
|
||||||
if (long_pos != long_arguments.end()) return argument_map.at(long_pos->second);
|
if (long_pos != long_arguments.end()) return argument_map.at(long_pos->second);
|
||||||
} else if (arg.first == conventions::argument_type::SHORT) {
|
} else if (arg.first == conventions::argument_type::SHORT) {
|
||||||
auto short_pos = short_arguments.find(arg.second);
|
auto short_pos = short_arguments.find(arg.second);
|
||||||
if (short_pos != short_arguments.end()) return argument_map.at(short_pos->second);
|
if (short_pos != short_arguments.end()) return argument_map.at(short_pos->second);
|
||||||
|
} else if (arg.first == conventions::argument_type::INTERCHANGABLE) {
|
||||||
|
auto long_pos = long_arguments.find(arg.second);
|
||||||
|
if (long_pos != long_arguments.end()) return argument_map.at(long_pos->second);
|
||||||
|
auto short_pos = short_arguments.find(arg.second);
|
||||||
|
if (short_pos != short_arguments.end()) return argument_map.at(short_pos->second);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown argument: " + arg.second);
|
throw std::runtime_error("Unknown argument: " + arg.second);
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@@ -1,4 +1,3 @@
|
|||||||
#include "argument_parser.hpp"
|
|
||||||
#include <argparse>
|
#include <argparse>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -6,7 +5,6 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace argument_parser::conventions;
|
|
||||||
|
|
||||||
struct Point {
|
struct Point {
|
||||||
int x, y;
|
int x, y;
|
||||||
@@ -69,8 +67,10 @@ struct argument_parser::parsing_traits::parser_trait<std::vector<std::string>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const std::initializer_list<argument_parser::conventions::convention const* const> conventions = {
|
const std::initializer_list<argument_parser::conventions::convention const* const> conventions = {
|
||||||
&gnu_argument_convention,
|
&argument_parser::conventions::gnu_argument_convention,
|
||||||
&gnu_equal_argument_convention
|
&argument_parser::conventions::gnu_equal_argument_convention,
|
||||||
|
&argument_parser::conventions::windows_argument_convention,
|
||||||
|
&argument_parser::conventions::windows_equal_argument_convention
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto echo = argument_parser::helpers::make_parametered_action<std::string>([](std::string const& text) {
|
const auto echo = argument_parser::helpers::make_parametered_action<std::string>([](std::string const& text) {
|
||||||
@@ -150,7 +150,14 @@ int main() {
|
|||||||
parser.add_argument<std::vector<int>>("t", "test", "Test vector<int>", false);
|
parser.add_argument<std::vector<int>>("t", "test", "Test vector<int>", false);
|
||||||
parser.add_argument<std::vector<std::string>>("ts", "test-strings", "Test vector<string>", false);
|
parser.add_argument<std::vector<std::string>>("ts", "test-strings", "Test vector<string>", false);
|
||||||
parser.on_complete(::run_grep);
|
parser.on_complete(::run_grep);
|
||||||
parser.handle_arguments(conventions);
|
try {
|
||||||
|
parser.handle_arguments(conventions);
|
||||||
|
} catch(std::exception const& e) {
|
||||||
|
std::cerr << "Error: " << e.what() << std::endl;
|
||||||
|
parser.display_help(conventions);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto test = parser.get_optional<std::vector<int>>("test");
|
auto test = parser.get_optional<std::vector<int>>("test");
|
||||||
if (test) {
|
if (test) {
|
||||||
|
|||||||
Reference in New Issue
Block a user