-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* First draft version of supporting actions, default arguments and etc: - removed ParseResult (parsing directly into ArgMap) - list of supported types in BuiltinTypes - Arg has std::variant default value member - Arg stores its action - implemented very basic assign and append actions - removed Program::assign_* member functions - temporarily not assigning default values when setting parsed arguments - just updated unit tests to pass, gotta re-do them * only override action_fn is it was not set by user * Arg is not required by default * setting required for positionals * using actions instead of namespace * Some code organization: - moved Program to its own .hpp/.cpp files - types.hpp/.cpp renamed to args.hpp/.cpp, added "section comments" - opzioni::parsing::parse_option moved to program.hpp, not in parsing namespace anymore - include cleanup - removed unused opzioni.cpp and types.test.cpp * Removed unused TypedConverter * pseudo-random version bump * Basic append templated on container too * testing error messages in parsing.test.cpp * Usando optional<variant> pro valor padrão * Atribuindo valores padrão * Fix unintentional copy * Testing positional argument for command * clang-format * Fix include guards of args.hpp * fix typo in comment
- Loading branch information
1 parent
ac64a95
commit c456d5a
Showing
14 changed files
with
380 additions
and
409 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#ifndef OPZIONI_ARGS_H | ||
#define OPZIONI_ARGS_H | ||
|
||
#include "converters.hpp" | ||
#include "memory.hpp" | ||
|
||
#include <map> | ||
#include <optional> | ||
#include <string> | ||
#include <utility> | ||
#include <variant> | ||
#include <vector> | ||
|
||
#include <fmt/format.h> | ||
|
||
namespace opzioni { | ||
|
||
// +----------------------+ | ||
// | forward declarations | | ||
// +----------------------+ | ||
|
||
struct Arg; | ||
struct ArgMap; | ||
|
||
namespace actions { | ||
|
||
using signature = void (*)(ArgMap &, Arg const &, std::optional<std::string> const &); | ||
|
||
template <typename T> void assign(ArgMap &, Arg const &, std::optional<std::string> const &); | ||
|
||
} // namespace actions | ||
|
||
// +----------------------------------------+ | ||
// | related to type list and builtin types | | ||
// +----------------------------------------+ | ||
|
||
template <typename...> struct TypeList; | ||
|
||
template <typename...> struct VariantOf; | ||
template <typename... Ts> struct VariantOf<TypeList<Ts...>> { using type = std::variant<Ts...>; }; | ||
|
||
using BuiltinTypes = TypeList<bool, int, double, std::string, std::vector<int>>; | ||
using BuiltinType = VariantOf<BuiltinTypes>::type; | ||
|
||
// +-----------+ | ||
// | arguments | | ||
// +-----------+ | ||
|
||
struct ArgValue { | ||
BuiltinType value{}; | ||
|
||
template <typename T> T as() const { return std::get<T>(value); } | ||
}; | ||
|
||
struct ArgMap { | ||
ArgValue operator[](std::string name) const { | ||
if (!args.contains(name)) | ||
throw UnknownArgument(fmt::format("Could not find argument `{}`", name)); | ||
return args.at(name); | ||
} | ||
|
||
template <typename T> T get_if_else(T &&desired, std::string name, T &&otherwise) const { | ||
// mainly intended for flags which are not only true or false | ||
if (args.contains(name)) | ||
return desired; | ||
else | ||
return otherwise; | ||
} | ||
|
||
template <typename T> T as(std::string name) const { | ||
auto const arg = (*this)[name]; | ||
return arg.as<T>(); | ||
} | ||
|
||
auto size() const noexcept { return this->args.size(); } | ||
|
||
std::string cmd_name; | ||
memory::ValuePtr<ArgMap> subcmd; | ||
std::map<std::string, ArgValue> args; | ||
}; | ||
|
||
struct Arg { | ||
std::string name{}; | ||
std::string description{}; | ||
bool is_required = false; | ||
std::optional<BuiltinType> default_value{}; | ||
actions::signature action_fn = actions::assign<std::string>; | ||
|
||
Arg &help(std::string) noexcept; | ||
Arg &required() noexcept; | ||
Arg &action(actions::signature) noexcept; | ||
|
||
template <typename T> Arg &otherwise(T value) { | ||
default_value = std::move(value); | ||
is_required = false; | ||
if (action_fn == actions::assign<std::string>) | ||
action_fn = actions::assign<T>; | ||
return *this; | ||
} | ||
}; | ||
|
||
// +---------------------------+ | ||
// | implementation of actions | | ||
// +---------------------------+ | ||
|
||
namespace actions { | ||
|
||
template <typename T> void assign(ArgMap &map, Arg const &arg, std::optional<std::string> const &parsed_value) { | ||
T value = parsed_value.has_value() ? convert<T>(*parsed_value) : std::get<T>(*arg.default_value); | ||
map.args[arg.name] = ArgValue{value}; | ||
} | ||
|
||
template <typename Elem, typename Container = std::vector<Elem>> | ||
void append(ArgMap &map, Arg const &arg, std::optional<std::string> const &parsed_value) { | ||
Elem value = convert<Elem>(*parsed_value); | ||
if (auto list = map.args.find(arg.name); list != map.args.end()) { | ||
std::get<Container>(list->second.value).push_back(std::move(value)); | ||
} else { | ||
map.args.emplace(std::make_pair(arg.name, Container{std::move(value)})); | ||
} | ||
} | ||
|
||
} // namespace actions | ||
|
||
} // namespace opzioni | ||
|
||
#endif // OPZIONI_ARGS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,7 @@ | ||
#ifndef OPZIONI_H | ||
#define OPZIONI_H | ||
|
||
#include "types.hpp" | ||
|
||
namespace opzioni {} // namespace opzioni | ||
#include "args.hpp" | ||
#include "program.hpp" | ||
|
||
#endif // OPZIONI_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#ifndef OPZIONI_PROGRAM_H | ||
#define OPZIONI_PROGRAM_H | ||
|
||
#include "args.hpp" | ||
#include "memory.hpp" | ||
|
||
#include <map> | ||
#include <optional> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace opzioni { | ||
|
||
struct ParsedOption { | ||
std::string name; | ||
std::optional<std::string> value; | ||
}; | ||
|
||
ParsedOption parse_option(std::string const &) noexcept; | ||
|
||
struct Program { | ||
std::string name{}; | ||
std::string description{}; | ||
std::string epilog{}; | ||
|
||
std::map<std::string, memory::ValuePtr<Program>> cmds; | ||
std::vector<Arg> positional_args; | ||
std::map<std::string, Arg> flags; | ||
std::map<std::string, Arg> options; | ||
|
||
Program() = default; | ||
Program(std::string name) : name(name) {} | ||
Program(std::string name, std::string description, std::string epilog) | ||
: name(name), description(description), epilog(epilog) {} | ||
|
||
Program &help(std::string) noexcept; | ||
Program &with_epilog(std::string) noexcept; | ||
|
||
ArgMap operator()(int, char const *[]) const; | ||
|
||
Arg &pos(std::string); | ||
Arg &opt(std::string); | ||
Arg &flag(std::string); | ||
Program &cmd(std::string); | ||
|
||
bool is_flag(std::string const &) const noexcept; | ||
void set_default_values(ArgMap &) const noexcept; | ||
|
||
std::optional<std::string> is_positional(std::string const &) const noexcept; | ||
std::optional<std::string> is_long_flag(std::string const &) const noexcept; | ||
std::optional<std::string> is_short_flags(std::string const &) const noexcept; | ||
std::optional<ParsedOption> is_option(std::string const &) const noexcept; | ||
std::optional<decltype(cmds)::const_iterator> is_subcmd(std::string const &) const noexcept; | ||
}; | ||
|
||
} // namespace opzioni | ||
|
||
#endif // OPZIONI_PROGRAM_H |
Oops, something went wrong.