54    explicit C_EZArgs(
const std::string &description = {}): m_desc(description) {}
 
   60                       std::string_view description,
 
   61                       std::invocable<> 
auto &&trigger,
 
   62                       std::invocable<std::string_view> 
auto &&
parse){
 
   63        auto &def = create_flag_def(name, short_name, description);
 
   64        def.m_trigger  = std::move(trigger);
 
   65        def.m_parse    = std::move(
parse);
 
 
   69                       std::string_view description,
 
   70                       std::invocable<> 
auto &&trigger){
 
   71        create_flag_def(name, short_name, description).m_trigger = std::move(trigger);
 
 
   75                       std::string_view description,
 
   76                       std::invocable<std::string_view> 
auto &&
parse){
 
   77        create_flag_def(name, short_name, description).m_parse = std::move(
parse);
 
 
   81                       std::string_view description,
 
   82                       std::invocable<> 
auto trigger,
 
   83                       std::invocable<std::string_view> 
auto &&
parse) {
 
   84        auto &def = create_flag_def(name, 
char(), description);
 
   85        def.m_trigger  = std::move(trigger);
 
   86        def.m_parse    = std::move(
parse);
 
 
   90                       std::string_view description,
 
   91                       std::invocable<> 
auto &&trigger) {
 
   92        create_flag_def(name, 
char(), description).m_trigger = std::move(trigger);
 
 
   96                       std::string_view description,
 
   97                       std::invocable<std::string_view> 
auto &&
parse){
 
   98        create_flag_def(name, 
char(), description).m_parse = std::move(
parse);
 
 
  102                       std::string_view description,
 
  103                       std::invocable<> 
auto &&trigger,
 
  104                       std::invocable<std::string_view> 
auto &&
parse) {
 
  105        auto &def = create_flag_def({}, short_name, description);
 
  106        def.m_trigger  = std::move(trigger);
 
  107        def.m_parse    = std::move(
parse);
 
 
  111                       std::string_view description,
 
  112                       std::invocable<> 
auto &&trigger) {
 
  113        create_flag_def({}, short_name, description).m_trigger = std::move(trigger);
 
 
  117                       std::string_view description,
 
  118                       std::invocable<std::string_view> 
auto &&
parse) {
 
  119        create_flag_def({}, short_name, description).m_parse = std::move(
parse);
 
 
  123    C_EZArgs &
add_subcommand(
const std::string &name, std::invocable<> 
auto onParsed, 
const std::string &description = {});
 
  124    void details(std::string_view s) { m_details = s; }
 
  127        const std::ranges::forward_range 
auto &count_optionals, 
bool unlimited = 
false);
 
  129        { 
return position_args(arg_names, std::ranges::views::empty<size_t>, unlimited); }
 
 
  132    [[nodiscard]]
C_ErrorOrIndex parse(std::integral 
auto argc, 
const char *
const argv[]) 
const;
 
  140        std::string             m_name, m_descOneLiner;
 
  142        std::function<void()>   m_trigger;
 
  143        std::function<void(std::string_view)> m_parse;
 
  148        std::vector<std::string>    m_posArgs;
 
  149        std::vector<size_t>         m_posCounts;
 
  152    using C_ArgLayoutMap = std::list<std::pair<std::string,C_EZArgs>>;
 
  154    using C_UP2U = std::variant<std::monostate,C_ArgLayout,C_ArgLayoutMap>;
 
  163    const std::string       m_desc;
 
  164    std::string             m_details;
 
  165    std::deque<C_FlagDef>   m_flags;
 
  168    std::function<void()>   m_onParsed;
 
  169    size_t                  mutable m_totoalPositionArgs{};
 
  170    bool                    m_helpShielded{
false};
 
  171    bool                    m_hShielded{
false};
 
  174    static_assert(std::variant_size_v<C_UP2U> == 3);
 
  175    static_assert(std::is_same_v<std::monostate,    std::variant_alternative_t<UP2U_NULL,   C_UP2U>>);
 
  176    static_assert(std::is_same_v<C_ArgLayout,       std::variant_alternative_t<UP2U_LAYOUT, C_UP2U>>);
 
  177    static_assert(std::is_same_v<C_ArgLayoutMap,    std::variant_alternative_t<UP2U_SUBCMD, C_UP2U>>);
 
  180    C_FlagDef &create_flag_def(std::string_view name, 
char short_name, std::string_view description);
 
  181    const C_FlagDef *find_shortname_def(
char sname) 
const;
 
  182    const C_FlagDef* find_longname_def(std::string_view name) 
