2012-12-07 14:27:10 +01:00
|
|
|
#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"
|
2017-03-15 19:25:59 +01:00
|
|
|
#include "meta.hh"
|
2015-01-06 14:40:56 +01:00
|
|
|
#include "array_view.hh"
|
2015-03-14 20:16:46 +01:00
|
|
|
#include "optional.hh"
|
2018-05-30 15:23:38 +02:00
|
|
|
#include "flags.hh"
|
2013-04-09 20:05:40 +02:00
|
|
|
#include "string.hh"
|
2017-10-09 16:12:42 +02:00
|
|
|
#include "string_utils.hh"
|
2012-12-07 14:27:10 +01:00
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2015-03-09 14:48:41 +01:00
|
|
|
using ParameterList = ConstArrayView<String>;
|
2012-12-07 14:27:10 +01:00
|
|
|
|
2014-01-23 20:36:07 +01:00
|
|
|
struct parameter_error : public runtime_error
|
|
|
|
{
|
|
|
|
using runtime_error::runtime_error;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct unknown_option : public parameter_error
|
2012-12-07 14:27:10 +01:00
|
|
|
{
|
2014-10-20 20:18:38 +02:00
|
|
|
unknown_option(StringView name)
|
2015-06-01 22:15:59 +02:00
|
|
|
: parameter_error(format("unknown option '{}'", name)) {}
|
2012-12-07 14:27:10 +01:00
|
|
|
};
|
|
|
|
|
2014-01-23 20:36:07 +01:00
|
|
|
struct missing_option_value: public parameter_error
|
2012-12-07 14:27:10 +01:00
|
|
|
{
|
2014-10-20 20:18:38 +02:00
|
|
|
missing_option_value(StringView name)
|
2015-06-01 22:15:59 +02:00
|
|
|
: parameter_error(format("missing value for option '{}'", name)) {}
|
2012-12-07 14:27:10 +01:00
|
|
|
};
|
|
|
|
|
2014-01-23 20:36:07 +01:00
|
|
|
struct wrong_argument_count : public parameter_error
|
2013-03-27 14:27:12 +01:00
|
|
|
{
|
2014-01-23 20:36:07 +01:00
|
|
|
wrong_argument_count() : parameter_error("wrong argument count") {}
|
2013-03-27 14:27:12 +01:00
|
|
|
};
|
|
|
|
|
2014-02-11 23:23:44 +01:00
|
|
|
struct SwitchDesc
|
2014-02-11 23:16:17 +01:00
|
|
|
{
|
|
|
|
bool takes_arg;
|
|
|
|
String description;
|
|
|
|
};
|
|
|
|
|
2017-03-07 02:12:37 +01:00
|
|
|
using SwitchMap = HashMap<String, SwitchDesc, MemoryDomain::Commands>;
|
2014-02-11 23:16:17 +01:00
|
|
|
|
2014-02-11 23:23:44 +01:00
|
|
|
String generate_switches_doc(const SwitchMap& opts);
|
2013-03-27 14:27:12 +01:00
|
|
|
|
2014-02-08 02:02:58 +01:00
|
|
|
struct ParameterDesc
|
2012-12-07 14:27:10 +01:00
|
|
|
{
|
2013-04-02 14:22:55 +02:00
|
|
|
enum class Flags
|
|
|
|
{
|
|
|
|
None = 0,
|
2018-06-29 00:36:06 +02:00
|
|
|
SwitchesOnlyAtStart = 0b0001,
|
|
|
|
SwitchesAsPositional = 0b0010,
|
|
|
|
IgnoreUnknownSwitches = 0b0100
|
2013-04-02 14:22:55 +02:00
|
|
|
};
|
2017-03-15 18:55:34 +01:00
|
|
|
friend constexpr bool with_bit_ops(Meta::Type<Flags>) { return true; }
|
2013-04-02 14:22:55 +02:00
|
|
|
|
2014-02-11 23:23:44 +01:00
|
|
|
SwitchMap switches;
|
2014-02-08 02:02:58 +01:00
|
|
|
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
|
|
|
|
{
|
2012-12-07 14:27:10 +01:00
|
|
|
// the options defines named options, if they map to true, then
|
|
|
|
// they are understood as string options, else they are understood as
|
|
|
|
// boolean option.
|
2023-02-12 20:12:52 +01:00
|
|
|
ParametersParser(ParameterList params, const ParameterDesc& desc, bool ignore_errors = false);
|
|
|
|
|
|
|
|
enum class State {
|
|
|
|
Switch,
|
|
|
|
SwitchArgument,
|
|
|
|
Positional,
|
|
|
|
};
|
2012-12-07 14:27:10 +01:00
|
|
|
|
2015-03-14 20:16:46 +01:00
|
|
|
// 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;
|
2012-12-07 14:27:10 +01:00
|
|
|
|
2022-05-19 18:15:20 +02:00
|
|
|
struct iterator
|
2012-12-07 14:27:10 +01:00
|
|
|
{
|
2022-05-19 18:15:20 +02:00
|
|
|
using difference_type = ptrdiff_t;
|
|
|
|
using value_type = String;
|
|
|
|
using pointer = String*;
|
|
|
|
using reference = String&;
|
|
|
|
using iterator_category = std::forward_iterator_tag;
|
|
|
|
|
2012-12-07 14:27:10 +01:00
|
|
|
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]; }
|
2012-12-07 14:27:10 +01:00
|
|
|
|
2013-02-27 20:51:44 +01:00
|
|
|
iterator& operator++() { ++m_index; return *this; }
|
2014-06-12 21:03:17 +02:00
|
|
|
iterator operator++(int) { auto copy = *this; ++m_index; return copy; }
|
2012-12-07 14:27:10 +01:00
|
|
|
|
|
|
|
bool operator==(const iterator& other) const
|
|
|
|
{
|
2013-04-09 20:04:11 +02:00
|
|
|
kak_assert(&m_parser == &other.m_parser);
|
2013-02-27 20:51:44 +01:00
|
|
|
return m_index == other.m_index;
|
2012-12-07 14:27:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const iterator& other) const
|
|
|
|
{
|
2015-03-12 14:58:31 +01:00
|
|
|
return not (*this == other);
|
2012-12-07 14:27:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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(); }
|
|
|
|
|
2012-12-07 14:27:10 +01:00
|
|
|
// 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]];
|
|
|
|
}
|
|
|
|
|
2018-05-30 15:23:38 +02:00
|
|
|
ConstArrayView<String> positionals_from(size_t first) const
|
|
|
|
{
|
2019-05-10 15:46:16 +02:00
|
|
|
// kak_assert(m_desc.flags & (ParameterDesc::Flags::SwitchesOnlyAtStart | ParameterDesc::Flags::SwitchesAsPositional));
|
2018-06-28 11:48:11 +02:00
|
|
|
return m_params.subrange(first < m_positional_indices.size() ? m_positional_indices[first] : -1);
|
2018-05-30 15:23:38 +02:00
|
|
|
}
|
|
|
|
|
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()); }
|
2012-12-07 14:27:10 +01:00
|
|
|
|
2023-02-12 20:12:52 +01:00
|
|
|
State state() const { return *m_state; }
|
|
|
|
|
2012-12-07 14:27:10 +01:00
|
|
|
private:
|
2015-01-12 14:45:44 +01:00
|
|
|
ParameterList m_params;
|
|
|
|
Vector<size_t, MemoryDomain::Commands> m_positional_indices;
|
2019-05-10 15:46:16 +02:00
|
|
|
HashMap<String, StringView> m_switches;
|
2023-02-12 20:12:52 +01:00
|
|
|
Optional<State> m_state;
|
2012-12-07 14:27:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // parameters_parser_hh_INCLUDED
|