11#![ deny( missing_docs) ]
22use std:: io:: { Result , Write } ;
3+ use std:: ops:: Index ;
34
45use anathema_geometry:: Size ;
56use anathema_widgets:: Style ;
@@ -11,7 +12,7 @@ use super::LocalPos;
1112use super :: style:: write_style;
1213
1314#[ derive( Debug , Copy , Clone , PartialEq ) ]
14- pub ( crate ) struct Cell {
15+ pub struct Cell {
1516 pub ( crate ) style : Style ,
1617 pub ( crate ) state : CellState ,
1718}
@@ -49,7 +50,7 @@ impl Cell {
4950}
5051
5152/// Represent the state of a cell inside a [`Buffer`].
52- #[ derive( Debug , Copy , Clone , PartialEq ) ]
53+ #[ derive( Copy , Clone , PartialEq ) ]
5354pub ( crate ) enum CellState {
5455 /// Empty
5556 Empty ,
@@ -60,6 +61,17 @@ pub(crate) enum CellState {
6061 Continuation ,
6162}
6263
64+ impl std:: fmt:: Debug for CellState {
65+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
66+ match self {
67+ CellState :: Empty => write ! ( f, "<E>" ) ,
68+ CellState :: Occupied ( Glyph :: Single ( glyph, _width) ) => write ! ( f, "{glyph}" ) ,
69+ CellState :: Occupied ( Glyph :: Cluster ( index, width) ) => write ! ( f, "<C{index:?},{width}>" ) ,
70+ CellState :: Continuation => write ! ( f, "<C>" ) ,
71+ }
72+ }
73+ }
74+
6375/// A buffer contains a list of cells representing characters that can be rendered.
6476/// This doesn't necessarily have to be `stdout`, it can be anything that implements
6577/// [`std::io::Write`]
@@ -163,7 +175,7 @@ impl Buffer {
163175 return None ;
164176 }
165177
166- let index = self . index ( pos ) ;
178+ let index = pos . to_index ( self . size . width ) ;
167179 let cell = self . inner . get ( index) ?;
168180 match & cell. state {
169181 CellState :: Occupied ( c) => Some ( ( c, & cell. style ) ) ,
@@ -177,44 +189,28 @@ impl Buffer {
177189 return None ;
178190 }
179191
180- let index = self . index ( pos ) ;
192+ let index = pos . to_index ( self . size . width ) ;
181193 let cell = self . inner . get_mut ( index) ?;
182194 match & mut cell. state {
183195 CellState :: Occupied ( c) => Some ( ( c, & mut cell. style ) ) ,
184196 _ => None ,
185197 }
186198 }
187199
188- /// An iterator over all the rows in the buffer
189- pub fn rows ( & mut self ) -> impl Iterator < Item = impl Iterator < Item = Option < ( Glyph , Style ) > > + ' _ > {
190- self . cell_lines ( ) . map ( |chunk| {
191- chunk. iter ( ) . map ( |cell| match cell. state {
192- CellState :: Occupied ( c) => Some ( ( c, cell. style ) ) ,
193- _ => None ,
194- } )
195- } )
196- }
197-
198200 pub ( super ) fn reset_cell ( & mut self , pos : LocalPos ) {
199201 let index = pos. to_index ( self . size . width ) ;
200202 self . inner [ index] = Cell :: empty ( ) ;
201203 }
202204
203- fn index ( & self , pos : LocalPos ) -> usize {
204- ( pos. y * self . size . width + pos. x ) as usize
205- }
206-
207205 fn put ( & mut self , mut cell : Cell , pos : LocalPos ) {
208206 let index = pos. to_index ( self . size . width ) ;
209207
210208 if let CellState :: Occupied ( c) = cell. state {
211209 // If this is a unicode char that is wider than one cell,
212210 // add a continuation cell if it fits, this way if we overwrite it
213211 // we can set the continuation cell to `Empty`.
214- if pos. x < self . size . width {
215- if let 2 .. = c. width ( ) {
216- self . put ( Cell :: continuation ( cell. style ) , LocalPos :: new ( pos. x + 1 , pos. y ) ) ;
217- }
212+ if pos. x < self . size . width && c. width ( ) >= 2 {
213+ self . put ( Cell :: continuation ( cell. style ) , LocalPos :: new ( pos. x + 1 , pos. y ) ) ;
218214 }
219215 }
220216
@@ -239,21 +235,33 @@ impl Buffer {
239235 }
240236 }
241237
242- fn cell_lines ( & mut self ) -> impl Iterator < Item = & mut [ Cell ] > {
238+ pub ( super ) fn cell_lines ( & mut self ) -> impl Iterator < Item = & mut [ Cell ] > {
243239 self . inner . chunks_mut ( self . size . width as usize )
244240 }
245241}
246242
243+ impl Index < ( usize , usize ) > for Buffer {
244+ type Output = Cell ;
245+
246+ fn index ( & self , pos : ( usize , usize ) ) -> & Self :: Output {
247+ let pos = LocalPos :: from ( pos) ;
248+ let index = pos. to_index ( self . size . width ) ;
249+ & self . inner [ index]
250+ }
251+ }
252+
247253#[ derive( Debug , Clone , Copy , PartialEq ) ]
248254pub ( crate ) enum Change {
249255 Remove ,
256+ Continuation ,
250257 Insert ( Glyph ) ,
251258}
252259
253260impl Change {
254261 fn width ( self ) -> usize {
255262 match self {
256263 Self :: Remove => 1 ,
264+ Self :: Continuation => 0 ,
257265 Self :: Insert ( c) => c. width ( ) ,
258266 }
259267 }
@@ -274,7 +282,7 @@ pub(crate) fn diff(
274282
275283 let change = match new_cell. state {
276284 CellState :: Empty => Change :: Remove ,
277- CellState :: Continuation => continue ,
285+ CellState :: Continuation => Change :: Continuation ,
278286 CellState :: Occupied ( c) => Change :: Insert ( c) ,
279287 } ;
280288
@@ -336,6 +344,7 @@ pub(crate) fn draw_changes(
336344 }
337345 }
338346 } ,
347+ Change :: Continuation => ( ) , // Don't write on continuation, just advance
339348 Change :: Remove => {
340349 w. queue ( Print ( ' ' ) ) ?;
341350 }
0 commit comments