-
Notifications
You must be signed in to change notification settings - Fork 715
/
display_buffer.hh
204 lines (154 loc) · 5.94 KB
/
display_buffer.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#ifndef display_buffer_hh_INCLUDED
#define display_buffer_hh_INCLUDED
#include "face.hh"
#include "coord.hh"
#include "range.hh"
#include "string.hh"
#include "vector.hh"
#include "hash_map.hh"
#include <algorithm>
namespace Kakoune
{
class Buffer;
using BufferRange = Range<BufferCoord>;
class BufferIterator;
// Return a buffer iterator to the coord, tolerating one past end of line coords
BufferIterator get_iterator(const Buffer& buffer, BufferCoord coord);
struct DisplayAtom : public UseMemoryDomain<MemoryDomain::Display>
{
public:
enum Type { Range, ReplacedRange, Text };
DisplayAtom(const Buffer& buffer, BufferRange range, Face face = {})
: face(face), m_type(Range), m_buffer(&buffer), m_range{range} {}
DisplayAtom(const Buffer& buffer, BufferRange range, String str, Face face = {})
: face(face), m_type(ReplacedRange), m_buffer(&buffer), m_range{range}, m_text{std::move(str)} {}
DisplayAtom(String str, Face face)
: face(face), m_type(Text), m_text(std::move(str)) {}
explicit DisplayAtom(String str)
: DisplayAtom(std::move(str), Face{}) {}
StringView content() const;
ColumnCount length() const;
bool empty() const;
const BufferCoord& begin() const
{
kak_assert(has_buffer_range());
return m_range.begin;
}
const BufferCoord& end() const
{
kak_assert(has_buffer_range());
return m_range.end;
}
void replace(String text)
{
if (m_type == Range)
m_type = ReplacedRange;
m_text = std::move(text);
}
void replace(const BufferRange& range)
{
kak_assert(m_type == Text);
m_type = ReplacedRange;
m_range = range;
}
bool has_buffer_range() const
{
return m_type == Range or m_type == ReplacedRange;
}
const Buffer& buffer() const { kak_assert(m_buffer); return *m_buffer; }
Type type() const { return m_type; }
ColumnCount trim_begin(ColumnCount count);
ColumnCount trim_end_to_length(ColumnCount count);
bool operator==(const DisplayAtom& other) const
{
return face == other.face and type() == other.type() and
content() == other.content();
}
public:
Face face;
private:
friend class DisplayLine;
Type m_type;
const Buffer* m_buffer = nullptr;
BufferRange m_range;
String m_text;
};
using AtomList = Vector<DisplayAtom, MemoryDomain::Display>;
class DisplayLine : public UseMemoryDomain<MemoryDomain::Display>
{
public:
using iterator = AtomList::iterator;
using const_iterator = AtomList::const_iterator;
using value_type = AtomList::value_type;
DisplayLine() = default;
DisplayLine(AtomList atoms);
DisplayLine(String str, Face face)
{ push_back({ std::move(str), face }); }
iterator begin() { return m_atoms.begin(); }
iterator end() { return m_atoms.end(); }
const_iterator begin() const { return m_atoms.begin(); }
const_iterator end() const { return m_atoms.end(); }
const AtomList& atoms() const { return m_atoms; }
ColumnCount length() const;
const BufferRange& range() const { return m_range; }
// Split atom pointed by it at buffer coord pos,
// returns an iterator to the first atom
iterator split(iterator it, BufferCoord pos);
// Split atom pointed by it at its pos column,
// returns an iterator to the first atom
iterator split(iterator it, ColumnCount pos);
iterator split(BufferCoord pos);
iterator insert(iterator it, DisplayAtom atom);
template<typename It>
iterator insert(iterator pos, It beg, It end)
{
auto has_buffer_range = [](const DisplayAtom& atom) { return atom.has_buffer_range(); };
auto had_range = any_of(*this, has_buffer_range);
if (auto first = std::find_if(beg, end, has_buffer_range); first != end)
{
auto& last = *std::find_if(std::reverse_iterator(end), std::reverse_iterator(first), has_buffer_range);
m_range.begin = had_range ? std::min(m_range.begin, (*first).begin()) : (*first).begin();
m_range.end = had_range ? std::max(m_range.end, last.end()) : last.end();
}
return m_atoms.insert(pos, beg, end);
}
DisplayLine extract(iterator beg, iterator end);
iterator erase(iterator beg, iterator end);
DisplayAtom& push_back(DisplayAtom atom);
// remove front from the begining of the line, and make sure
// the line is less that col_count character
bool trim(ColumnCount front, ColumnCount col_count);
// remove front from the begining of the line + first_col, and make sure
// the line is less that col_count character
bool trim_from(ColumnCount first_col, ColumnCount front, ColumnCount col_count);
// Merge together consecutive atoms sharing the same display attributes
void optimize();
private:
void compute_range();
BufferRange m_range = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN } };
AtomList m_atoms;
};
using DisplayLineList = Vector<DisplayLine>;
class FaceRegistry;
DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const HashMap<String, DisplayLine>& builtins = {});
DisplayLineList parse_display_line_list(StringView content, const FaceRegistry& faces, const HashMap<String, DisplayLine>& builtins = {});
class DisplayBuffer : public UseMemoryDomain<MemoryDomain::Display>
{
public:
DisplayBuffer() {}
DisplayLineList& lines() { return m_lines; }
const DisplayLineList& lines() const { return m_lines; }
// returns the smallest BufferRange which contains every DisplayAtoms
const BufferRange& range() const { return m_range; }
void compute_range();
// Optimize all lines, set DisplayLine::optimize
void optimize();
void set_timestamp(size_t timestamp) { m_timestamp = timestamp; }
size_t timestamp() const { return m_timestamp; }
private:
DisplayLineList m_lines;
BufferRange m_range;
size_t m_timestamp = -1;
};
}
#endif // display_buffer_hh_INCLUDED