15C_EZArgs::C_FlagDef &C_EZArgs::create_flag_def(std::string_view name,
char short_name, std::string_view description)
23 auto &dst = m_flags.emplace_back();
24 if (!name.empty() && name[0] ==
'-')
26 dst.m_name = name.substr(2);
35 dst.m_descOneLiner = description;
36 dst.m_shortName = short_name;
37 if (dst.m_name ==
"help")
38 m_helpShielded =
true;
39 if (dst.m_shortName ==
'h')
45std::string C_EZArgs::retro_path(
const char *
const argv[])
const
47 std::vector<const char*> polish_args;
48 for (
auto cur =
this; cur; cur = cur->m_owner)
49 polish_args.emplace_back(*(argv--));
52 for (
auto i = polish_args.rbegin(); i != polish_args.rend(); ++i)
55 ret = std::filesystem::path{*i}.filename().string();
65C_ErrorOrIndex C_EZArgs::help_full(
const char *
const argv[])
const
68 std::string help =
"USAGE: " + retro_path(argv);
69 std::string validActions;
70 switch (m_up2u.index())
76 auto &lo = std::get<UP2U_LAYOUT>(m_up2u);
77 const auto minPosArgs = lo.m_posCounts.empty()? lo.m_posArgs.size(): lo.m_posCounts.front();
78 for (
size_t i = 0; i < minPosArgs; ++i)
79 ((help +=
" <") += lo.m_posArgs[i]) +=
'>';
81 std::string optionals;
85 size_t ub = lo.m_posArgs.size();
86 for (
auto i: lo.m_posCounts)
89 for (
auto j = i; j < ub; ++j)
90 t += (t.empty()?
"[<":
"> <") + lo.m_posArgs[j];
94 if (optionals.empty())
97 optionals = t +
"> " + optionals +
']';
101 if (!optionals.empty())
102 (help +=
' ') += optionals;
106 validActions +=
"VALID ACTIONS:\n";
108 auto &subcmds = std::get<UP2U_SUBCMD>(m_up2u);
110 size_t positionalCount{};
111 for (
auto &i: subcmds)
113 actions += actions.empty()?
'(':
'|';
115 ((validActions +=
" ") += i.first) +=
'\n';
116 if (!i.second.m_desc.empty())
117 ((validActions +=
'\t') += i.second.m_desc) +=
'\n';
118 if (i.second.m_up2u.index() != UP2U_NULL)
121 (help +=
' ') += actions;
122 if (!positionalCount)
124 else if (positionalCount < subcmds.size())
131 for (
auto cur =
this; cur; cur = cur->m_owner)
132 for (
auto &def: cur->m_flags)
136 help += def.m_shortName;
138 (help +=
'-') += def.m_name;
141 help += def.m_trigger?
" [ARG]":
" ARG";
147 else if (!m_helpShielded)
160 if (help.back() !=
'\n')
164 if (!validActions.empty())
165 help += validActions;
169 std::string flags = help_flags();
170 const char *help_flag{};
171 switch ((m_hShielded?0:2) + (m_helpShielded?0:1))
174 help_flag =
" --help\n";
180 help_flag =
" -h, --help\n";
184 flags.append(help_flag).append(
"\tDisplay this help and exit\n");
187 "VALID FLAGS:\n" + flags;
190 for (
auto cur = m_owner; cur; cur = cur->m_owner)
191 flags += cur->help_flags();
194 "INHERITED FLAGS:\n" + flags;
198 if (!m_details.empty())
204 if (m_details.back() !=
'\n')
212std::string C_EZArgs::help_flags()
const
215 for (
auto &def: m_flags)
220 help += def.m_shortName;
221 if (!def.m_name.empty())
222 (help +=
", --") += def.m_name;
225 (help +=
'-') += def.m_name;
228 help += def.m_trigger?
" [ARG]":
" ARG";
231 if (!def.m_descOneLiner.empty())
232 (help +=
'\t').
append(def.m_descOneLiner) +=
'\n';
237std::string C_EZArgs::help_tip(
const std::string &error,
const char *
const argv[])
const
239 const char *helpFlag{};
242 else if (!m_helpShielded)
246 return std::format(
"{}\nType \"{} {}\" to read the help", error, retro_path(argv), helpFlag);
251const C_EZArgs::C_FlagDef* C_EZArgs::find_shortname_def(
char sname)
const
253 for (
auto cur =
this; cur; cur = cur->m_owner)
254 for (
auto& def : cur->m_flags)
256 if (def.m_shortName == sname)
263const C_EZArgs::C_FlagDef* C_EZArgs::find_longname_def(std::string_view name)
const
265 for (
auto cur =
this; cur; cur = cur->m_owner)
266 for (
auto& def : cur->m_flags)
268 if (def.m_name == name)
275bool C_EZArgs::is_valid_flag(
const char *
const *argv_rest,
int argc_rest)
const
277 const auto arg = *argv_rest;
284 const auto flag = arg + 2;
285 const auto eqsign = strchr(flag,
'=');
286 const auto flag_name = eqsign ? std::string_view(flag,
size_t(eqsign - flag)) : std::string_view(flag);
287 return nullptr != find_longname_def(flag_name);
291 for (
auto p = arg; *++p;)
292 if (
auto const def = find_shortname_def(*p))
305 if (argc_rest < 2 || is_valid_flag(argv_rest+1, argc_rest-1))
#define RUNTIME_ERROR(fmtStr,...)
Wrap FILE(DATE)#__LINE__ FUNCTION: msg into std::runtime_error.
THE common namespace of bux library.
void append(const T &src, std::string &dst)
std::string message() const
std::optional< size_t > m_optIndex