1use prototty_render::*;
2#[cfg(feature = "serialize")]
3use serde::{Deserialize, Serialize};
4
5pub trait Wrap: private_wrap::Sealed {
6 #[doc(hidden)]
7 fn clear(&mut self);
8 #[doc(hidden)]
9 fn process_character<F: Frame, C: ColModify>(
10 &mut self,
11 character: char,
12 style: Style,
13 context: ViewContext<C>,
14 frame: &mut F,
15 );
16 #[doc(hidden)]
17 fn flush<F: Frame, C: ColModify>(&mut self, context: ViewContext<C>, frame: &mut F) {
18 let _ = context;
19 let _ = frame;
20 }
21 #[doc(hidden)]
22 fn num_lines(&self) -> usize;
23}
24
25#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
26#[derive(Debug, Clone)]
27pub struct None {
28 cursor: Coord,
29}
30
31#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
32#[derive(Debug, Clone)]
33pub struct Word {
34 cursor: Coord,
35 current_word_buffer: Vec<ViewCell>,
36}
37
38#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
39#[derive(Debug, Clone)]
40pub struct Char {
41 cursor: Coord,
42}
43
44impl None {
45 pub fn new() -> Self {
46 Self {
47 cursor: Coord::new(0, 0),
48 }
49 }
50}
51
52impl Word {
53 pub fn new() -> Self {
54 Self {
55 cursor: Coord::new(0, 0),
56 current_word_buffer: Vec::new(),
57 }
58 }
59}
60
61impl Char {
62 pub fn new() -> Self {
63 Self {
64 cursor: Coord::new(0, 0),
65 }
66 }
67}
68
69impl Default for None {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl Default for Word {
76 fn default() -> Self {
77 Self::new()
78 }
79}
80
81impl Default for Char {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl Wrap for None {
88 fn clear(&mut self) {
89 self.cursor = Coord::new(0, 0);
90 }
91 fn process_character<F: Frame, C: ColModify>(
92 &mut self,
93 character: char,
94 style: Style,
95 context: ViewContext<C>,
96 frame: &mut F,
97 ) {
98 match character {
99 '\n' => {
100 self.cursor.x = 0;
101 self.cursor.y += 1;
102 }
103 '\r' => self.cursor.x = 0,
104 other => {
105 let view_cell = ViewCell {
106 character: Some(other),
107 style,
108 };
109 frame.set_cell_relative(self.cursor, 0, view_cell, context);
110 self.cursor += Coord::new(1, 0);
111 }
112 }
113 }
114 fn num_lines(&self) -> usize {
115 self.cursor.y as usize + 1
116 }
117}
118
119impl Wrap for Word {
120 fn clear(&mut self) {
121 self.cursor = Coord::new(0, 0);
122 self.current_word_buffer.clear();
123 }
124
125 fn process_character<F: Frame, C: ColModify>(
126 &mut self,
127 character: char,
128 style: Style,
129 context: ViewContext<C>,
130 frame: &mut F,
131 ) {
132 match character {
133 '\n' => {
134 self.flush(context, frame);
135 self.cursor.x = 0;
136 self.cursor.y += 1;
137 }
138 '\r' => {
139 self.flush(context, frame);
140 self.cursor.x = 0;
141 }
142 ' ' => {
143 self.flush(context, frame);
144 if self.cursor.x != 0 {
145 let view_cell = ViewCell {
146 character: Some(' '),
147 style,
148 };
149 frame.set_cell_relative(self.cursor, 0, view_cell, context);
150 self.cursor.x += 1;
151 assert!(self.cursor.x as u32 <= context.size.width());
152 if self.cursor.x as u32 == context.size.width() {
153 self.cursor.x = 0;
154 self.cursor.y += 1;
155 }
156 }
157 }
158 other => {
159 let view_cell = ViewCell {
160 character: Some(other),
161 style,
162 };
163 self.current_word_buffer.push(view_cell);
164 assert!(self.cursor.x as u32 + self.current_word_buffer.len() as u32 <= context.size.width());
165 if self.cursor.x as u32 + self.current_word_buffer.len() as u32 == context.size.width() {
166 if self.cursor.x == 0 {
167 self.flush(context, frame);
168 } else {
169 self.cursor.x = 0;
170 self.cursor.y += 1;
171 }
172 }
173 }
174 }
175 }
176
177 fn flush<F: Frame, C: ColModify>(&mut self, context: ViewContext<C>, frame: &mut F) {
178 for view_cell in self.current_word_buffer.drain(..) {
179 frame.set_cell_relative(self.cursor, 0, view_cell, context);
180 self.cursor.x += 1;
181 }
182 assert!(self.cursor.x as u32 <= context.size.width());
183 if self.cursor.x as u32 == context.size.width() {
184 self.cursor.x = 0;
185 self.cursor.y += 1;
186 }
187 }
188
189 fn num_lines(&self) -> usize {
190 self.cursor.y as usize + 1
191 }
192}
193
194impl Wrap for Char {
195 fn clear(&mut self) {
196 self.cursor = Coord::new(0, 0);
197 }
198
199 fn process_character<F: Frame, C: ColModify>(
200 &mut self,
201 character: char,
202 style: Style,
203 context: ViewContext<C>,
204 frame: &mut F,
205 ) {
206 match character {
207 '\n' => {
208 self.cursor.x = 0;
209 self.cursor.y += 1;
210 }
211 '\r' => self.cursor.x = 0,
212 other => {
213 let view_cell = ViewCell {
214 character: Some(other),
215 style,
216 };
217 frame.set_cell_relative(self.cursor, 0, view_cell, context);
218 self.cursor += Coord::new(1, 0);
219 if self.cursor.x >= context.size.width() as i32 {
220 self.cursor.x = 0;
221 self.cursor.y += 1;
222 }
223 }
224 }
225 }
226
227 fn num_lines(&self) -> usize {
228 self.cursor.y as usize + 1
229 }
230}
231
232mod private_wrap {
233 pub trait Sealed {}
234 impl Sealed for super::None {}
235 impl Sealed for super::Word {}
236 impl Sealed for super::Char {}
237}