Coreutils++
The GNU Coreutils implemented in C++
Loading...
Searching...
No Matches
ArgumentParser.hpp
Go to the documentation of this file.
1
20
21#ifndef LIB_ARGUMENTPARSER_HPP_
22#define LIB_ARGUMENTPARSER_HPP_
23
24#include <array>
25#include <concepts>
26#include <cstddef>
27#include <cstdlib>
28#include <print>
29#include <span>
30#include <string_view>
31#include <tuple>
32#include <type_traits>
33
35
36namespace coreutils {
37
38template <class T, auto Converter, detail::ComptimeString... Names>
40 detail::Argument<T, detail::NArgs::Many, Converter, Names...>;
41
42template <class T, auto Converter>
44 detail::Argument<T, detail::NArgs::Many, Converter, "">;
45
46template <detail::ComptimeString... Names>
48 [](std::string_view) {}, Names...>;
49
50template <class T, auto Converter, detail::ComptimeString... Names>
52 detail::Argument<T, detail::NArgs::One, Converter, Names...>;
53
54template <detail::ComptimeString HelpText, detail::ComptimeString... Names>
55struct ArgumentInfo final {
56 static inline constexpr std::array<std::string_view, sizeof...(Names)>
57 names{Names.PrintableView()...};
58 static inline constexpr std::string_view help_text{
59 HelpText.PrintableView()};
60};
61
62template <class ConvertedType, auto Converter>
64 std::regular_invocable<decltype(Converter), std::string_view> &&
65 std::same_as<ConvertedType,
66 std::invoke_result_t<decltype(Converter), std::string_view>>;
67
68template <class ConvertedType, auto Converter>
69concept EmptyConverter = std::same_as<bool, ConvertedType> &&
70 std::same_as<decltype(Converter), nullptr_t>;
71
72template <class ConvertedType>
73concept NonVoid = !std::same_as<ConvertedType, void>;
74
75template <class ConvertedType, auto Converter>
79
80template <class ConvertedType, auto Converter>
82struct ConversionInfo final {
83 using type = ConvertedType;
84 static inline constexpr decltype(Converter) Fn{Converter};
85};
86
87template <detail::ComptimeString Program, detail::ComptimeString Version,
88 detail::ComptimeString Usage, detail::ComptimeString Summary>
89struct ProgramInfo final {
90 static inline constexpr detail::ComptimeString name{Program};
91 static inline constexpr detail::ComptimeString version{Version};
92 static inline constexpr detail::ComptimeString usage{Usage};
93 static inline constexpr detail::ComptimeString summary{Summary};
94};
95
96template <class T, template <class, auto> class U>
97struct is_conversion_info : std::false_type {};
98
99template <class V, auto C, template <class, auto> class U>
100struct is_conversion_info<U<V, C>, ConversionInfo> : std::true_type {};
101
102template <class T>
105
106template <class T, template <detail::ComptimeString...> class U>
107struct is_instance_of : std::false_type {};
108
109template <detail::ComptimeString... Info>
110struct is_instance_of<ProgramInfo<Info...>, ProgramInfo> : std::true_type {};
111
112template <detail::ComptimeString... Info>
113struct is_instance_of<ArgumentInfo<Info...>, ArgumentInfo> : std::true_type {};
114
115template <class T>
117
118template <class T>
120
121template <class T>
123 is_conversion_info_v<T> && std::same_as<typename T::type, bool> &&
124 std::same_as<std::remove_cv_t<decltype(T::Fn)>, nullptr_t>;
125
126template <class T>
128 is_conversion_info_v<T> && !std::same_as<typename T::type, void>;
129
130template <IsArgumentInfo Info_t, IsFlagConverter Converter_t>
131struct Flag {};
132
133template <IsArgumentInfo Info_t, IsValueConverter Converter_t>
134struct Option {};
135
136template <class T>
137concept Arg = requires(T arg) {
138 std::same_as<std::string_view, decltype(T::help_view_)>;
139 T::value;
140};
141
142template <IsProgramInfo Program, Arg... Args>
143class ArgumentParser final {
144 public:
145 constexpr explicit ArgumentParser(int argc, const char** argv)
146 : args_{argv + 1, argv + argc} {}
147
148 constexpr auto ParseArgsOrExit() {
149 for (std::string_view arg : args_) {
150 if (arg == "--version") {
151 PrintVersion();
152 } else if (arg == "--help") {
153 PrintHelp();
154 } else {
155 if (arg.starts_with('-')) {
156 std::apply(
157 [arg](auto&... a) { (a.TryParseFlag(arg), ...); },
159 } else {
160 std::apply(
161 [arg](auto&... a) { (a.TryParseValue(arg), ...); },
163 }
164 }
165 }
166 }
167
168 [[noreturn]]
169 constexpr void PrintVersion() const {
170 std::println("{} (coreutilspp) version {}\n\n{}",
171 Program::name.PrintableView(),
172 Program::version.PrintableView(), license_info_);
173 std::exit(0);
174 }
175
176 [[noreturn]]
177 constexpr void PrintHelp() const {
178 std::println(Program::usage.PrintableView());
179 std::println(Program::summary.PrintableView());
180 std::println("\t{:<15}{:<}", "--help", "display this help and exit");
181 std::println("\t{:<15}{:<}", "--version",
182 "output version information and exit");
183 (std::println("\t{}", Args::help_view_), ...);
184 std::exit(0);
185 }
186
187 template <class Out>
188 constexpr Out& get() {
189 return std::get<Out>(arg_values_);
190 }
191
192 private:
193 // since argc and argv should be valid for the lifetime of the main
194 // function, storing this should be safe, as the lifetime of this object
195 // should logically always be less than the main function.
196 std::span<const char*> args_{};
197 std::tuple<Args...> arg_values_{};
198
199 static constexpr std::string_view license_info_{
200 "Copyright (C) 2025 Free Software Foundation, Inc.\nLicense GPLv3+: "
201 "GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\nThis "
202 "is free software: you are free to change and redistribute it.\nThere "
203 "is NO WARRANTY, to the extent permitted by law."};
204};
205} // namespace coreutils
206
207#endif // LIB_ARGUMENTPARSER_HPP_
static constexpr std::string_view license_info_
Definition ArgumentParser.hpp:199
constexpr Out & get()
Definition ArgumentParser.hpp:188
std::tuple< Args... > arg_values_
Definition ArgumentParser.hpp:197
constexpr ArgumentParser(int argc, const char **argv)
Definition ArgumentParser.hpp:145
constexpr auto ParseArgsOrExit()
Definition ArgumentParser.hpp:148
constexpr void PrintHelp() const
Definition ArgumentParser.hpp:177
std::span< const char * > args_
Definition ArgumentParser.hpp:196
constexpr void PrintVersion() const
Definition ArgumentParser.hpp:169
Definition ArgumentParser.hpp:137
Definition ArgumentParser.hpp:76
Definition ArgumentParser.hpp:69
Definition ArgumentParser.hpp:119
Definition ArgumentParser.hpp:122
Definition ArgumentParser.hpp:116
Definition ArgumentParser.hpp:127
Definition ArgumentParser.hpp:73
Definition ArgumentParser.hpp:63
implmentation details for the coreutlspp-wide argument parser
@ One
Definition ArgumentParser.hpp:72
@ Many
Definition ArgumentParser.hpp:73
@ None
Definition ArgumentParser.hpp:71
Definition ArgumentParser.hpp:36
detail::Argument< T, detail::NArgs::Many, Converter, Names... > MultiValueArgument
Definition ArgumentParser.hpp:39
decltype(auto) is_conversion_info_v
Definition ArgumentParser.hpp:103
detail::Argument< T, detail::NArgs::Many, Converter, ""> PositionalArguments
Definition ArgumentParser.hpp:43
detail::Argument< void, detail::NArgs::None,[](std::string_view) {}, Names... > BooleanArgument
Definition ArgumentParser.hpp:47
detail::Argument< T, detail::NArgs::One, Converter, Names... > SingleValueArgument
Definition ArgumentParser.hpp:51
Definition ArgumentParser.hpp:55
static constexpr std::string_view help_text
Definition ArgumentParser.hpp:58
static constexpr std::array< std::string_view, sizeof...(Names)> names
Definition ArgumentParser.hpp:57
Definition ArgumentParser.hpp:82
static constexpr decltype(Converter) Fn
Definition ArgumentParser.hpp:84
ConvertedType type
Definition ArgumentParser.hpp:83
Definition ArgumentParser.hpp:131
Definition ArgumentParser.hpp:134
Definition ArgumentParser.hpp:89
static constexpr detail::ComptimeString summary
Definition ArgumentParser.hpp:93
static constexpr detail::ComptimeString usage
Definition ArgumentParser.hpp:92
static constexpr detail::ComptimeString version
Definition ArgumentParser.hpp:91
static constexpr detail::ComptimeString name
Definition ArgumentParser.hpp:90
Definition ArgumentParser.hpp:103
Definition ArgumentParser.hpp:40
consteval std::string_view PrintableView() const
Definition ArgumentParser.hpp:52
Definition ArgumentParser.hpp:97
Definition ArgumentParser.hpp:107