const;
 
  183    bool is_valid_flag(
const char *
const *argv_rest, 
int argc_rest) 
const;
 
  184    std::string help_flags() 
const;
 
  185    C_ErrorOrIndex help_full(
const char *
const argv[]) 
const;
 
  186    std::string help_tip(
const std::string &error, 
const char *
const argv[]) 
const;
 
  187    std::string retro_path(
const char *
const argv[]) 
const;
 
 
  201    switch (m_up2u.index())
 
  204        m_up2u.emplace<UP2U_SUBCMD>(); 
 
  209        throw std::runtime_error{
"Already set as positional arguments"};
 
  211    auto &ret = std::get<UP2U_SUBCMD>(m_up2u).emplace_back(name, description).second;
 
  213    ret.m_helpShielded  = m_helpShielded;
 
  214    ret.m_hShielded     = m_hShielded;
 
  216    ret.m_onParsed      = onParsed;
 
 
  221    const std::ranges::forward_range 
auto   &arg_names,
 
  222    const std::ranges::forward_range 
auto   &count_optionals,
 
  235    if (!std::empty(arg_names) || unlimited)
 
  238        switch (m_up2u.index())
 
  241            m_up2u.emplace<C_ArgLayout>();
 
  246            throw std::runtime_error{
"Already added subcommands"};
 
  248        auto &dst = std::get<1>(m_up2u);
 
  249        dst.m_posArgs.assign(std::begin(arg_names), std::end(arg_names));
 
  250        dst.m_unlimited = unlimited;
 
  253        dst.m_posCounts.assign(std::begin(count_optionals), std::end(count_optionals));
 
  254        sort(dst.m_posCounts.begin(), dst.m_posCounts.end());
 
  255        const auto n_args = dst.m_posArgs.size();
 
  256        while (!dst.m_posCounts.empty() && dst.m_posCounts.back() >= n_args)
 
  257            dst.m_posCounts.pop_back();
 
  259        dst.m_posCounts.emplace_back(n_args);
 
 
  272    decltype(argc) ind = 1;
 
  273    switch (m_up2u.index())
 
  278        for (; ind < argc && argv[ind][0] != 
'-'; ++ind);
 
  279        m_totoalPositionArgs = size_t(ind);
 
  280        if (ind < argc && (argv[ind][1] == 
'h' || !strcmp(argv[ind], 
"--help")))
 
  281            return help_full(argv);
 
  284            auto &lo = std::get<1>(m_up2u);
 
  285            decltype(argc) lower_bound = 0;
 
  286            for (
auto i: lo.m_posCounts)
 
  288                if (lower_bound < ind && ind <= 
static_cast<decltype(argc)
>(i))
 
  293                        const bool plural = i > 1;
 
  294                        message = 
"Positional argument";
 
  297                        for (
size_t j = 0; j < i; ++j)
 
  298                            message.append(
" <").append(lo.m_posArgs[j]) += 
'>';
 
  300                        message += plural? 
" are required":  
" is required";
 
  303                        message = std::to_string(ind-1).append(ind > 2? 
" positonal arguments are":  
" positonal argument is").append(
" not allowed");
 
  305                    return {help_tip(message,argv), ind};
 
  307                lower_bound = 
static_cast<decltype(argc)
>(i + 1);
 
  309            if (!lo.m_unlimited && ind > 
static_cast<decltype(argc)
>(lo.m_posArgs.size() + 1))
 
  311                std::string message = 
