159 lines
4.1 KiB
C++
159 lines
4.1 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2022, Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cruft/util/cast.hpp>
|
|
#include <cruft/util/concepts/string.hpp>
|
|
#include <cruft/util/debug/assert.hpp>
|
|
#include <cruft/util/parse/value.hpp>
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <functional>
|
|
|
|
|
|
namespace cruft::cmdopt2 {
|
|
struct argument_t {
|
|
std::string name;
|
|
std::optional<std::string> description;
|
|
bool required_ = false;
|
|
|
|
using acceptor1_t = std::function<void(char const *)>;
|
|
std::optional<acceptor1_t> acceptor1;
|
|
};
|
|
|
|
|
|
template <typename T>
|
|
concept parseable = std::is_arithmetic_v<T>;
|
|
|
|
|
|
template <typename BaseT>
|
|
struct ops_t : argument_t {
|
|
template <typename ValueT>
|
|
BaseT bind (ValueT&&) = delete;
|
|
|
|
template <typename ValueT>
|
|
BaseT
|
|
bind (ValueT &ref)
|
|
{
|
|
CHECK (!acceptor1);
|
|
if constexpr (parseable<ValueT>) {
|
|
acceptor1 = [&ref] (char const* str) { ref = parse::from_string<ValueT> (str); };
|
|
} else {
|
|
acceptor1 = [&ref] (char const* str) { ref = str; };
|
|
}
|
|
return get ();
|
|
}
|
|
|
|
template <typename ValueT>
|
|
BaseT
|
|
bind (std::optional<ValueT> &ref)
|
|
{
|
|
CHECK (!acceptor1);
|
|
|
|
if constexpr (parseable<ValueT>) {
|
|
acceptor1 = [&ref] (char const* str) { ref = parse::from_string<ValueT> (str); };
|
|
} else {
|
|
acceptor1 = [&ref] (char const* str) { ref = str; };
|
|
}
|
|
|
|
return get ();
|
|
}
|
|
|
|
template <typename ValueT>
|
|
BaseT
|
|
bind (std::vector<ValueT> &ref)
|
|
{
|
|
if (!repeat_)
|
|
throw std::logic_error ("vector argument with non-repeatable argument");
|
|
|
|
if constexpr (parseable<ValueT>) {
|
|
acceptor1 = [&ref] (char const* str) {
|
|
ref.emplace_back (parse::from_string<ValueT> (str));
|
|
};
|
|
} else {
|
|
acceptor1 = [&ref] (char const* str) {
|
|
ref.emplace_back (str);
|
|
};
|
|
}
|
|
|
|
return get ();
|
|
}
|
|
|
|
BaseT
|
|
get (void) const
|
|
{
|
|
return reinterpret_cast<BaseT const&> (*this);
|
|
}
|
|
|
|
BaseT
|
|
acceptor (acceptor1_t _acceptor) const
|
|
{
|
|
BaseT res = get ();
|
|
res.acceptor1 = _acceptor;
|
|
return res;
|
|
}
|
|
|
|
bool required (void) const
|
|
{
|
|
return required_;
|
|
}
|
|
|
|
BaseT required (bool val) const
|
|
{
|
|
BaseT res = get ();
|
|
res.required_ = val;
|
|
return res;
|
|
}
|
|
|
|
bool repeat_;
|
|
BaseT repeat (bool val) const
|
|
{
|
|
BaseT res = get ();
|
|
res.repeat_ = val;
|
|
return res;
|
|
}
|
|
};
|
|
|
|
struct positional_t : public ops_t<positional_t> {
|
|
positional_t ignore (void) const;
|
|
};
|
|
|
|
positional_t positional (char const *name);
|
|
positional_t positional (std::string_view name);
|
|
positional_t positional (std::string const &name);
|
|
positional_t positional (std::string &&name);
|
|
|
|
|
|
struct keyword_t : public ops_t<keyword_t> {
|
|
using acceptor0_t = std::function<void(void)>;
|
|
std::optional<acceptor0_t> acceptor0;
|
|
|
|
using ops_t::acceptor;
|
|
keyword_t acceptor (acceptor0_t);
|
|
|
|
keyword_t ignore (void) const;
|
|
|
|
keyword_t flag (void) const;
|
|
keyword_t flag (std::string_view long_) const;
|
|
keyword_t flag (char short_) const;
|
|
|
|
keyword_t count (int &) const;
|
|
keyword_t present (bool &) const;
|
|
|
|
std::optional<char> short_;
|
|
std::optional<std::string> long_;
|
|
};
|
|
|
|
keyword_t keyword (char const *name);
|
|
keyword_t keyword (std::string_view name);
|
|
keyword_t keyword (std::string const &name);
|
|
keyword_t keyword (std::string &&name);
|
|
}
|