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