1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/*
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Concepts.h>
#include <AK/DeprecatedString.h>
#include <AK/Function.h>
#include <AK/Vector.h>
#include <LibMain/Main.h>
#include <stdio.h>
namespace Core {
class ArgsParser {
public:
ArgsParser();
enum class Required {
Yes,
No
};
enum class FailureBehavior {
PrintUsageAndExit,
PrintUsage,
Exit,
Ignore,
};
enum class OptionArgumentMode {
None,
Optional,
Required,
};
/// When an option is hidden.
/// If the hide mode is not None, then it's always hidden from the usage/synopsis.
enum class OptionHideMode {
None,
Markdown,
CommandLineAndMarkdown,
};
struct Option {
OptionArgumentMode argument_mode { OptionArgumentMode::Required };
char const* help_string { nullptr };
char const* long_name { nullptr };
char short_name { 0 };
char const* value_name { nullptr };
Function<bool(char const*)> accept_value;
OptionHideMode hide_mode { OptionHideMode::None };
DeprecatedString name_for_display() const
{
if (long_name)
return DeprecatedString::formatted("--{}", long_name);
return DeprecatedString::formatted("-{:c}", short_name);
}
};
struct Arg {
char const* help_string { nullptr };
char const* name { nullptr };
int min_values { 0 };
int max_values { 1 };
Function<bool(char const*)> accept_value;
};
bool parse(int argc, char* const* argv, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit);
bool parse(Main::Arguments const& arguments, FailureBehavior failure_behavior = FailureBehavior::PrintUsageAndExit)
{
if (arguments.argv == nullptr && arguments.argc == 0) {
// Allocate the data from arguments.strings instead.
Vector<DeprecatedString> strings;
Vector<char const*> data;
strings.ensure_capacity(arguments.strings.size());
data.ensure_capacity(arguments.strings.size());
for (auto& entry : arguments.strings) {
strings.append(entry);
data.append(strings.last().characters());
}
return parse(data.size(), const_cast<char* const*>(data.data()), failure_behavior);
}
return parse(arguments.argc, arguments.argv, failure_behavior);
}
// *Without* trailing newline!
void set_general_help(char const* help_string) { m_general_help = help_string; };
void set_stop_on_first_non_option(bool stop_on_first_non_option) { m_stop_on_first_non_option = stop_on_first_non_option; }
void print_usage(FILE*, char const* argv0);
void print_usage_terminal(FILE*, char const* argv0);
void print_usage_markdown(FILE*, char const* argv0);
void print_version(FILE*);
void add_option(Option&&);
void add_ignored(char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(bool& value, char const* help_string, char const* long_name, char short_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(char const*& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(DeprecatedString& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(StringView& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
template<Integral I>
void add_option(I& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(double& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(Optional<double>& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(Optional<size_t>& value, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_option(Vector<size_t>& values, char const* help_string, char const* long_name, char short_name, char const* value_name, char separator = ',', OptionHideMode hide_mode = OptionHideMode::None);
// Note: This option is being used when we expect the user to use the same option
// multiple times (e.g. "program --option=example --option=anotherexample ...").
void add_option(Vector<DeprecatedString>& values, char const* help_string, char const* long_name, char short_name, char const* value_name, OptionHideMode hide_mode = OptionHideMode::None);
void add_positional_argument(Arg&&);
void add_positional_argument(char const*& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(DeprecatedString& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(StringView& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(int& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(unsigned& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(double& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(Vector<char const*>& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(Vector<DeprecatedString>& value, char const* help_string, char const* name, Required required = Required::Yes);
void add_positional_argument(Vector<StringView>& value, char const* help_string, char const* name, Required required = Required::Yes);
private:
void autocomplete(FILE*, StringView program_name, ReadonlySpan<char const*> remaining_arguments);
Vector<Option> m_options;
Vector<Arg> m_positional_args;
bool m_show_help { false };
bool m_show_version { false };
bool m_perform_autocomplete { false };
char const* m_general_help { nullptr };
bool m_stop_on_first_non_option { false };
};
}
|