1
1
#include < fmt/format.h>
2
- #include < facade/util/cmd_args .hpp>
2
+ #include < facade/util/cli_opts .hpp>
3
3
#include < facade/util/visitor.hpp>
4
4
#include < algorithm>
5
5
#include < cassert>
@@ -12,7 +12,7 @@ namespace facade {
12
12
namespace {
13
13
namespace fs = std::filesystem;
14
14
15
- CmdArgs ::Opt const * find_opt (CmdArgs ::Spec const & spec, std::variant<std::string_view, char > key) {
15
+ CliOpts ::Opt const * find_opt (CliOpts ::Spec const & spec, std::variant<std::string_view, char > key) {
16
16
for (auto const & opt : spec.options ) {
17
17
bool match{};
18
18
auto const visitor = Visitor{
@@ -30,22 +30,25 @@ CmdArgs::Opt const* find_opt(CmdArgs::Spec const& spec, std::variant<std::string
30
30
}
31
31
32
32
struct OptParser {
33
- using Result = CmdArgs ::Result;
33
+ using Result = CliOpts ::Result;
34
34
35
- CmdArgs ::Spec spec {};
36
- Ptr<CmdArgs ::Parser> out;
35
+ CliOpts ::Spec valid_spec {};
36
+ Ptr<CliOpts ::Parser> out;
37
37
std::string exe_name{};
38
38
39
- OptParser (CmdArgs::Spec spec, Ptr<CmdArgs::Parser> out, char const * arg0) : spec(std::move(spec)), out(out) {
40
- std::erase_if (this ->spec .options , [](CmdArgs::Opt const & o) { return !o.key .valid (); });
41
- this ->spec .options .push_back (CmdArgs::Opt{.key = {.full = " help" }, .help = " Show this help text" });
42
- this ->spec .options .push_back (CmdArgs::Opt{.key = {.full = " version" }, .help = " Show the version" });
39
+ OptParser (CliOpts::Spec spec, Ptr<CliOpts::Parser> out, char const * arg0) : out(out) {
40
+ valid_spec.version = spec.version .empty () ? " (unknown)" : spec.version ;
41
+ std::erase_if (spec.options , [](CliOpts::Opt const & o) { return !o.key .valid (); });
42
+ valid_spec.options .reserve (spec.options .size () + 2 );
43
+ std::move (spec.options .begin (), spec.options .end (), std::back_inserter (valid_spec.options ));
44
+ valid_spec.options .push_back (CliOpts::Opt{.key = {.full = " help" }, .help = " Show this help text" });
45
+ valid_spec.options .push_back (CliOpts::Opt{.key = {.full = " version" }, .help = " Display the version" });
43
46
exe_name = fs::path{arg0}.filename ().stem ().generic_string ();
44
47
}
45
48
46
49
std::size_t get_max_width () const {
47
50
auto ret = std::size_t {};
48
- for (auto const & opt : spec .options ) {
51
+ for (auto const & opt : valid_spec .options ) {
49
52
auto width = opt.key .full .size ();
50
53
if (!opt.value .empty ()) {
51
54
width += 1 ; // =
@@ -64,7 +67,7 @@ struct OptParser {
64
67
str.reserve (1024 );
65
68
fmt::format_to (std::back_inserter (str), " Usage: {} [OPTION]...\n\n " , exe_name);
66
69
auto const max_width = get_max_width ();
67
- for (auto const & opt : spec .options ) {
70
+ for (auto const & opt : valid_spec .options ) {
68
71
fmt::format_to (std::back_inserter (str), " {}{}" , (opt.key .single ? ' -' : ' ' ), (opt.key .single ? opt.key .single : ' ' ));
69
72
if (!opt.key .full .empty ()) { fmt::format_to (std::back_inserter (str), " {} --{}" , (opt.key .single ? ' ,' : ' ' ), opt.key .full ); }
70
73
auto width = opt.key .full .size ();
@@ -82,11 +85,11 @@ struct OptParser {
82
85
}
83
86
84
87
Result print_version () const {
85
- std::cout << fmt::format (" {} version {}\n " , exe_name, spec .version );
88
+ std::cout << fmt::format (" {} version {}\n " , exe_name, valid_spec .version );
86
89
return Result::eExitSuccess;
87
90
}
88
91
89
- CmdArgs ::Result opt (CmdArgs ::Key key, CmdArgs ::Value value) const {
92
+ CliOpts ::Result opt (CliOpts ::Key key, CliOpts ::Value value) const {
90
93
if (key.full == " help" ) { return print_help (); }
91
94
if (key.full == " version" ) { return print_version (); }
92
95
if (out) { out->opt (key, value); }
@@ -95,7 +98,7 @@ struct OptParser {
95
98
};
96
99
97
100
struct ParseOpt {
98
- using Result = CmdArgs ::Result;
101
+ using Result = CliOpts ::Result;
99
102
100
103
OptParser const & out;
101
104
@@ -117,7 +120,7 @@ struct ParseOpt {
117
120
return Result::eExitFailure;
118
121
}
119
122
120
- Result missing_value (CmdArgs ::Opt const & opt) const {
123
+ Result missing_value (CliOpts ::Opt const & opt) const {
121
124
auto str = opt.key .full ;
122
125
if (str.empty ()) { str = {&opt.key .single , 1 }; }
123
126
std::cerr << fmt::format (" missing required value for option: {}{}\n " , (opt.key .full .empty () ? " -" : " --" ), str);
@@ -126,15 +129,15 @@ struct ParseOpt {
126
129
127
130
Result parse_word () {
128
131
auto const it = current.find (' =' );
129
- CmdArgs ::Opt const * opt{};
130
- auto value = CmdArgs ::Value{};
132
+ CliOpts ::Opt const * opt{};
133
+ auto value = CliOpts ::Value{};
131
134
if (it != std::string_view::npos) {
132
135
auto const key = current.substr (0 , it);
133
- opt = find_opt (out.spec , key);
136
+ opt = find_opt (out.valid_spec , key);
134
137
if (!opt) { return unknown_option (key); }
135
138
value = current.substr (it + 1 );
136
139
} else {
137
- opt = find_opt (out.spec , current);
140
+ opt = find_opt (out.valid_spec , current);
138
141
if (!opt) { return unknown_option (current); }
139
142
}
140
143
if (!opt->value .empty () && !opt->is_optional_value && value.empty ()) { return missing_value (*opt); }
@@ -145,14 +148,14 @@ struct ParseOpt {
145
148
char prev{};
146
149
while (!at_end () && peek () != ' =' ) {
147
150
prev = advance ();
148
- auto const * opt = find_opt (out.spec , prev);
151
+ auto const * opt = find_opt (out.valid_spec , prev);
149
152
if (!opt) { return unknown_option ({&prev, 1 }); }
150
153
return out.opt (opt->key , {});
151
154
}
152
155
if (peek () == ' =' ) {
153
156
if (prev == ' \0 ' ) { return unknown_option (" " ); }
154
157
advance ();
155
- auto const * opt = find_opt (out.spec , prev);
158
+ auto const * opt = find_opt (out.valid_spec , prev);
156
159
if (!opt) { return unknown_option ({&prev, 1 }); }
157
160
return out.opt (opt->key , current);
158
161
}
@@ -176,7 +179,7 @@ struct ParseOpt {
176
179
177
180
} // namespace
178
181
179
- auto CmdArgs ::parse (Spec spec, Ptr<Parser> out, int argc, char const * const * argv) -> Result {
182
+ auto CliOpts ::parse (Spec spec, Ptr<Parser> out, int argc, char const * const * argv) -> Result {
180
183
if (argc < 1 ) { return Result::eContinue; }
181
184
auto opt_parser = OptParser{std::move (spec), out, argv[0 ]};
182
185
auto parse_opt = ParseOpt{opt_parser};
@@ -186,7 +189,7 @@ auto CmdArgs::parse(Spec spec, Ptr<Parser> out, int argc, char const* const* arg
186
189
return Result::eContinue;
187
190
}
188
191
189
- auto CmdArgs ::parse (std::string_view version, int argc, char const * const * argv) -> Result {
192
+ auto CliOpts ::parse (std::string_view version, int argc, char const * const * argv) -> Result {
190
193
auto spec = Spec{.version = version};
191
194
return parse (std::move (spec), {}, argc, argv);
192
195
}
0 commit comments