-
Notifications
You must be signed in to change notification settings - Fork 730
/
Copy pathparameters_parser.hh
152 lines (121 loc) · 4.35 KB
/
parameters_parser.hh
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
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED
#include "exception.hh"
#include "hash_map.hh"
#include "meta.hh"
#include "array_view.hh"
#include "optional.hh"
#include "string.hh"
#include "format.hh"
#include <functional>
namespace Kakoune
{
using ParameterList = ConstArrayView<String>;
struct parameter_error : public runtime_error
{
using runtime_error::runtime_error;
};
struct unknown_option : public parameter_error
{
unknown_option(StringView name)
: parameter_error(format("unknown option '{}'", name)) {}
};
struct missing_option_value: public parameter_error
{
missing_option_value(StringView name)
: parameter_error(format("missing value for option '{}'", name)) {}
};
struct wrong_argument_count : public parameter_error
{
wrong_argument_count() : parameter_error("wrong argument count") {}
};
class Context;
struct Completions;
using ArgCompleter = std::function<Completions (const Context&, StringView, ByteCount)>;
struct SwitchDesc
{
Optional<ArgCompleter> arg_completer;
String description;
};
using SwitchMap = HashMap<String, SwitchDesc, MemoryDomain::Commands>;
String generate_switches_doc(const SwitchMap& opts);
struct ParameterDesc
{
enum class Flags
{
None = 0,
SwitchesOnlyAtStart = 0b0001,
SwitchesAsPositional = 0b0010,
IgnoreUnknownSwitches = 0b0100
};
friend constexpr bool with_bit_ops(Meta::Type<Flags>) { return true; }
SwitchMap switches;
Flags flags = Flags::None;
size_t min_positionals = 0;
size_t max_positionals = -1;
};
// ParametersParser provides tools to parse command parameters.
// There are 3 types of parameters:
// * unnamed options, which are accessed by position (ignoring named ones)
// * named boolean options, which are enabled using '-name' syntax
// * named string options, which are defined using '-name value' syntax
struct ParametersParser
{
// the options defines named options, if they map to true, then
// they are understood as string options, else they are understood as
// boolean option.
ParametersParser(ParameterList params, const ParameterDesc& desc, bool ignore_errors = false);
enum class State {
Switch,
SwitchArgument,
Positional,
};
// Return a valid optional if the switch was given, with
// a non empty StringView value if the switch took an argument.
Optional<StringView> get_switch(StringView name) const;
struct iterator
{
using difference_type = ptrdiff_t;
using value_type = String;
using pointer = String*;
using reference = String&;
using iterator_category = std::forward_iterator_tag;
iterator(const ParametersParser& parser, size_t index)
: m_parser(parser), m_index(index) {}
const String& operator*() const { return m_parser[m_index]; }
const String* operator->() const { return &m_parser[m_index]; }
iterator& operator++() { ++m_index; return *this; }
iterator operator++(int) { auto copy = *this; ++m_index; return copy; }
bool operator==(const iterator& other) const
{
kak_assert(&m_parser == &other.m_parser);
return m_index == other.m_index;
}
private:
const ParametersParser& m_parser;
size_t m_index;
};
// positional parameters count
size_t positional_count() const { return m_positional_indices.size(); }
// access positional parameter by index
const String& operator[] (size_t index) const
{
kak_assert(index < positional_count());
return m_params[m_positional_indices[index]];
}
ConstArrayView<String> positionals_from(size_t first) const
{
// kak_assert(m_desc.flags & (ParameterDesc::Flags::SwitchesOnlyAtStart | ParameterDesc::Flags::SwitchesAsPositional));
return m_params.subrange(first < m_positional_indices.size() ? m_positional_indices[first] : -1);
}
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, m_positional_indices.size()); }
State state() const { return *m_state; }
private:
ParameterList m_params;
Vector<size_t, MemoryDomain::Commands> m_positional_indices;
HashMap<String, StringView> m_switches;
Optional<State> m_state;
};
}
#endif // parameters_parser_hh_INCLUDED