Skip to content

Commit 8a73c20

Browse files
committed
implement json5 comments, more work on spec
1 parent c62e0c3 commit 8a73c20

6 files changed

Lines changed: 90 additions & 32 deletions

File tree

example/simple.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22

33
#include <rsl/config>
44

5-
struct Arguments : rsl::config {
6-
// static inline std::string config_path = "foo";
7-
[[=positional]] std::string text;
5+
struct Test : rsl::config {
86
bool from_config;
7+
8+
[[=option]]
9+
static void zoinks(){}
10+
};
11+
12+
struct Arguments : rsl::cli {
13+
[[=positional]] std::string text;
14+
Test foo;
915
[[=positional]] int times = 5;
1016

1117
[[=option]]
1218
void test(int x) {
1319
std::println("text: {}, times: {}, x: {}", text, times, x);
1420
}
15-
16-
// [[=option]]
17-
// static void config(std::string cfg_path) {
18-
// std::println("config() invoked");
19-
// Arguments::config_path = cfg_path;
20-
// }
2121
};
2222

2323
int main(int argc, char** argv) {

include/rsl/cli/spec.hpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "annotations.hpp"
1414

1515
namespace rsl {
16+
struct cli;
1617
struct config;
1718
}
1819

@@ -35,11 +36,11 @@ struct Spec {
3536
std::vector<Spec> subcommands;
3637

3738
consteval void parse(std::meta::info r) {
38-
// for (auto base : bases_of(r)) {
39-
// bases.emplace_back(type_of(base));
40-
// }
41-
4239
auto ctx = std::meta::access_context::current();
40+
for (auto base : bases_of(r, ctx)) {
41+
parse_base(r, base);
42+
}
43+
4344
std::size_t nsdm_idx = bases_of(r, ctx).size();
4445
for (auto member : members_of(r, ctx)) {
4546
if (!has_identifier(member) || !is_public(member)) {
@@ -53,19 +54,21 @@ struct Spec {
5354
}
5455
}
5556

56-
consteval void parse_base(std::meta::info r) {
57-
if (extract<bool>(substitute(^^std::derived_from, {dealias(r), ^^config}))) {
58-
for (auto fnc_template : members_of(^^config, std::meta::access_context::current()) |
59-
std::views::filter(std::meta::is_function_template)) {
60-
if (!can_substitute(fnc_template, {r})) {
57+
consteval void parse_base(std::meta::info self, std::meta::info r) {
58+
if (extract<bool>(substitute(^^std::convertible_to, {type_of(r), ^^config}))) {
59+
// special case built-in bases. These need to access the child type
60+
61+
for (auto fnc_template : members_of(type_of(r), std::meta::access_context::current())) {
62+
if (!is_function_template(fnc_template) || !can_substitute(fnc_template, {self})) {
6163
continue;
6264
}
6365

64-
auto fnc = substitute(fnc_template, {r});
66+
auto fnc = substitute(fnc_template, {self});
6567
if (meta::has_annotation<annotations::Option>(fnc)) {
6668
commands.emplace_back(identifier_of(fnc_template), fnc);
6769
}
6870
}
71+
bases.push_back({});
6972
}
7073
}
7174

@@ -150,7 +153,7 @@ struct Spec {
150153
};
151154

152155
rsl::string_view name;
153-
rsl::span<rsl::span<Argument const>> bases;
156+
rsl::span<rsl::span<Argument const> const> bases;
154157
rsl::span<Argument const> arguments;
155158
rsl::span<Option const> commands;
156159
rsl::span<Option const> options;
@@ -159,9 +162,14 @@ struct Spec {
159162
auto type = is_type(r) ? r : type_of(r);
160163
auto parser = Parser();
161164
parser.parse(type);
162-
parser.parse_base(type);
165+
// parser.parse_base(type);
163166
parser.validate();
164-
// bases = define_static_array(parser.bases);
167+
std::vector<rsl::span<Argument const>> meta_bases;
168+
for (auto base : parser.bases) {
169+
meta_bases.push_back(rsl::span(define_static_array(base)));
170+
}
171+
172+
bases = define_static_array(meta_bases);
165173
arguments = define_static_array(parser.arguments);
166174
commands = define_static_array(parser.commands);
167175
options = define_static_array(parser.options);

include/rsl/config

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,17 @@ public:
3232
};
3333

3434
class config {
35-
static std::string& get_config_path();
3635
static void print_help(_cli_impl::Spec const& spec,
3736
std::string_view program_name,
3837
std::string_view description);
3938

4039
public:
4140
static constexpr auto option = annotations::option;
42-
static constexpr auto positional = annotations::positional;
4341
static constexpr auto value = rsl::placeholders::_0;
4442

4543
using shorthand = annotations::Shorthand;
4644
using description = annotations::Description;
4745

48-
static std::string_view config_path() { return get_config_path(); }
49-
50-
template <typename T>
51-
[[= option]] static void config_path(std::string new_path) {
52-
get_config_path() = new_path;
53-
}
54-
5546
template <typename T>
5647
[[= option]] [[noreturn]]
5748
static void help() {
@@ -66,6 +57,31 @@ public:
6657
}
6758
};
6859

60+
class cli : public config {
61+
static std::string& get_config_path();
62+
public:
63+
static constexpr auto option = annotations::option;
64+
static constexpr auto positional = annotations::positional;
65+
static constexpr auto value = rsl::placeholders::_0;
66+
67+
using shorthand = annotations::Shorthand;
68+
using description = annotations::Description;
69+
70+
static std::string_view config_path() { return get_config_path(); }
71+
72+
template <typename T>
73+
[[= option]]
74+
static void config_path(std::string new_path) {
75+
get_config_path() = new_path;
76+
}
77+
78+
template <typename T>
79+
[[= option]] [[noreturn]]
80+
static void help() {
81+
config::template help<T>();
82+
}
83+
};
84+
6985
template <typename T>
7086
T load_config(std::vector<std::string_view> args_in) {
7187
static constexpr _cli_impl::Spec spec{^^T};

include/rsl/json5/json5.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct Parser {
8080
std::string_view::iterator cursor = std::begin(file);
8181

8282
void skip_whitespace();
83+
bool skip_comment();
8384
void expect_consume(char c);
8485
void maybe_consume(char c);
8586
void parse_until(std::vector<char> delims, std::string& out);

src/cli.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <rsl/config>
44

55
namespace rsl {
6-
std::string& config::get_config_path() {
6+
std::string& cli::get_config_path() {
77
static std::string config_path{ std::filesystem::current_path() / "settings.json5" };
88
return config_path;
99
}

src/json5/parser.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,42 @@ void Parser::expect_more() const {
3232
}
3333
}
3434

35+
bool Parser::skip_comment() {
36+
if (cursor == file.end()){
37+
return false;
38+
}
39+
40+
if (*cursor == '/') {
41+
++cursor;
42+
expect_more();
43+
std::string content;
44+
if (*cursor == '/') {
45+
++cursor;
46+
parse_until({'\n'}, content);
47+
} else if (*cursor == '*') {
48+
++cursor;
49+
parse_until({'*', '/'}, content);
50+
} else {
51+
// roll back - this parse was invalid
52+
--cursor;
53+
return false;
54+
}
55+
// TODO we probably want to keep comments to round-trip properly
56+
// std::println("Comment: {}", content);
57+
return true;
58+
}
59+
return false;
60+
}
61+
3562
void Parser::skip_whitespace() {
3663
while (is_whitespace(*cursor))
3764
cursor++;
65+
66+
if (skip_comment()) {
67+
// comment found - recurse
68+
skip_whitespace();
69+
}
70+
3871
};
3972

4073
void Parser::expect_consume(char c) {

0 commit comments

Comments
 (0)