libmx2 2.2.1
C++20 multimedia and game-engine library (SDL2 / OpenGL / Vulkan)
Loading...
Searching...
No Matches
argz.hpp
Go to the documentation of this file.
1
2/**
3 * @file argz.hpp
4 * @brief Lightweight, header-only, template command-line argument parser.
5 *
6 * Supports both short options (@c -x) and long options (@c --name), with or
7 * without values, for any string type that satisfies the StringType concept
8 * (typically @c std::string or @c std::wstring).
9 *
10 * Typical usage:
11 * @code
12 * Argz<std::string> parser(argc, argv);
13 * parser.addOptionSingle('h', "Show help")
14 * .addOptionSingleValue('o', "Output file");
15 * Argument<std::string> arg;
16 * int code;
17 * while ((code = parser.proc(arg)) != -1) { ... }
18 * @endcode
19 *
20 * A convenience wrapper proc_args() provides a pre-built parser that handles
21 * the options common to all libmx2 applications (-p path, -r resolution, -f fullscreen, …).
22 */
23
24#ifndef _ARGZ_HPP_X
25#define _ARGZ_HPP_X
26
27#include <algorithm>
28#include <iomanip>
29#include <iostream>
30#include <string>
31#include <type_traits>
32#include <unordered_map>
33#include <utility>
34#include <vector>
35
36/**
37 * @concept StringType
38 * @brief Models a string-like class with indexing, concatenation, length, and value_type.
39 *
40 * Both @c std::string and @c std::wstring satisfy this concept.
41 * @tparam T The type to constrain.
42 */
43template <typename T>
44concept StringType = std::is_class_v<T> && requires(T type) {
45 type.length();
46 type[0];
47 type += type;
48 type = type;
49 typename T::value_type;
50 typename T::size_type;
51 { type.length() } -> std::same_as<typename T::size_type>;
52 { type[0] } -> std::same_as<typename T::value_type &>;
53 { type += T{} } -> std::same_as<T &>;
54 { type = T{} } -> std::same_as<T &>;
55};
56
57/** @brief Discriminator for option kind used inside Argument. */
59
60/**
61 * @struct Argument
62 * @brief Describes a single parsed argument entry returned by Argz::proc().
63 * @tparam String String type satisfying StringType.
64 *
65 * After a successful call to Argz::proc() the member @c arg_letter holds the
66 * matched code (or @c '-' for bare positional arguments) and @c arg_value holds
67 * any associated value string.
68 */
69template <StringType String>
70struct Argument {
71 String arg_name; ///< Long option name (e.g. @c "output").
72 int arg_letter; ///< Short option code (e.g. @c 'o') or unique integer for long-only options.
73 String arg_value; ///< Value string supplied after the option, if any.
74 ArgType arg_type; ///< Which @c ArgType variant this argument represents.
75 String desc; ///< Human-readable description used in help output.
76 ~Argument() = default;
84 desc = a.desc;
85 return *this;
86 }
87 auto operator<=>(const Argument<String> &a) const { return (arg_letter <=> a.arg_letter); }
88};
89
90/**
91 * @struct ArgumentData
92 * @brief Holds the raw @c argv strings converted to the target @c String type.
93 * @tparam String String type satisfying StringType.
94 */
95template <StringType String>
97 std::vector<String> args; ///< Converted argv entries (argv[1] … argv[argc-1]).
98 int argc; ///< Original argc value.
99 ~ArgumentData() = default;
100 ArgumentData() = default;
103 if(!args.empty()) {
104 args.erase(args.begin(), args.end());
105 }
106 std::copy(a.args.begin(), a.args.end(), std::back_inserter(args));
107 argc = a.argc;
108 return *this;
109 }
112 args = std::move(a.args);
113 argc = a.argc;
114 return *this;
115 }
116};
117
118/**
119 * @class ArgException
120 * @brief Exception thrown by Argz::proc() on unrecognised or malformed options.
121 * @tparam String String type satisfying StringType.
122 */
123template <StringType String>
125public:
126 ArgException() = default;
127 ArgException(const String &s) : value{s} {}
128 String text() const { return value; }
129
130private:
131 String value;
132};
133
134/**
135 * @class Argz
136 * @brief Template command-line argument parser.
137 * @tparam String String type satisfying StringType (usually @c std::string or @c std::wstring).
138 *
139 * Options are registered with addOption*() before parsing.
140 * Call proc() in a loop until it returns @c -1 to iterate over all arguments.
141 */
142template <StringType String>
143class Argz {
144public:
145 ~Argz() = default;
146 Argz() = default;
147
148 /**
149 * @brief Construct and immediately ingest argv.
150 * @param argc Argument count from main().
151 * @param argv Argument vector from main().
152 */
153 Argz(int argc, char **argv) { initArgs(argc, argv); }
155
157 arg_data = a.arg_data;
158 if(!arg_info.empty()) {
159 arg_info.erase(arg_info.begin(), arg_info.end());
160 }
161 for(const auto &i : a.arg_info) {
162 arg_info[i.first] = i.second;
163 }
164 index = a.index;
165 cindex = a.cindex;
166 return *this;
167 }
168
169 Argz(Argz<String> &&a) : arg_data{std::move(a.arg_data)}, arg_info{std::move(a.arg_info)}, index{a.index}, cindex{a.cindex} {}
170
172 arg_data = std::move(a.arg_data);
173 arg_info = std::move(a.arg_info);
174 index = a.index;
175 cindex = a.cindex;
176 return *this;
177 }
178
179 /**
180 * @brief Ingest argc/argv, converting to the target String type.
181 * @param argc Argument count.
182 * @param argv Argument vector.
183 * @return Reference to @c *this for method chaining.
184 */
185 Argz<String> &initArgs(int argc, char **argv) {
186 arg_data.argc = argc;
187 if constexpr(std::is_same<typename String::value_type, char>::value) {
188 for(int i = 1; i < argc; ++i) {
189 const char *a = argv[i];
190 arg_data.args.push_back(a);
191 }
192 reset();
193 return *this;
194 }
195 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
196 for(int i = 1; i < argc; ++i) {
197 const char *a = argv[i];
198 String data;
199 for(size_t z = 0; a[z] != 0; ++z) {
200 data += static_cast<typename String::value_type>(a[z]);
201 }
202 arg_data.args.push_back(data);
203 }
204 reset();
205 return *this;
206 }
207 reset();
208 return *this;
209 }
210
211 /** @brief Reset the internal parse cursor to the beginning of argv. */
212 void reset() {
213 index = 0;
214 cindex = 1;
215 }
216
217 /**
218 * @brief Register a flag-only short option (e.g. @c -v, @c -h).
219 * @param c Short option character code.
220 * @param description Help text.
221 * @return Reference to @c *this for chaining.
222 */
223 Argz<String> &addOptionSingle(const int &c, const String &description) {
225 a.arg_letter = c;
227 a.desc = description;
228 arg_info[c] = a;
229 return *this;
230 }
231
232 /**
233 * @brief Register a short option that requires a value argument (e.g. @c -o file).
234 * @param c Short option character code.
235 * @param description Help text.
236 * @return Reference to @c *this for chaining.
237 */
238 Argz<String> &addOptionSingleValue(const int &c, const String &description) {
240 a.arg_letter = c;
242 a.desc = description;
243 arg_info[c] = a;
244 return *this;
245 }
246
247 /**
248 * @brief Register a flag-only long option (e.g. @c --verbose).
249 * @param code Unique integer code associated with this option.
250 * @param value Long option name string (without @c --).
251 * @param description Help text.
252 * @return Reference to @c *this for chaining.
253 */
254 Argz<String> &addOptionDouble(const int &code, const String &value, const String &description) {
256 a.arg_letter = code;
258 a.desc = description;
259 a.arg_name = value;
260 arg_info[code] = a;
261 return *this;
262 }
263
264 /**
265 * @brief Register a long option that requires a value argument (e.g. @c --output file).
266 * @param code Unique integer code.
267 * @param value Long option name string.
268 * @param description Help text.
269 * @return Reference to @c *this for chaining.
270 */
271 Argz<String> &addOptionDoubleValue(const int &code, const String &value, const String &description) {
273 a.arg_letter = code;
275 a.desc = description;
276 a.arg_name = value;
277 arg_info[code] = a;
278 return *this;
279 }
280
281 /**
282 * @brief Look up the integer code registered for a long option name.
283 * @param value Long option name (without @c --).
284 * @return The registered code, or @c -1 if not found.
285 */
286 int lookUpCode(const String &value) {
287 for(const auto &i : arg_info) {
288 if(i.second.arg_name == value) {
289 return i.second.arg_letter;
290 }
291 }
292 return -1;
293 }
294
295 /**
296 * @brief Advance the cursor and parse the next argument.
297 * @param a Output: filled with the matched option details.
298 * @return The option code on success; @c '-' for a positional argument; @c -1 when exhausted.
299 * @throws ArgException<String> On unrecognised options or missing values.
300 */
302 if(index < static_cast<int>(arg_data.args.size())) {
303 const String &type{arg_data.args[index]};
304 if(type.length() > 3 && type[0] == '-' && type[1] == '-') {
305 String name{};
306 for(size_t z = 2; z < type.length(); ++z)
307 name += type[z];
308 int code = lookUpCode(name);
309 if(code != -1) {
310 auto pos = arg_info.find(code);
311 if(pos != arg_info.end()) {
312 if(pos->second.arg_type == ArgType::ARG_DOUBLE) {
313 a = pos->second;
314 a.arg_name = name;
315 index++;
316 return code;
317 } else {
318 a = pos->second;
319 a.arg_name = name;
320 if(++index < static_cast<int>(arg_data.args.size()) && arg_data.args[index][0] != '-') {
321 a.arg_name = name;
322 a.arg_value = arg_data.args[index];
323 index++;
324 return code;
325 } else {
326 if constexpr(std::is_same<typename String::value_type, char>::value) {
327 throw ArgException<String>("Expected Value");
328 }
329 }
330 }
331 }
332 } else {
333 if constexpr(std::is_same<typename String::value_type, char>::value) {
334 String value = "Error argument: ";
335 value += name;
336 value += " switch not found";
337 throw ArgException<String>(value);
338 }
339 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
340 String value = L"Error argument: ";
341 value += name;
342 value += L" switch not found";
343 throw ArgException<String>(value);
344 }
345 }
346 } else if(type.length() == 1 && type[0] == '-') {
347 if constexpr(std::is_same<typename String::value_type, char>::value) {
348 throw ArgException<String>("Expected Value found -");
349 }
350 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
351 throw ArgException<String>(L"Expected Value found -");
352 }
353 } else if(type.length() > 1 && (type[0] == '-')) {
354 const int c{type[cindex]};
355 const auto pos{arg_info.find(c)};
356 cindex++;
357 if(cindex >= static_cast<int>(type.length())) {
358 cindex = 1;
359 index++;
360 }
361 String name_val{};
362 name_val += static_cast<typename String::value_type>(c);
363 if(pos != arg_info.end()) {
364 if(pos->second.arg_type == ArgType::ARG_SINGLE) {
365 a = pos->second;
366 a.arg_name = name_val;
367 return c;
368 } else if(pos->second.arg_type == ArgType::ARG_SINGLE_VALUE) {
369 if(index < static_cast<int>(arg_data.args.size())) {
370 const String &s{arg_data.args[index]};
371 if(s.length() > 1 && s[0] == '-' && !(s[1] >= '0' && s[1] <= '9')) {
372 if constexpr(std::is_same<typename String::value_type, char>::value) {
373 throw ArgException<String>("Expected value");
374 }
375 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
376 throw ArgException<String>(L"Expected value");
377 }
378 } else if(s.length() == 1 && s[0] == '-') {
379 if constexpr(std::is_same<typename String::value_type, char>::value) {
380 throw ArgException<String>("Expected Value found -");
381 }
382 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
383 throw ArgException<String>(L"Expected Value found -");
384 }
385 }
386 if(s.length() > 0) {
387 a = pos->second;
388 a.arg_value = s;
389 a.arg_name = name_val;
390 index++;
391 return c;
392 }
393 } else {
394 if constexpr(std::is_same<typename String::value_type, char>::value) {
395 throw ArgException<String>("Expected Value");
396 }
397 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
398 throw ArgException<String>(L"Expected Value");
399 }
400 }
401 } else {
402 if constexpr(std::is_same<typename String::value_type, char>::value) {
403 throw ArgException<String>("Invalid switch not found!");
404 }
405 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
406 throw ArgException<String>(L"Invalid switch not found!");
407 }
408 }
409 } else {
410 if constexpr(std::is_same<typename String::value_type, char>::value) {
411 String value;
412 value = "Error argument ";
413 value += static_cast<typename String::value_type>(c);
414 value += " switch not found.";
415 throw ArgException<String>(value);
416 }
417 if constexpr(std::is_same<typename String::value_type, wchar_t>::value) {
418 String value;
419 value = L"Error argument ";
420 value += static_cast<typename String::value_type>(c);
421 value += L" switch not found.";
422 throw ArgException<String>(value);
423 }
424 }
425 } else {
426 a = Argument<String>();
427 a.arg_name = String{};
429 a.arg_name = a.arg_value = arg_data.args.at(index);
430 index++;
431 return '-';
432 }
433 }
434 return -1;
435 }
436
437 /**
438 * @brief Print all registered options to any ostream-like object.
439 * @tparam T Output stream type (e.g. @c std::ostream, @c std::wostream).
440 * @param cout Destination stream.
441 */
442 template <typename T>
443 void help(T &cout) {
444 using char_type = typename std::decay<decltype(*std::declval<T>().rdbuf())>::type::char_type;
445 std::vector<Argument<String>> v;
446 std::vector<Argument<String>> v2;
447 for(const auto &i : arg_info) {
448 if(i.second.arg_type == ArgType::ARG_SINGLE || i.second.arg_type == ArgType::ARG_SINGLE_VALUE)
449 v.push_back(i.second);
450 else if(i.second.arg_type == ArgType::ARG_DOUBLE || i.second.arg_type == ArgType::ARG_DOUBLE_VALUE)
451 v2.push_back(i.second);
452 }
453 std::sort(v.begin(), v.end());
454 std::sort(v2.begin(), v2.end());
455 std::vector<Argument<String>> farg;
456 farg.reserve(v.size() + v2.size());
457 std::copy(v.begin(), v.end(), std::back_inserter(farg));
458 std::copy(v2.begin(), v2.end(), std::back_inserter(farg));
459 for(auto a = farg.begin(); a != farg.end(); ++a) {
460 if(a->arg_type == ArgType::ARG_SINGLE || a->arg_type == ArgType::ARG_SINGLE_VALUE) {
461 if constexpr(std::is_same<char_type, char>::value) {
462 String item;
463 item += static_cast<char_type>(a->arg_letter);
464 cout << "-" << std::setfill(' ') << std::setw(9) << std::left << item << "\t";
465 cout << std::setfill(' ') << std::left << std::setw(10) << a->desc;
466 cout << '\n';
467 } else if constexpr(std::is_same<char_type, wchar_t>::value) {
468 String item;
469 item += static_cast<char_type>(a->arg_letter);
470 cout << L"-" << std::setfill(L' ') << std::setw(9) << std::left << item << L"\t";
471 cout << std::setfill(L' ') << std::setw(10) << a->desc;
472 cout << L'\n';
473 }
474 } else {
475 if constexpr(std::is_same<char_type, char>::value) {
476 cout << "--";
477 cout << std::setfill(' ') << std::left << std::setw(10) << a->arg_name;
478 cout << "\t";
479 cout << std::setw(10) << a->desc;
480 cout << '\n';
481 } else if constexpr(std::is_same<char_type, wchar_t>::value) {
482 cout << L"--";
483 cout << std::setfill(L' ') << std::left << std::setw(10) << a->arg_name;
484 cout << L"\t";
485 cout << std::setw(10) << std::left << a->desc;
486 cout << L'\n';
487 }
488 }
489 }
490 }
491 /** @return Number of argv entries consumed so far. */
492 const size_t count() const { return index; }
493protected:
495 std::unordered_map<int, Argument<String>> arg_info;
496private:
497 int index = 0, cindex = 1;
498};
499
500/**
501 * @struct Arguments
502 * @brief Plain data structure returned by proc_args() with all common libmx2 CLI options.
503 */
504struct Arguments {
505 int width; ///< Viewport width in pixels (default: 1280).
506 int height; ///< Viewport height in pixels (default: 720).
507 std::string path; ///< Asset search path (default: ".").
508 bool fullscreen; ///< Whether fullscreen mode was requested.
509 std::string filename; ///< Optional input filename (@c --filename).
510 std::string texture; ///< Optional texture file path (@c --texture).
511 std::string shaderPath; ///< Optional SPV shader folder path (@c -S / @c --shader-path).
512};
513
514/**
515 * @brief Parse standard libmx2 command-line options from main()'s argv.
516 *
517 * Registers and processes the following options:
518 * | Flag | Long form | Description |
519 * |------|--------------------|----------------------------------------------|
520 * | -h | | Print help and exit |
521 * | -p | --path | Asset directory path |
522 * | -r | --resolution | Resolution as WxH (e.g. 1920x1080) |
523 * | -f | --fullscreen | Enable fullscreen |
524 * | | --filename | Input filename |
525 * | | --texture | Texture file |
526 * | -S | --shader-path | SPV shader folder (must contain index.txt) |
527 *
528 * @param argc Reference to argc from main().
529 * @param argv argv from main().
530 * @return Populated Arguments struct; on parse error, returns a default-valued struct.
531 */
532inline Arguments proc_args(int &argc, char **argv) {
533 Arguments args;
534 Argz<std::string> parser(argc, argv);
535 parser.addOptionSingle('h', "Display help message")
536 .addOptionSingleValue('p', "assets path")
537 .addOptionDoubleValue('P', "path", "assets path")
538 .addOptionSingleValue('r',"Resolution WidthxHeight")
539 .addOptionDoubleValue('R',"resolution", "Resolution WidthxHeight")
540 .addOptionSingle('f', "fullscreen")
541 .addOptionDouble('F', "fullscreen", "fullscreen")
542 .addOptionDoubleValue(256, "filename", "input filename")
543 .addOptionDoubleValue(257, "texture", "texture file (.png or .tex)")
544 .addOptionSingleValue('S', "shader SPV folder path (contains index.txt)")
545 .addOptionDoubleValue(258, "shader-path", "shader SPV folder path (contains index.txt)")
546 ;
547
549 std::string path;
550 int value = 0;
551 int tw = 1280, th = 720;
552 bool fullscreen = false;
553 std::string filename;
554 std::string texture;
555 std::string shaderPath;
556 try {
557 while((value = parser.proc(arg)) != -1) {
558 switch(value) {
559 case 256:
560 filename = arg.arg_value;
561 break;
562 case 257:
563 texture = arg.arg_value;
564 break;
565 case 'S':
566 case 258:
567 shaderPath = arg.arg_value;
568 break;
569 case 'h':
570 case 'v':
571 parser.help(std::cout);
572 exit(EXIT_SUCCESS);
573 break;
574 case 'p':
575 case 'P':
576 path = arg.arg_value;
577 break;
578 case 'r':
579 case 'R': {
580 auto pos = arg.arg_value.find("x");
581 if(pos == std::string::npos) {
582 std::cerr << "Error invalid resolution use WidthxHeight\n";
583 std::cerr.flush();
584 exit(EXIT_FAILURE);
585 }
586 std::string left, right;
587 left = arg.arg_value.substr(0, pos);
588 right = arg.arg_value.substr(pos+1);
589 tw = atoi(left.c_str());
590 th = atoi(right.c_str());
591 }
592 break;
593 case 'f':
594 case 'F':
595 fullscreen = true;
596 break;
597 }
598 }
599 } catch (const ArgException<std::string>& e) {
600 std::cerr << "mx: Argument Exception" << e.text() << std::endl;
601 args.width = 1280;
602 args.height = 720;
603 args.path = ".";
604 args.fullscreen = false;
605 return args;
606 }
607 if(path.empty()) {
608 std::cerr << "mx: No path provided trying default current directory.\n";
609 path = ".";
610 }
611 args.width = tw;
612 args.height = th;
613 args.path = path;
614 args.fullscreen = fullscreen;
615 args.filename = filename;
616 args.texture = texture;
617 args.shaderPath = shaderPath;
618 return args;
619}
620
621#endif
Arguments proc_args(int &argc, char **argv)
Parse standard libmx2 command-line options from main()'s argv.
Definition argz.hpp:532
ArgType
Discriminator for option kind used inside Argument.
Definition argz.hpp:58
@ ARG_DOUBLE_VALUE
Definition argz.hpp:58
@ ARG_SINGLE
Definition argz.hpp:58
@ ARG_SINGLE_VALUE
Definition argz.hpp:58
@ ARG_DOUBLE
Definition argz.hpp:58
@ ARG_NONE
Definition argz.hpp:58
Exception thrown by Argz::proc() on unrecognised or malformed options.
Definition argz.hpp:124
ArgException(const String &s)
Definition argz.hpp:127
String value
Definition argz.hpp:131
String text() const
Definition argz.hpp:128
ArgException()=default
Template command-line argument parser.
Definition argz.hpp:143
Argz()=default
void help(T &cout)
Print all registered options to any ostream-like object.
Definition argz.hpp:443
std::unordered_map< int, Argument< String > > arg_info
Definition argz.hpp:495
Argz< String > & addOptionSingleValue(const int &c, const String &description)
Register a short option that requires a value argument (e.g.
Definition argz.hpp:238
Argz(Argz< String > &&a)
Definition argz.hpp:169
ArgumentData< String > arg_data
Definition argz.hpp:494
Argz< String > & addOptionDouble(const int &code, const String &value, const String &description)
Register a flag-only long option (e.g.
Definition argz.hpp:254
const size_t count() const
Definition argz.hpp:492
Argz< String > & initArgs(int argc, char **argv)
Ingest argc/argv, converting to the target String type.
Definition argz.hpp:185
~Argz()=default
Argz< String > & addOptionDoubleValue(const int &code, const String &value, const String &description)
Register a long option that requires a value argument (e.g.
Definition argz.hpp:271
int proc(Argument< String > &a)
Advance the cursor and parse the next argument.
Definition argz.hpp:301
Argz< String > & operator=(Argz< String > &&a)
Definition argz.hpp:171
Argz< String > & addOptionSingle(const int &c, const String &description)
Register a flag-only short option (e.g.
Definition argz.hpp:223
Argz< String > & operator=(const Argz< String > &a)
Definition argz.hpp:156
int lookUpCode(const String &value)
Look up the integer code registered for a long option name.
Definition argz.hpp:286
Argz(const Argz< String > &a)
Definition argz.hpp:154
void reset()
Reset the internal parse cursor to the beginning of argv.
Definition argz.hpp:212
int cindex
Definition argz.hpp:497
int index
Definition argz.hpp:497
Argz(int argc, char **argv)
Construct and immediately ingest argv.
Definition argz.hpp:153
Models a string-like class with indexing, concatenation, length, and value_type.
Definition argz.hpp:44
Holds the raw argv strings converted to the target String type.
Definition argz.hpp:96
ArgumentData(ArgumentData< String > &&a)
Definition argz.hpp:110
ArgumentData< String > & operator=(ArgumentData< String > &&a)
Definition argz.hpp:111
ArgumentData(const ArgumentData< String > &a)
Definition argz.hpp:101
~ArgumentData()=default
ArgumentData()=default
ArgumentData & operator=(const ArgumentData< String > &a)
Definition argz.hpp:102
std::vector< String > args
Converted argv entries (argv[1] … argv[argc-1]).
Definition argz.hpp:97
int argc
Original argc value.
Definition argz.hpp:98
Describes a single parsed argument entry returned by Argz::proc().
Definition argz.hpp:70
int arg_letter
Short option code (e.g. 'o') or unique integer for long-only options.
Definition argz.hpp:72
~Argument()=default
Argument & operator=(const Argument< String > &a)
Definition argz.hpp:79
Argument(const Argument &a)
Definition argz.hpp:78
ArgType arg_type
Which ArgType variant this argument represents.
Definition argz.hpp:74
String arg_name
Long option name (e.g. "output").
Definition argz.hpp:71
auto operator<=>(const Argument< String > &a) const
Definition argz.hpp:87
Argument()
Definition argz.hpp:77
String arg_value
Value string supplied after the option, if any.
Definition argz.hpp:73
String desc
Human-readable description used in help output.
Definition argz.hpp:75
Plain data structure returned by proc_args() with all common libmx2 CLI options.
Definition argz.hpp:504
std::string shaderPath
Optional SPV shader folder path (-S / --shader-path).
Definition argz.hpp:511
bool fullscreen
Whether fullscreen mode was requested.
Definition argz.hpp:508
std::string texture
Optional texture file path (--texture).
Definition argz.hpp:510
int height
Viewport height in pixels (default: 720).
Definition argz.hpp:506
std::string filename
Optional input filename (--filename).
Definition argz.hpp:509
std::string path
Asset search path (default: ".").
Definition argz.hpp:507
int width
Viewport width in pixels (default: 1280).
Definition argz.hpp:505