36 std::optional<std::string> description;
37 std::size_t min_count = 1;
38 std::size_t max_count = 1;
42 flag(std::string name, std::optional<std::string> description = {}):
43 name(name), description(description) {}
51 min_count = std::max(
static_cast<std::size_t
>(1), min_count);
136 using storage_t = std::variant<
154 void display(std::ostream& out)
const {
156 switch (storage.index()) {
158 std::get<0>(storage).display(out);
161 std::get<1>(storage).display(out);
164 std::get<2>(storage).display(out);
167 std::get<3>(storage).display(out);
170 std::get<4>(storage).display(out);
173 std::get<5>(storage).display(out);
176 std::get<6>(storage).display(out);
183 return std::holds_alternative<T>(storage);
188 return std::get<T>(storage);
192 const T& as()
const {
193 return std::get<T>(storage);
203 friend class program;
205 std::unordered_map<std::string, std::any> _flags;
206 std::vector<std::string> _pos_args;
207 std::optional<std::tuple<std::string, clone_ptr<match>>> _subcommand = {};
209 void add_flag(std::string name, std::any
value) {
210 _flags.emplace(name,
value);
213 void add_pos_arg(std::string arg) {
214 _pos_args.push_back(arg);
223 std::unordered_map<std::string, std::any> _flags,
224 std::vector<std::string> _pos_args,
226 ): _flags(_flags), _pos_args(_pos_args), _subcommand(_subcommand) {}
228 match* clone()
const {
229 return new match { _flags, _pos_args, _subcommand };
232 std::size_t count_flags()
const {
233 return _flags.size();
236 bool has_flag(
const std::string& name)
const {
237 return _flags.count(name);
241 std::optional<T> get_flag(
const std::string& name)
const {
242 auto match = _flags.find(name);
243 if (match == _flags.end()) {
246 return std::any_cast<T>(match->second);
249 std::size_t count_pos_args()
const {
250 return _pos_args.size();
253 std::string get_pos_arg(std::size_t i) {
257 auto get_pos_args()
const {
261 bool has_subcommand()
const noexcept {
262 return _subcommand.has_value();
265 std::tuple<std::string, clone_ptr<match>>& subcommand() {
266 ZEN_ASSERT(_subcommand);
287 friend class program;
292 std::optional<std::string> _description;
293 std::unordered_map<std::string, _flag_info> _flags;
294 std::vector<command> _subcommands;
295 std::vector<posarg> _pos_args;
296 bool _is_fallback =
false;
297 std::optional<command_callback_t> _callback;
301 inline command(std::string name, std::optional<std::string> description = {}):
302 _name(name), _description(description) {}
304 command& description(std::string description) {
305 _description = description;
310 command& flag(flag<T> fl) {
311 _flags.emplace(fl.name,
_flag_info { fl.description, typeid(T), fl.min_count, fl.max_count });
315 command& action(command_callback_t callback) {
316 _callback = callback;
320 command& fallback() {
325 command& subcommand(command cmd) {
326 _subcommands.push_back(cmd);
330 command& pos_arg(std::string name,
int arity = 1) {
331 _pos_args.push_back(
posarg(name, arity));
358 inline program(std::string name, std::optional<std::string> description = {}):
359 _command(name, description) {}
361 program& description(std::string description) {
362 _command.description(description);
366 program& subcommand(
command cmd) {
367 _command.subcommand(cmd);
372 program& flag(flag<T> fl) {
377 program& pos_arg(std::string name,
int arity = 1) {
378 _command.pos_arg(name, arity);
382 result<match> parse_args(std::vector<std::string_view> argv);
384 result<match> parse_args(
int argc,
const char** argv);