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 153 154 155
|
#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 "flags.hh"
#include "string.hh"
#include "string_utils.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;
enum class CompletionFlags;
using ArgCompleter = std::function<Completions (const Context&, CompletionFlags,
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
|