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 "event_manager.hh"
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
#include "client_manager.hh"
|
#include "client_manager.hh"
|
||||||
|
#include "parameters_parser.hh"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -38,188 +39,6 @@ struct wrong_argument_count : runtime_error
|
||||||
wrong_argument_count() : runtime_error("wrong argument count") {}
|
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* open_or_create(const String& filename, Context& context)
|
||||||
{
|
{
|
||||||
Buffer* buffer = create_buffer_from_file(filename);
|
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