"Too many positional arguments:";
 
  312                for (
auto &i: lo.m_posArgs)
 
  313                    message.append(
" <").append(i) += 
'>';
 
  314                return {help_tip(message,argv), ind};
 
  319        if (ind >= argc || !strcmp(argv[ind],
"-h") || !strcmp(argv[ind],
"--help"))
 
  320            return help_full(argv);
 
  323            for (
auto &i: std::get<2>(m_up2u))
 
  324                if (i.first == argv[ind])
 
  326                    auto ret = i.second.parse(argc-ind, argv+ind);
 
  329                        m_totoalPositionArgs = i.second.m_totoalPositionArgs + size_t(ind);
 
  330                        return ret.m_optIndex.value() + size_t(ind);
 
  335            return {help_tip(std::string(
"Unknown subcommand: ")+argv[ind], argv), ind};
 
  338    const auto flagStartInd = ind;
 
  341    for (; ind < argc; ++ind)
 
  343        auto arg = argv[ind];
 
  346            return {help_tip(std::string(
"Unexpected argument: ")+arg, argv), ind};
 
  351            const auto flag = arg + 2;
 
  352            const auto eqsign = strchr(flag, 
'=');
 
  353            const auto flag_name = eqsign? std::string_view(flag, 
size_t(eqsign-flag)): std::string_view(flag);
 
  354            if (
auto def = find_longname_def(flag_name))
 
  361                        def->m_parse(eqsign+1);
 
  364                    return {help_tip(std::string(
"Value parser absent: ")+arg, argv), ind};
 
  366                else if (ind+1 < argc && !is_valid_flag(&argv[ind+1], 
int(argc-(ind+1))))
 
  371                        def->m_parse(argv[++ind]);
 
  374                    return {help_tip(std::string(
"Value parser absent: ")+arg, argv), ind};
 
  384                    return {help_tip(std::string(def->m_parse?
"Missing flag value: ":
"Triggerless flag: ")+arg, argv), ind};
 
  387            if (
"help" == flag_name)
 
  388                return help_full(argv);
 
  390                return {help_tip(std::string(
"Unknown flag: --")+=flag_name, argv), ind};
 
  394            while (
char sname = *++arg)
 
  396                if (
auto def = find_shortname_def(sname))
 
  398                    if (!arg[1] && ind+1 < argc && !is_valid_flag(&argv[ind+1], 
int(argc-(ind+1))))
 
  403                            def->m_parse(argv[++ind]);
 
  406                        return {help_tip(std::string(
"Value parser absent: -")+sname, argv), ind};
 
  416                        return {help_tip(std::string(def->m_parse?
"Missing flag value: -":
"Triggerless flag: -")+sname, argv), ind};
 
  420                    return help_full(argv);
 
  422                    return {help_tip(std::string(
"Unknown flag: -")+=sname, argv), ind};
 
 
C_EZArgs & add_subcommand(const std::string &name, std::invocable<> auto onParsed, const std::string &description={})
C_EZArgs & add_flag(char short_name, std::string_view description, std::invocable<> auto &&trigger)
C_EZArgs & add_flag(std::string_view name, char short_name, std::string_view description, std::invocable<> auto &&trigger)
C_EZArgs & add_flag(char short_name, std::string_view description, std::invocable<> auto &&trigger, std::invocable< std::string_view > auto &&parse)
auto parsed_position_argc() const
C_EZArgs(const C_EZArgs &)=delete
C_EZArgs & add_flag(std::string_view name, std::string_view description, std::invocable<> auto trigger, std::invocable< std::string_view > auto &&parse)
C_EZArgs & add_flag(std::string_view name, char short_name, std::string_view description, std::invocable< std::string_view > auto &&parse)
C_ErrorOrIndex parse(std::integral auto argc, const char *const argv[]) const
C_EZArgs & add_flag(char short_name, std::string_view description, std::invocable< std::string_view > auto &&parse)
C_EZArgs & add_flag(std::string_view name, std::string_view description, std::invocable< std::string_view > auto &&parse)
C_EZArgs & operator=(const C_EZArgs &)=delete
C_EZArgs & add_flag(std::string_view name, std::string_view description, std::invocable<> auto &&trigger)
C_EZArgs(const std::string &description={})
C_EZArgs & add_flag(std::string_view name, char short_name, std::string_view description, std::invocable<> auto &&trigger, std::invocable< std::string_view > auto &&parse)
C_EZArgs & position_args(const std::ranges::forward_range auto &arg_names, const std::ranges::forward_range auto &count_optionals, bool unlimited=false)
C_EZArgs & position_args(const std::ranges::forward_range auto &arg_names, bool unlimited=false)
void details(std::string_view s)
THE common namespace of bux library.
std::string message() const
C_ErrorOrIndex(const std::string &help)
C_ErrorOrIndex(std::integral auto flagStartInd)
std::optional< size_t > m_optIndex
C_ErrorOrIndex(const std::string &error, std::integral auto flagErrInd)