HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
command_line.hpp
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "architecture.hpp"
8#include "generator.hpp"
9
10namespace hi::inline v1 {
11
13 char32_t option;
14 std::option<std::string> argument;
15};
16
18 std::string option;
19 std::option<std::string> argument;
20};
21
23 std::string executable;
24};
25
27 std::string argument;
28};
29
30using cmdline_option = std::variant<cmline_executable, cmdline_short_option, cmdline_long_option, cmdline_argument>;
31
60template<typename It>
61generator<cmdln_option> command_line_parser(It first, It last, std::string_view options_with_arguments)
62{
63 hilet options_with_arguments_ = hi::to_u32string(options_with_arguments);
64 auto it = first;
65
66 if (it != last) {
67 co_yield cmdln_option::executable{*it};
68 ++it;
69 }
70
71 char32_t short_option_name = 0;
72 for (; it != last; ++it) {
73 if (short_option_name) {
74 // Add the argument to the option.
75 co_yield cmdln_short_option{short_option_name, *it};
76 short_option_name = 0;
77
78 } else if (*it == "--") {
79 break;
80
81 } else if (it->starts_with("--")) {
82 // Long-option
83 hilet eq_index = it->find('=');
84 if (eq_index == std::string::npos) {
85 // Long-option without argument
86 co_yield cmdln_long_option{it->substr(2), {}};
87
88 } else {
89 // Long-option with argument in same token.
90 hi_assert(eq_index >= 2);
91 hilet name_length = eq_index - 2;
92 co_yield cmdln_long_option(it->substr(2, name_length), it->substr(eq_index + 1));
93 }
94
95 } else if (it.front() == '-' or it.front() == '+') {
96 // List of short-options.
97 // Short options are processed as UTF-32 units.
98 hilet token = to_u32string(*it);
99 hilet first_c = std::next(begin(token));
100 hilet last_c = end(token);
101 negative = it.front() == '+';
102
103 for (auto jt = first_c; jt != last_c; ++jt) {
104 hilet c = *jt;
105 auto name = hi::to_string(std::u32string(1, c));
106
107 if (options_with_arguments_.find(c) == std::u32string::npos) {
108 // Option without argument
109 co_yield cmdln_short_option(c, {});
110
111 } else if (std::next(jt) == last) {
112 // Option with the argument in the next token.
113 short_option_name = c;
114
115 } else {
116 // Option with argument, where the argument is inside this token
117 auto argument = hi::to_string(std::u32string(std::next(jt), last_c));
118 co_yield cmdln_short_option(c, std::move(argument));
119 break;
120 }
121 }
122
123 } else {
124 // Anything not looking like an option is a non-option
125 co_yield cmdln_non_option{*it};
126 }
127 }
128
129 // All tokens after double hyphen '--' are non-options.
130 for (; it != last; ++it) {
131 co_yield cmdln_non_option{*it};
132 }
133
134 if (short_option_name) {
135 throw parse_error("Missing argument for option -{}", short_option_name);
136 }
137}
138
140public:
141 char32_t short_option;
142 std::string long_option;
143 std::string argument_name;
144 std::string description;
145 hi::notifier<void(std::string_view argument)> notifier;
146
166 constexpr command_line_option(std::string_view option_help)
167 {
168 auto it = begin(option_help);
169 hilet last = end(option_help);
170 }
171
172 static char32_t parse_short_option(std::string_view::iterator &it, std::string_view::iterator last)
173 {
174 if (it == last || *it != '-') {
175 throw parse_error("Expecting '-'");
176 }
177
178 ++it;
179
180 if (it == last) {
181 throw parse_error("Missing character after '-'");
182 }
183 if (*it == '-') {
184 return 0;
185 }
186 }
187};
188
192public:
193#if HI_OPERATING_SYSTEM == HI_OS_WINDOWS
194 void parse();
195#else
196 void parse(int argc, char **argv);
197#endif
198
199 template<typename... Args>
200 command_line_option &add_option(Args &&...args) noexcept
201 {
202 return _options.emplace(std::forward<Args>(args)...);
203 }
204
205private:
207};
208
209} // namespace hi::inline v1
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:87
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
constexpr std::string to_string(std::u32string_view rhs) noexcept
Conversion from UTF-32 to UTF-8.
Definition to_string.hpp:215
constexpr std::u32string to_u32string(std::u32string_view rhs) noexcept
Identity conversion from UTF-32 to UTF-32.
Definition to_string.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
generator< cmdln_option > command_line_parser(It first, It last, std::string_view options_with_arguments)
A POSIX command line parser.
Definition command_line.hpp:61
Definition command_line.hpp:12
Definition command_line.hpp:17
Definition command_line.hpp:22
Definition command_line.hpp:26
Definition command_line.hpp:139
constexpr command_line_option(std::string_view option_help)
Syntax:
Definition command_line.hpp:166
Command line parser.
Definition command_line.hpp:191
A return value for a generator-function.
Definition generator.hpp:28
A notifier which can be used to call a set of registered callbacks.
Definition notifier.hpp:26
T move(T... args)
T next(T... args)