Skip to content

Commit

Permalink
feat: basic positionals specification
Browse files Browse the repository at this point in the history
  • Loading branch information
ggabriel96 committed Jan 28, 2025
1 parent 3b2e4a2 commit ac111c3
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 24 deletions.
11 changes: 6 additions & 5 deletions examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

int main(int argc, char const *argv[]) {
auto p = Program()
.Add<"age", int>()
.Add<"name", std::string>();
.Pos<"name", std::string>({.help = "The name of the delivery recipient"})
.Pos<"address", std::string>({.help = "The shipping address for your purchase"})
;

p.SetValue<"age">(28);
auto age = p.GetValue<"age">();
fmt::print("age: [{}]\n", age.value_or(-1));
// p.SetValue<"age">(28);
// auto age = p.GetValue<"name">();
// fmt::print("name: [{}]\n", age.value_or(std::string()));
}
57 changes: 57 additions & 0 deletions include/experimental/arg.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#ifndef OPZIONI_ARG_H
#define OPZIONI_ARG_H

#include <cstddef>
#include <string_view>

struct ArgSpec {
std::string_view abbrev{};
std::string_view help{};
bool is_required = true;
};

enum struct ArgType { POS, OPT, FLG };

struct Arg {
ArgType type = ArgType::POS;
std::string_view name{};
std::string_view abbrev{};
std::string_view help{};
bool is_required = true;
// BuiltinVariant default_value{};
// BuiltinVariant implicit_value{};
// act::fn::Signature action_fn = act::fn::assign<std::string_view>;
// std::size_t gather_amount = 1;
// DefaultValueSetter default_setter = nullptr;

constexpr bool has_abbrev() const noexcept { return !abbrev.empty(); }
// constexpr bool has_default() const noexcept { return default_value.index() != 0 || default_setter != nullptr; }
// constexpr bool has_implicit() const noexcept { return implicit_value.index() != 0; }
constexpr bool is_positional() const noexcept { return type == ArgType::POS; }

std::string format_base_usage() const noexcept;
std::string format_for_help_description() const noexcept;
std::string format_for_help_index() const noexcept;
std::string format_for_usage_summary() const noexcept;
};

constexpr bool operator<(Arg const &lhs, Arg const &rhs) noexcept {
bool const lhs_is_positional = lhs.type == ArgType::POS;
bool const rhs_is_positional = rhs.type == ArgType::POS;

if (lhs_is_positional && rhs_is_positional)
return false; // don't move positionals relative to each other

if (!lhs_is_positional && !rhs_is_positional)
return lhs.name < rhs.name; // sort non-positionals by name

return lhs_is_positional; // sort positionals before other types
}

constexpr bool operator==(Arg const &lhs, Arg const &rhs) noexcept {
auto const same_name = lhs.name == rhs.name;
auto const same_abbrev = lhs.has_abbrev() && rhs.has_abbrev() && lhs.abbrev == rhs.abbrev;
return same_name || same_abbrev;
}

#endif
68 changes: 49 additions & 19 deletions include/experimental/program.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#ifndef OPZIONI_PROGRAM_H
#define OPZIONI_PROGRAM_H

#include <algorithm>
#include <array>
#include <optional>
#include <tuple>
#include <type_traits>

#include "experimental/arg.hpp"
#include "experimental/fixed_string.hpp"
#include "experimental/get_type.hpp"

Expand All @@ -13,40 +16,67 @@ struct Program;

template<>
struct Program<> {

template <fixed_string Name, typename T>
consteval auto Add() {
return Program<StringList<Name>, TypeList<T>>{};
consteval auto Pos(ArgSpec spec) {
Program<StringList<Name>, TypeList<T>> new_program;
new_program.args[0] = Arg{
.name = Name,
.abbrev = "",
.help = spec.help,
.is_required = spec.is_required,
};
new_program.amount_pos += 1;
return new_program;
}

};

template <fixed_string... Names, typename... Types>
struct Program<StringList<Names...>, TypeList<Types...>> {
using argNames = StringList<Names...>;
using argTypes = TypeList<Types...>;

std::tuple<std::optional<Types>...> values{};
std::array<Arg, sizeof... (Names)> args;
std::size_t amount_pos = 0;

template <fixed_string Name, typename T>
consteval auto Add() {
return Program<StringList<Name, Names...>, TypeList<T, Types...>>{};
consteval Program() = default;

template <fixed_string... OtherNames, typename... OtherTypes>
consteval Program(Program<StringList<OtherNames...>, TypeList<OtherTypes...>> const &other) {
std::copy_n(other.args.begin(), sizeof... (OtherNames), args.begin());
}

template<fixed_string Name>
constexpr std::optional<typename GetType<Name, argNames, argTypes>::type> GetValue() const noexcept {
using ValueIdx = IndexOfStr<0, Name, argNames>;
static_assert(ValueIdx::value != -1, "unknown parameter name");
return std::get<ValueIdx::value>(values);
template <fixed_string Name, typename T>
consteval auto Pos(ArgSpec spec) {
Program<StringList<Name, Names...>, TypeList<T, Types...>> new_program(*this);
new_program.args[sizeof... (Names) - 1] = Arg{
.name = Name,
.abbrev = "",
.help = spec.help,
.is_required = spec.is_required,
};
new_program.amount_pos += 1;
std::sort(new_program.args.begin(), new_program.args.end());
return new_program;
}

template<fixed_string Name, typename V>
void SetValue(V value) noexcept {
using T = GetType<Name, argNames, argTypes>::type;
static_assert(!std::is_same_v< T, void >, "unknown parameter name");
static_assert(std::is_same_v< V, T >, "parameter of given name has different type than provided value");
using ValueIdx = IndexOfType<0, V, argTypes>;
// template<fixed_string Name>
// constexpr std::optional<typename GetType<Name, argNames, argTypes>::type> GetValue() const noexcept {
// using ValueIdx = IndexOfStr<0, Name, argNames>;
// static_assert(ValueIdx::value != -1, "unknown parameter name");
// return std::get<ValueIdx::value>(values);
// }

std::get<ValueIdx::value>(values).emplace(value);
}
// template<fixed_string Name, typename V>
// void SetValue(V value) noexcept {
// using T = GetType<Name, argNames, argTypes>::type;
// static_assert(!std::is_same_v< T, void >, "unknown parameter name");
// static_assert(std::is_same_v< V, T >, "parameter of given name has different type than provided value");
// using ValueIdx = IndexOfType<0, V, argTypes>;

// std::get<ValueIdx::value>(values).emplace(value);
// }
};

#endif

0 comments on commit ac111c3

Please sign in to comment.