summaryrefslogtreecommitdiff
path: root/src/parameters_parser.hh
blob: 698230afce4b6d21d4228afc0c151b276870bbbe (plain)
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
#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED

#include "exception.hh"
#include "memoryview.hh"
#include "string.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 + "'") {}
};

struct wrong_argument_count : runtime_error
{
    wrong_argument_count() : runtime_error("wrong argument count") {}
};

using OptionMap = std::unordered_map<String, bool>;

// 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
{
    enum class Flags
    {
        None = 0,
        OptionsOnlyAtStart = 1,
    };
    friend constexpr Flags operator|(Flags lhs, Flags rhs)
    {
        return (Flags)((int) lhs | (int) rhs);
    }
    friend constexpr bool operator&(Flags lhs, Flags rhs)
    {
        return ((int) lhs & (int) rhs) != 0;
    }

    // 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,
                     OptionMap options,
                     Flags flags = Flags::None,
                     size_t min_positionals = 0,
                     size_t max_positionals = -1);

    // 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
        {
            return m_parser.m_params[m_parser.m_positional_indices[m_index]];
        }

        const String* operator->() const
        {
            return &m_parser.m_params[m_parser.m_positional_indices[m_index]];
        }

        iterator& operator++() { ++m_index; return *this; }

        bool operator==(const iterator& other) const
        {
            kak_assert(&m_parser == &other.m_parser);
            return m_index == other.m_index;
        }

        bool operator!=(const iterator& other) const
        {
            kak_assert(&m_parser == &other.m_parser);
            return m_index != other.m_index;
        }

        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;
    };

    // 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<size_t> m_positional_indices;
    std::unordered_map<String, bool> m_options;
};

}

#endif // parameters_parser_hh_INCLUDED