home/src/parameters_parser.hh

137 lines
3.9 KiB
C++
Raw Normal View History

#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED
#include "exception.hh"
2017-03-07 02:12:37 +01:00
#include "hash_map.hh"
#include "meta.hh"
2015-01-06 14:40:56 +01:00
#include "array_view.hh"
#include "optional.hh"
#include "flags.hh"
2013-04-09 20:05:40 +02:00
#include "string.hh"
#include "string_utils.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(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") {}
};
struct SwitchDesc
{
bool takes_arg;
String description;
};
2017-03-07 02:12:37 +01:00
using SwitchMap = HashMap<String, SwitchDesc, MemoryDomain::Commands>;
String generate_switches_doc(const SwitchMap& opts);
struct ParameterDesc
{
enum class Flags
{
None = 0,
SwitchesOnlyAtStart = 1,
SwitchesAsPositional = 2,
};
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);
// 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;
2015-03-12 14:58:31 +01:00
struct iterator : std::iterator<std::forward_iterator_tag, String>
{
iterator(const ParametersParser& parser, size_t index)
: m_parser(parser), m_index(index) {}
2015-03-12 14:58:31 +01:00
const String& operator*() const { return m_parser[m_index]; }
const String* operator->() const { return &m_parser[m_index]; }
2013-02-27 20:51:44 +01:00
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);
2013-02-27 20:51:44 +01:00
return m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
2015-03-12 14:58:31 +01:00
return not (*this == other);
}
private:
const ParametersParser& m_parser;
size_t m_index;
};
2015-03-12 14:58:31 +01:00
// positional parameters count
size_t positional_count() const { return m_positional_indices.size(); }
// access positional parameter by index
2015-03-12 14:58:31 +01:00
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);
}
2015-03-12 14:58:31 +01:00
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, m_positional_indices.size()); }
private:
2015-01-12 14:45:44 +01:00
ParameterList m_params;
Vector<size_t, MemoryDomain::Commands> m_positional_indices;
const ParameterDesc& m_desc;
};
}
#endif // parameters_parser_hh_INCLUDED