di 0.1.0
Loading...
Searching...
No Matches
argument.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/cli/value_type.h"
4#include "di/cli/zsh.h"
10#include "di/parser/prelude.h"
12
13namespace di::cli::detail {
14class Argument {
15private:
16 using Parse = Result<> (*)(void*, Span<TransparentStringView>);
17 using GetValues = Vector<Tuple<String, StringView>> (*)();
18 using DefaultValue = String (*)();
19
20 template<auto member>
21 constexpr static auto concrete_variadic() -> bool {
22 using Value = meta::MemberPointerValue<decltype(member)>;
23
24 // Match any form of vector, but not a string-like type.
25 return concepts::detail::MutableVector<Value> && !concepts::HasEncoding<Value>;
26 }
27
28 template<auto member>
29 constexpr static auto concrete_parse(void* output_untyped, Span<TransparentStringView> input) -> Result<> {
30 using Base = meta::MemberPointerClass<decltype(member)>;
31 using Value = meta::MemberPointerValue<decltype(member)>;
32
33 auto* output = static_cast<Base*>(output_untyped);
34 if constexpr (concrete_variadic<member>()) {
35 auto& vector = (*output).*member = Value();
36 for (auto view : input) {
38 DI_TRY(vector.emplace_back(DI_TRY(parser::parse<meta::ContainerValue<Value>>(view))));
39 } else {
40 vector.emplace_back(DI_TRY(parser::parse<meta::ContainerValue<Value>>(view)));
41 }
42 }
43 return {};
44 } else {
45 DI_ASSERT(input.size() == 1);
46 if constexpr (concepts::Optional<Value>) {
47 (*output).*member = DI_TRY(parser::parse<meta::OptionalValue<Value>>(input[0]));
48 } else {
49 (*output).*member = DI_TRY(parser::parse<Value>(input[0]));
50 }
51 return {};
52 }
53 }
54
55public:
56 Argument() = default;
57
58 template<auto member>
59 constexpr explicit Argument(Constexpr<member>, StringView argument_name = {}, StringView description = {},
60 bool required = false, Optional<ValueType> value_type = {})
61 : m_parse(concrete_parse<member>)
62 , m_get_values(detail::concrete_get_values<meta::MemberPointerValue<decltype(member)>>)
63 , m_default_value(detail::concrete_default_value<member>)
64 , m_argument_name(argument_name)
65 , m_description(description)
66 , m_value_type(value_type.value_or(default_value_type<meta::MemberPointerValue<decltype(member)>>))
67 , m_required(required)
68 , m_variadic(concrete_variadic<member>()) {
69 static_assert(concepts::MemberObjectPointer<decltype(member)>,
70 "Argument member must be a pointer to a member object.");
71 }
72
73 constexpr auto parse(void* output, Span<TransparentStringView> input) const {
74 DI_ASSERT(m_parse);
75 return m_parse(output, input);
76 }
77 constexpr auto argument_name() const { return m_argument_name; }
78 constexpr auto description() const { return m_description; }
79 constexpr auto required() const { return m_required; }
80 constexpr auto variadic() const { return m_variadic; }
81
82 constexpr auto required_argument_count() const -> usize { return required() ? 1 : 0; }
83
84 constexpr auto display_name() const {
85 auto result = di::String {};
86 if (!required()) {
87 result.push_back(U'[');
88 }
89 result += m_argument_name;
90 if (variadic()) {
91 result.push_back(U'.');
92 result.push_back(U'.');
93 result.push_back(U'.');
94 }
95 if (!required()) {
96 result.push_back(U']');
97 }
98 return result;
99 }
100
101 constexpr auto default_value() const -> String { return m_default_value(); }
102 constexpr auto value_type() const -> ValueType { return m_value_type; }
103 constexpr auto values() const -> Vector<Tuple<String, StringView>> { return m_get_values(); }
104
105 constexpr auto zsh_completion_spec() const -> String {
106 auto var = variadic() ? "*"_sv : ""_sv;
107 auto optional = required_argument_count() > 0 ? ""_sv : ":"_sv;
108 auto values = this->values();
109 return format("{}:{} -- {}:{}"_sv, var, optional, zsh::escape_arg_description(description()),
110 zsh::value_completions(m_value_type, values.span()));
111 }
112
113private:
114 Parse m_parse { nullptr };
115 GetValues m_get_values { nullptr };
116 DefaultValue m_default_value { nullptr };
117 StringView m_argument_name;
118 StringView m_description;
119 ValueType m_value_type { ValueType::Unknown };
120 bool m_required { false };
121 bool m_variadic { false };
122};
123}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition vector.h:25
Definition optional_forward_declaration.h:5
Definition span_forward_declaration.h:10
Definition vocab.h:30
Definition encoding.h:225
Definition language.h:203
Definition vocab.h:77
#define DI_TRY(...)
Definition monad_try.h:13
constexpr auto value_completions(ValueType value_type, Span< Tuple< String, StringView > > values) -> String
Definition zsh.h:140
constexpr auto escape_arg_description(StringView input) -> String
Definition zsh.h:57
ValueType
Definition value_type.h:11
@ Unknown
Definition value_type.h:12
constexpr auto default_value_type
Definition value_type.h:82
string::StringViewImpl< string::Utf8Encoding > StringView
Definition string_view.h:12
string::StringImpl< string::Utf8Encoding > String
Definition string.h:11
Type< detail::MemberPointerValueHelper< RemoveCV< T > > > MemberPointerValue
Definition language.h:184
meta::RemoveCVRef< T >::Value OptionalValue
Definition vocab.h:82
Type< detail::MemberPointerClassHelper< RemoveCV< T > > > MemberPointerClass
Definition language.h:195
IteratorValue< ContainerIterator< T > > ContainerValue
Definition container_value.h:8
constexpr auto parse
Definition parse.h:23
size_t usize
Definition integers.h:33
Expected< T, Error > Result
Definition result.h:8
constexpr auto format
Definition format.h:7
constexpr auto parse
Definition parse.h:23
A wrapper for a constexpr value.
Definition constexpr.h:36