Skip to content

Commit abfb832

Browse files
committed
implement shorthands
1 parent 17446ce commit abfb832

5 files changed

Lines changed: 35 additions & 15 deletions

File tree

include/rsl/cli/annotations.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,4 @@ struct Shorthand : _impl::StringAnnotation {
4343
struct Description : _impl::StringAnnotation {
4444
using _impl::StringAnnotation::StringAnnotation;
4545
};
46-
4746
} // namespace rsl::annotations

include/rsl/cli/option.hpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <meta>
3+
#include <rsl/constexpr_assert>
34
#include <rsl/meta_traits>
45
#include <vector>
56
#include <string_view>
@@ -104,19 +105,32 @@ struct Option {
104105
rsl::string_view name;
105106
rsl::string_view description;
106107
rsl::span<Parameter const> parameters;
108+
char shorthand = '\0';
107109
bool run_early = false;
108110
bool is_flag = false;
109111

110112
std::optional<Unevaluated> parse(ArgParser& parser) {
111113
auto opt_name = parser.current();
112-
if (!opt_name.starts_with("--")) {
114+
if (!opt_name.starts_with('-')) {
113115
return {};
114116
}
115117

116-
opt_name.remove_prefix(2);
117-
if (opt_name != name) {
118-
return {};
118+
opt_name.remove_prefix(1);
119+
if (!opt_name.starts_with('-')) {
120+
if (opt_name.size() != 1) {
121+
return {};
122+
}
123+
124+
if (opt_name[0] != shorthand) {
125+
return {};
126+
}
127+
} else {
128+
opt_name.remove_prefix(1);
129+
if (opt_name != name) {
130+
return {};
131+
}
119132
}
133+
120134
++parser.cursor; // parser will not unwind after this point
121135

122136
Unevaluated option{.handle = _impl_handler};
@@ -152,6 +166,15 @@ struct Option {
152166
description = std::define_static_string(desc->data);
153167
}
154168

169+
if (auto shorthand_tag = annotation_of_type<annotations::Shorthand>(reflection);
170+
shorthand_tag) {
171+
auto short_opt = shorthand_tag->data;
172+
if (short_opt.size() != 1) {
173+
compile_error("Shorthands need to be a single character");
174+
}
175+
shorthand = short_opt[0];
176+
}
177+
155178
if (meta::has_annotation<annotations::Flag>(reflection)) {
156179
is_flag = true;
157180
}

include/rsl/cli/parser.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ T parse_value(std::string_view value) {
3535
// TODO move out of header
3636
std::string lower_value(value);
3737
std::ranges::transform(lower_value, lower_value.begin(), [](char c) {return std::tolower(c); });
38-
std::println("{}", lower_value);
3938
if (lower_value == "1" || lower_value == "y" || lower_value == "yes" || lower_value == "on" ||
4039
lower_value == "true") {
4140
return true;

include/rsl/config

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,10 @@ struct config {
243243
};
244244

245245
struct cli {
246-
static constexpr auto option = annotations::option;
247-
static constexpr auto positional = annotations::positional;
248-
static constexpr auto value = rsl::placeholders::_0;
249-
static constexpr auto flag = annotations::flag;
250-
246+
static constexpr auto option = annotations::option;
247+
static constexpr auto positional = annotations::positional;
248+
static constexpr auto value = rsl::placeholders::_0;
249+
static constexpr auto flag = annotations::flag;
251250
using shorthand = annotations::Shorthand;
252251
using description = annotations::Description;
253252

src/cli.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ std::string& config::get_config_path() {
1111
void _cli_impl::print_help(_cli_impl::Spec const& spec,
1212
std::string_view program_name,
1313
std::string_view description) {
14+
if (!description.empty()) {
15+
std::println("{}", description);
16+
}
17+
1418
std::string arguments{};
1519
for (auto argument : spec.arguments) {
1620
if (argument.is_optional) {
@@ -21,10 +25,6 @@ void _cli_impl::print_help(_cli_impl::Spec const& spec,
2125
}
2226
std::println("usage: {} {}", program_name, arguments);
2327

24-
if (!description.empty()) {
25-
std::println("\n{}", description);
26-
}
27-
2828
std::println("\nArguments:");
2929
for (auto argument : spec.arguments) {
3030
std::println(" {} -> {}", argument.name, argument.type);

0 commit comments

Comments
 (0)