Skip to content

Commit 96f0275

Browse files
committed
fix commands
1 parent 9cadc0b commit 96f0275

File tree

7 files changed

+179
-154
lines changed

7 files changed

+179
-154
lines changed

example/simple.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
struct Test : rsl::config {
66
bool from_config;
77

8-
[[=option]]
8+
[[=rsl::cli::option]]
99
static void zoinks(){
1010
std::exit(1);
1111
}
1212
};
1313

14-
struct Arguments : rsl::cli {
14+
struct Arguments : rsl::cli, rsl::config {
1515
[[=positional]] std::string text;
1616
Test foo;
1717
[[=positional]] char times = 5;
@@ -24,14 +24,25 @@ struct Arguments : rsl::cli {
2424

2525
[[=option]]
2626
static void cmd(){
27-
std::exit(1);
27+
// std::exit(1);
2828
}
2929
};
3030

3131
int main(int argc, char** argv) {
3232
static constexpr rsl::_cli_impl::Spec spec{^^Arguments};
3333
std::println("bases: {}, arguments: {}, commands: {}, options: {}",
3434
spec.bases.size(), spec.arguments.size(), spec.commands.size(), spec.options.size());
35+
for (auto const& arg : spec.arguments) {
36+
std::println("arg: {}", arg.name);
37+
}
38+
39+
for (auto const& opt : spec.options) {
40+
std::println("opt: {}", opt.name);
41+
}
42+
43+
for (auto const& cmd : spec.commands) {
44+
std::println("cmd: {}", cmd.name);
45+
}
3546

3647
auto args = rsl::load_config<Arguments>(argc, argv);
3748
std::println("text: {}, times: {}", args.text, args.times);

example/stateful.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct Arguments : rsl::cli {
1919

2020
int main(int argc, char** argv) {
2121
auto args = Arguments(123);
22-
rsl::parse_args(args, {argv, argv+argc});
22+
args.parse_args(argc, argv);
23+
2324
std::println("{}", args.durations);
2425
}

include/rsl/cli/option.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ struct Option {
123123
option.parameters.push_back(*parameter);
124124
} else {
125125
if (!arg.is_optional) {
126-
parser.fail("Missing parameter {} of option {}", arg.name, name);
126+
parser.set_error("Missing parameter {} of option {}", arg.name, name);
127127
break;
128128
}
129129
}

include/rsl/cli/parser.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ namespace rsl::_cli_impl {
1111
struct ArgParser {
1212
std::span<std::string_view> args;
1313
std::size_t cursor = 0;
14+
std::string error;
1415

1516
std::string_view current() const { return args[cursor]; }
1617

1718
template <typename... Args>
18-
[[noreturn]] void fail(std::format_string<Args...> fmt, Args&&... args) const {
19-
std::println(fmt, std::forward<Args>(args)...);
20-
std::exit(1);
19+
void set_error(std::format_string<Args...> fmt, Args&&... args) {
20+
error = std::format(fmt, std::forward<Args>(args)...);
2121
}
22-
23-
[[nodiscard]] bool valid() const noexcept { return cursor < args.size(); }
22+
[[nodiscard]] bool has_error() const { return !error.empty(); }
23+
[[nodiscard]] bool valid() const { return cursor < args.size() && !has_error(); }
2424
};
2525

2626
template <typename T>

include/rsl/cli/spec.hpp

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ struct Spec {
101101
}
102102
for (auto command : subparser.commands) {
103103
command.name = std::define_static_string(std::string(name) + ':' + command.name);
104-
options.push_back(command);
104+
commands.push_back(command);
105105
}
106106
}
107107
return false;
@@ -197,58 +197,5 @@ struct Spec {
197197
commands = define_static_array(parser.commands);
198198
options = define_static_array(parser.options);
199199
}
200-
201-
bool parse_as_command(ArgParser& parser) const {
202-
for (auto cmd : commands) {
203-
if (auto unevaluated = cmd.parse(parser); unevaluated) {
204-
(*unevaluated)(nullptr);
205-
return true;
206-
}
207-
}
208-
return false;
209-
}
210-
211-
std::optional<Option::Unevaluated> parse_as_option(ArgParser& parser) const {
212-
for (auto opt : options) {
213-
if (auto unevaluated = opt.parse(parser); unevaluated) {
214-
return unevaluated;
215-
}
216-
}
217-
218-
return {};
219-
}
220-
221-
std::vector<Argument::Unevaluated> parse_arguments(ArgParser& parser) const {
222-
std::vector<Argument::Unevaluated> parsed_args;
223-
for (auto arg : arguments) {
224-
auto argument = arg.parse(parser);
225-
if (!argument) {
226-
if (!arg.is_optional) {
227-
std::println("Missing required argument {}", arg.name);
228-
std::exit(1);
229-
}
230-
// failed to parse argument - bail out
231-
return parsed_args;
232-
}
233-
parsed_args.push_back(*argument);
234-
}
235-
return parsed_args;
236-
}
237-
238-
std::vector<Option::Unevaluated> parse_options(ArgParser& parser) const {
239-
std::vector<Option::Unevaluated> parsed_opts{};
240-
while (parser.valid()) {
241-
if (parse_as_command(parser)) {
242-
continue;
243-
}
244-
245-
auto unevaluated = parse_as_option(parser);
246-
if (!unevaluated) {
247-
parser.fail("Could not find option `{}`", parser.current());
248-
}
249-
parsed_opts.push_back(*unevaluated);
250-
}
251-
return parsed_opts;
252-
}
253200
};
254201
} // namespace rsl::_cli_impl

0 commit comments

Comments
 (0)