1 #ifndef display_buffer_hh_INCLUDED
2 #define display_buffer_hh_INCLUDED
3 
4 #include "face.hh"
5 #include "hash.hh"
6 #include "coord.hh"
7 #include "range.hh"
8 #include "string.hh"
9 #include "vector.hh"
10 #include "hash_map.hh"
11 
12 namespace Kakoune
13 {
14 
15 class Buffer;
16 using BufferRange = Range<BufferCoord>;
17 
18 class BufferIterator;
19 // Return a buffer iterator to the coord, tolerating one past end of line coords
20 BufferIterator get_iterator(const Buffer& buffer, BufferCoord coord);
21 
22 struct DisplayAtom : public UseMemoryDomain<MemoryDomain::Display>
23 {
24 public:
25     enum Type { Range, ReplacedRange, Text };
26 
DisplayAtomKakoune::DisplayAtom27     DisplayAtom(const Buffer& buffer, BufferCoord begin, BufferCoord end)
28         : m_type(Range), m_buffer(&buffer), m_range{begin, end} {}
29 
DisplayAtomKakoune::DisplayAtom30     DisplayAtom(String str, Face face)
31         : face(face), m_type(Text), m_text(std::move(str)) {}
32 
DisplayAtomKakoune::DisplayAtom33     explicit DisplayAtom(String str)
34         : DisplayAtom(std::move(str), Face{}) {}
35 
36     StringView content() const;
37     ColumnCount length() const;
38 
beginKakoune::DisplayAtom39     const BufferCoord& begin() const
40     {
41         kak_assert(has_buffer_range());
42         return m_range.begin;
43     }
44 
endKakoune::DisplayAtom45     const BufferCoord& end() const
46     {
47         kak_assert(has_buffer_range());
48         return m_range.end;
49     }
50 
replaceKakoune::DisplayAtom51     void replace(String text)
52     {
53         kak_assert(m_type == Range);
54         m_type = ReplacedRange;
55         m_text = std::move(text);
56     }
57 
replaceKakoune::DisplayAtom58     void replace(const BufferRange& range)
59     {
60         kak_assert(m_type == Text);
61         m_type = ReplacedRange;
62         m_range = range;
63     }
64 
has_buffer_rangeKakoune::DisplayAtom65     bool has_buffer_range() const
66     {
67         return m_type == Range or m_type == ReplacedRange;
68     }
69 
bufferKakoune::DisplayAtom70     const Buffer& buffer() const { kak_assert(m_buffer); return *m_buffer; }
71 
typeKakoune::DisplayAtom72     Type type() const { return m_type; }
73 
74     void trim_begin(ColumnCount count);
75     void trim_end(ColumnCount count);
76 
operator ==Kakoune::DisplayAtom77     bool operator==(const DisplayAtom& other) const
78     {
79         return face == other.face and type() == other.type() and
80                content() == other.content();
81     }
82 
83 public:
84     Face face;
85 
86 private:
87     friend class DisplayLine;
88 
89     Type m_type;
90 
91     const Buffer* m_buffer = nullptr;
92     BufferRange m_range;
93     String m_text;
94 };
95 
96 using AtomList = Vector<DisplayAtom, MemoryDomain::Display>;
97 
98 class DisplayLine : public UseMemoryDomain<MemoryDomain::Display>
99 {
100 public:
101     using iterator = AtomList::iterator;
102     using const_iterator = AtomList::const_iterator;
103     using value_type = AtomList::value_type;
104 
105     DisplayLine() = default;
106     DisplayLine(AtomList atoms);
DisplayLine(String str,Face face)107     DisplayLine(String str, Face face)
108     { push_back({ std::move(str), face }); }
109 
begin()110     iterator begin() { return m_atoms.begin(); }
end()111     iterator end() { return m_atoms.end(); }
112 
begin() const113     const_iterator begin() const { return m_atoms.begin(); }
end() const114     const_iterator end() const { return m_atoms.end(); }
115 
atoms() const116     const AtomList& atoms() const { return m_atoms; }
117 
118     ColumnCount length() const;
range() const119     const BufferRange& range() const { return m_range; }
120 
121     // Split atom pointed by it at buffer coord pos,
122     // returns an iterator to the first atom
123     iterator split(iterator it, BufferCoord pos);
124 
125     // Split atom pointed by it at its pos column,
126     // returns an iterator to the first atom
127     iterator split(iterator it, ColumnCount pos);
128 
129     iterator split(BufferCoord pos);
130 
131     iterator insert(iterator it, DisplayAtom atom);
132 
133     template<typename It>
insert(iterator it,It beg,It end)134     iterator insert(iterator it, It beg, It end)
135     {
136         auto res = m_atoms.insert(it, beg, end);
137         compute_range();
138         return res;
139     }
140 
141     iterator erase(iterator beg, iterator end);
142     void push_back(DisplayAtom atom);
143 
144     // remove first_col from the begining of the line, and make sure
145     // the line is less that col_count character
146     bool trim(ColumnCount first_col, ColumnCount col_count);
147 
148     // Merge together consecutive atoms sharing the same display attributes
149     void optimize();
150 private:
151     void compute_range();
152     BufferRange m_range = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN } };
153     AtomList  m_atoms;
154 };
155 
156 using DisplayLineList = Vector<DisplayLine>;
157 class FaceRegistry;
158 
159 DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const HashMap<String, DisplayLine>& builtins = {});
160 DisplayLineList parse_display_line_list(StringView content, const FaceRegistry& faces, const HashMap<String, DisplayLine>& builtins = {});
161 
162 class DisplayBuffer : public UseMemoryDomain<MemoryDomain::Display>
163 {
164 public:
DisplayBuffer()165     DisplayBuffer() {}
166 
lines()167     DisplayLineList& lines() { return m_lines; }
lines() const168     const DisplayLineList& lines() const { return m_lines; }
169 
170     // returns the smallest BufferRange which contains every DisplayAtoms
range() const171     const BufferRange& range() const { return m_range; }
172     void compute_range();
173 
174     // Optimize all lines, set DisplayLine::optimize
175     void optimize();
176 
set_timestamp(size_t timestamp)177     void set_timestamp(size_t timestamp) { m_timestamp = timestamp; }
timestamp() const178     size_t timestamp() const { return m_timestamp; }
179 
180 private:
181     DisplayLineList m_lines;
182     BufferRange m_range;
183     size_t m_timestamp = -1;
184 };
185 
186 }
187 
188 #endif // display_buffer_hh_INCLUDED
189