extract ParametersParser to it's own file
This commit is contained in:
parent
d25bafa95d
commit
158f5a5c84
183
src/commands.cc
183
src/commands.cc
|
@ -17,6 +17,7 @@
|
|||
#include "event_manager.hh"
|
||||
#include "color_registry.hh"
|
||||
#include "client_manager.hh"
|
||||
#include "parameters_parser.hh"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -38,188 +39,6 @@ struct wrong_argument_count : runtime_error
|
|||
wrong_argument_count() : runtime_error("wrong argument count") {}
|
||||
};
|
||||
|
||||
struct unknown_option : public runtime_error
|
||||
{
|
||||
unknown_option(const String& name)
|
||||
: runtime_error("unknown option '" + name + "'") {}
|
||||
};
|
||||
|
||||
struct missing_option_value: public runtime_error
|
||||
{
|
||||
missing_option_value(const String& name)
|
||||
: runtime_error("missing value for option '" + name + "'") {}
|
||||
};
|
||||
|
||||
// ParameterParser 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(const CommandParameters& params,
|
||||
std::unordered_map<String, bool> options)
|
||||
: m_params(params), m_positional(params.size(), true), m_options(options)
|
||||
{
|
||||
for (size_t i = 0; i < params.size(); ++i)
|
||||
{
|
||||
if (params[i][0] == '-')
|
||||
{
|
||||
auto it = options.find(params[i].substr(1_byte));
|
||||
if (it == options.end())
|
||||
throw unknown_option(params[i]);
|
||||
|
||||
if (it->second)
|
||||
{
|
||||
if (i + 1 == params.size() or params[i+1][0] == '-')
|
||||
throw missing_option_value(params[i]);
|
||||
|
||||
m_positional[i+1] = false;
|
||||
}
|
||||
m_positional[i] = false;
|
||||
}
|
||||
|
||||
// all options following -- are positional
|
||||
if (params[i] == "--")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a named option (either string or boolean) is specified
|
||||
bool has_option(const String& name) const
|
||||
{
|
||||
assert(m_options.find(name) != m_options.end());
|
||||
for (auto& param : m_params)
|
||||
{
|
||||
if (param[0] == '-' and param.substr(1_byte) == name)
|
||||
return true;
|
||||
|
||||
if (param == "--")
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// get a string option value, returns an empty string if the option
|
||||
// is not defined
|
||||
const String& option_value(const String& name) const
|
||||
{
|
||||
auto it = m_options.find(name);
|
||||
assert(it != m_options.end());
|
||||
assert(it->second == true);
|
||||
|
||||
for (size_t i = 0; i < m_params.size(); ++i)
|
||||
{
|
||||
if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
|
||||
return m_params[i+1];
|
||||
|
||||
if (m_params[i] == "--")
|
||||
break;
|
||||
}
|
||||
static String empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
size_t positional_count() const
|
||||
{
|
||||
size_t res = 0;
|
||||
for (bool positional : m_positional)
|
||||
{
|
||||
if (positional)
|
||||
++res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct iterator
|
||||
{
|
||||
public:
|
||||
typedef String value_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef size_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
iterator(const ParametersParser& parser, size_t index)
|
||||
: m_parser(parser), m_index(index) {}
|
||||
|
||||
const String& operator*() const
|
||||
{
|
||||
assert(m_parser.m_positional[m_index]);
|
||||
return m_parser.m_params[m_index];
|
||||
}
|
||||
|
||||
const String* operator->() const
|
||||
{
|
||||
assert(m_parser.m_positional[m_index]);
|
||||
return &m_parser.m_params[m_index];
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
while (m_index < m_parser.m_positional.size() and
|
||||
not m_parser.m_positional[++m_index]) {}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& other) const
|
||||
{
|
||||
return &m_parser == &other.m_parser and m_index == other.m_index;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const
|
||||
{
|
||||
return &m_parser != &other.m_parser or m_index != other.m_index;
|
||||
}
|
||||
|
||||
bool operator<(const iterator& other) const
|
||||
{
|
||||
assert(&m_parser == &other.m_parser);
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
private:
|
||||
const ParametersParser& m_parser;
|
||||
size_t m_index;
|
||||
};
|
||||
|
||||
// positional parameter begin
|
||||
iterator begin() const
|
||||
{
|
||||
int index = 0;
|
||||
while (index < m_positional.size() and not m_positional[index])
|
||||
++index;
|
||||
return iterator(*this, index);
|
||||
}
|
||||
|
||||
// positional parameter end
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(*this, m_params.size());
|
||||
}
|
||||
|
||||
// access positional parameter by index
|
||||
const String& operator[] (size_t index) const
|
||||
{
|
||||
assert(index < positional_count());
|
||||
iterator it = begin();
|
||||
while (index)
|
||||
{
|
||||
++it;
|
||||
--index;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
private:
|
||||
const CommandParameters& m_params;
|
||||
std::vector<bool> m_positional;
|
||||
std::unordered_map<String, bool> m_options;
|
||||
};
|
||||
|
||||
Buffer* open_or_create(const String& filename, Context& context)
|
||||
{
|
||||
Buffer* buffer = create_buffer_from_file(filename);
|
||||
|
|
103
src/parameters_parser.cc
Normal file
103
src/parameters_parser.cc
Normal file
|
@ -0,0 +1,103 @@
|
|||
#include "parameters_parser.hh"
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
ParametersParser::ParametersParser(const ParameterList& params,
|
||||
std::unordered_map<String, bool> options)
|
||||
: m_params(params), m_positional(params.size(), true),
|
||||
m_options(std::move(options))
|
||||
{
|
||||
for (size_t i = 0; i < params.size(); ++i)
|
||||
{
|
||||
if (params[i][0] == '-')
|
||||
{
|
||||
auto it = m_options.find(params[i].substr(1_byte));
|
||||
if (it == m_options.end())
|
||||
throw unknown_option(params[i]);
|
||||
|
||||
if (it->second)
|
||||
{
|
||||
if (i + 1 == params.size() or params[i+1][0] == '-')
|
||||
throw missing_option_value(params[i]);
|
||||
|
||||
m_positional[i+1] = false;
|
||||
}
|
||||
m_positional[i] = false;
|
||||
}
|
||||
|
||||
// all options following -- are positional
|
||||
if (params[i] == "--")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParametersParser::has_option(const String& name) const
|
||||
{
|
||||
assert(m_options.find(name) != m_options.end());
|
||||
for (auto& param : m_params)
|
||||
{
|
||||
if (param[0] == '-' and param.substr(1_byte) == name)
|
||||
return true;
|
||||
|
||||
if (param == "--")
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const String& ParametersParser::option_value(const String& name) const
|
||||
{
|
||||
auto it = m_options.find(name);
|
||||
assert(it != m_options.end());
|
||||
assert(it->second == true);
|
||||
|
||||
for (size_t i = 0; i < m_params.size(); ++i)
|
||||
{
|
||||
if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
|
||||
return m_params[i+1];
|
||||
|
||||
if (m_params[i] == "--")
|
||||
break;
|
||||
}
|
||||
static String empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
size_t ParametersParser::positional_count() const
|
||||
{
|
||||
size_t res = 0;
|
||||
for (bool positional : m_positional)
|
||||
{
|
||||
if (positional)
|
||||
++res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const String& ParametersParser::operator[] (size_t index) const
|
||||
{
|
||||
assert(index < positional_count());
|
||||
iterator it = begin();
|
||||
while (index)
|
||||
{
|
||||
++it;
|
||||
--index;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
ParametersParser::iterator ParametersParser::begin() const
|
||||
{
|
||||
int index = 0;
|
||||
while (index < m_positional.size() and not m_positional[index])
|
||||
++index;
|
||||
return iterator(*this, index);
|
||||
}
|
||||
|
||||
ParametersParser::iterator ParametersParser::end() const
|
||||
{
|
||||
return iterator(*this, m_params.size());
|
||||
}
|
||||
|
||||
}
|
118
src/parameters_parser.hh
Normal file
118
src/parameters_parser.hh
Normal file
|
@ -0,0 +1,118 @@
|
|||
#ifndef parameters_parser_hh_INCLUDED
|
||||
#define parameters_parser_hh_INCLUDED
|
||||
|
||||
#include "string.hh"
|
||||
#include "memoryview.hh"
|
||||
#include "exception.hh"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
using ParameterList = memoryview<String>;
|
||||
|
||||
struct unknown_option : public runtime_error
|
||||
{
|
||||
unknown_option(const String& name)
|
||||
: runtime_error("unknown option '" + name + "'") {}
|
||||
};
|
||||
|
||||
struct missing_option_value: public runtime_error
|
||||
{
|
||||
missing_option_value(const String& name)
|
||||
: runtime_error("missing value for option '" + name + "'") {}
|
||||
};
|
||||
|
||||
// ParameterParser 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(const ParameterList& params,
|
||||
std::unordered_map<String, bool> options);
|
||||
|
||||
// check if a named option (either string or boolean) is specified
|
||||
bool has_option(const String& name) const;
|
||||
|
||||
// get a string option value, returns an empty string if the option
|
||||
// is not defined
|
||||
const String& option_value(const String& name) const;
|
||||
|
||||
// positional parameters count
|
||||
size_t positional_count() const;
|
||||
|
||||
struct iterator
|
||||
{
|
||||
public:
|
||||
typedef String value_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef size_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
iterator(const ParametersParser& parser, size_t index)
|
||||
: m_parser(parser), m_index(index) {}
|
||||
|
||||
const String& operator*() const
|
||||
{
|
||||
assert(m_parser.m_positional[m_index]);
|
||||
return m_parser.m_params[m_index];
|
||||
}
|
||||
|
||||
const String* operator->() const
|
||||
{
|
||||
assert(m_parser.m_positional[m_index]);
|
||||
return &m_parser.m_params[m_index];
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
while (m_index < m_parser.m_positional.size() and
|
||||
not m_parser.m_positional[++m_index]) {}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& other) const
|
||||
{
|
||||
return &m_parser == &other.m_parser and m_index == other.m_index;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const
|
||||
{
|
||||
return &m_parser != &other.m_parser or m_index != other.m_index;
|
||||
}
|
||||
|
||||
bool operator<(const iterator& other) const
|
||||
{
|
||||
assert(&m_parser == &other.m_parser);
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
private:
|
||||
const ParametersParser& m_parser;
|
||||
size_t m_index;
|
||||
};
|
||||
|
||||
// access positional parameter by index
|
||||
const String& operator[] (size_t index) const;
|
||||
// positional parameter begin
|
||||
iterator begin() const;
|
||||
// positional parameter end
|
||||
iterator end() const;
|
||||
|
||||
private:
|
||||
ParameterList m_params;
|
||||
std::vector<bool> m_positional;
|
||||
std::unordered_map<String, bool> m_options;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // parameters_parser_hh_INCLUDED
|
||||
|
Loading…
Reference in New Issue
Block a user