-
Notifications
You must be signed in to change notification settings - Fork 710
/
register_manager.hh
135 lines (108 loc) · 3.75 KB
/
register_manager.hh
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
#ifndef register_manager_hh_INCLUDED
#define register_manager_hh_INCLUDED
#include "array_view.hh"
#include "completion.hh"
#include "exception.hh"
#include "utils.hh"
#include "hash_map.hh"
#include "string.hh"
#include "vector.hh"
namespace Kakoune
{
class Context;
class Register
{
public:
virtual ~Register() = default;
virtual void set(Context& context, ConstArrayView<String> values, bool restoring = false) = 0;
virtual ConstArrayView<String> get(const Context& context) = 0;
virtual const String& get_main(const Context& context, size_t main_index) = 0;
using RestoreInfo = Vector<String, MemoryDomain::Registers>;
RestoreInfo save(const Context& context);
void restore(Context& context, const RestoreInfo& info);
NestedBool& modified_hook_disabled() { return m_disable_modified_hook; }
protected:
NestedBool m_disable_modified_hook;
};
// static value register, which can be modified
class StaticRegister : public Register
{
public:
StaticRegister(String name) : m_name{std::move(name)} {}
void set(Context& context, ConstArrayView<String> values, bool) override;
ConstArrayView<String> get(const Context&) override;
const String& get_main(const Context& context, size_t main_index) override;
protected:
String m_name;
Vector<String, MemoryDomain::Registers> m_content;
};
// Dynamic value register, use it's RegisterRetriever
// to get it's value when needed.
template<typename Getter, typename Setter>
class DynamicRegister : public StaticRegister
{
public:
DynamicRegister(String name, Getter getter, Setter setter)
: StaticRegister(std::move(name)), m_getter(std::move(getter)), m_setter(std::move(setter)) {}
void set(Context& context, ConstArrayView<String> values, bool) override
{
m_setter(context, values);
}
ConstArrayView<String> get(const Context& context) override
{
m_content = m_getter(context);
return StaticRegister::get(context);
}
private:
Getter m_getter;
Setter m_setter;
};
// Register that is used to store some kind prompt history
class HistoryRegister : public StaticRegister
{
public:
using StaticRegister::StaticRegister;
void set(Context& context, ConstArrayView<String> values, bool restoring) override;
const String& get_main(const Context&, size_t) override;
};
template<typename Func>
std::unique_ptr<Register> make_dyn_reg(String name, Func func)
{
auto setter = [](Context&, ConstArrayView<String>)
{
throw runtime_error("this register is not assignable");
};
return std::make_unique<DynamicRegister<Func, decltype(setter)>>(name, std::move(func), setter);
}
template<typename Getter, typename Setter>
std::unique_ptr<Register> make_dyn_reg(String name, Getter getter, Setter setter)
{
return std::make_unique<DynamicRegister<Getter, Setter>>(name, std::move(getter), std::move(setter));
}
class NullRegister : public Register
{
public:
void set(Context&, ConstArrayView<String>, bool) override {}
ConstArrayView<String> get(const Context&) override
{
return ConstArrayView<String>(String::ms_empty);
}
const String& get_main(const Context&, size_t) override
{
return String::ms_empty;
}
};
class RegisterManager : public Singleton<RegisterManager>
{
public:
Register& operator[](StringView reg) const;
Register& operator[](Codepoint c) const;
void add_register(Codepoint c, std::unique_ptr<Register> reg);
CandidateList complete_register_name(StringView prefix, ByteCount cursor_pos) const;
auto begin() const { return m_registers.begin(); }
auto end() const { return m_registers.end(); }
protected:
HashMap<Codepoint, std::unique_ptr<Register>, MemoryDomain::Registers> m_registers;
};
}
#endif // register_manager_hh_INCLUDED