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
|
#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED
#include "exception.hh"
#include "id_map.hh"
#include "array_view.hh"
#include "flags.hh"
#include "optional.hh"
#include "string.hh"
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("unknown option '" + name + "'") {}
};
struct missing_option_value: public parameter_error
{
missing_option_value(StringView name)
: parameter_error("missing value for option '" + name + "'") {}
};
struct wrong_argument_count : public parameter_error
{
wrong_argument_count() : parameter_error("wrong argument count") {}
};
struct SwitchDesc
{
bool takes_arg;
String description;
};
using SwitchMap = IdMap<SwitchDesc, MemoryDomain::Commands>;
String generate_switches_doc(const SwitchMap& opts);
struct ParameterDesc
{
enum class Flags
{
None = 0,
SwitchesOnlyAtStart = 1,
SwitchesAsPositional = 2,
};
ParameterDesc() = default;
ParameterDesc(SwitchMap switches, Flags flags = Flags::None,
size_t min_positionals = 0, size_t max_positionals = -1)
: switches(std::move(switches)), flags(flags),
min_positionals(min_positionals), max_positionals(max_positionals) {}
SwitchMap switches;
Flags flags = Flags::None;
size_t min_positionals = 0;
size_t max_positionals = -1;
};
template<> struct WithBitOps<ParameterDesc::Flags> : std::true_type {};
// 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);
// 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 : std::iterator<std::forward_iterator_tag, String>
{
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;
}
bool operator!=(const iterator& other) const
{
return not (*this == other);
}
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]];
}
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, m_positional_indices.size()); }
private:
ParameterList m_params;
Vector<size_t, MemoryDomain::Commands> m_positional_indices;
const ParameterDesc& m_desc;
};
}
#endif // parameters_parser_hh_INCLUDED
|