1
2
3
4
5 def main text:text [
6 local-scope
7 load-ingredients
8 open-console
9 hide-screen 0/screen
10 e:&:editor <- new-editor text, 0/left, 5/right
11 render 0/screen, e
12 show-screen 0/screen
13 wait-for-event 0/console
14 close-console
15 ]
16
17 scenario editor-renders-text-to-screen [
18 local-scope
19 assume-screen 10/width, 5/height
20 e:&:editor <- new-editor [abc], 0/left, 10/right
21 run [
22 ¦ render screen, e
23 ]
24 screen-should-contain [
25 ¦
26 ¦ . .
27 ¦ .abc .
28 ¦ . .
29 ]
30 ]
31
32 container editor [
33
34 data:&:duplex-list:char
35 top-of-screen:&:duplex-list:char
36 bottom-of-screen:&:duplex-list:char
37
38 before-cursor:&:duplex-list:char
39
40
41
42 left:num
43 right:num
44 bottom:num
45
46 cursor-row:num
47 cursor-column:num
48 ]
49
50
51
52 def new-editor s:text, left:num, right:num -> result:&:editor [
53 local-scope
54 load-ingredients
55
56 right <- subtract right, 1
57 result <- new editor:type
58
59 *result <- put *result, left:offset, left
60 *result <- put *result, right:offset, right
61
62 *result <- put *result, cursor-row:offset, 1/top
63 *result <- put *result, cursor-column:offset, left
64
65 init:&:duplex-list:char <- push 167/§, 0/tail
66 *result <- put *result, data:offset, init
67 *result <- put *result, top-of-screen:offset, init
68 *result <- put *result, before-cursor:offset, init
69 result <- insert-text result, s
70 <editor-initialization>
71 ]
72
73 def insert-text editor:&:editor, text:text -> editor:&:editor [
74 local-scope
75 load-ingredients
76
77 return-unless text
78 len:num <- length *text
79 return-unless len
80 idx:num <- copy 0
81
82 curr:&:duplex-list:char <- get *editor, data:offset
83 {
84 ¦ done?:bool <- greater-or-equal idx, len
85 ¦ break-if done?
86 ¦ c:char <- index *text, idx
87 ¦ insert c, curr
88 ¦
89 ¦ curr <- next curr
90 ¦ idx <- add idx, 1
91 ¦ loop
92 }
93 ]
94
95 scenario editor-initializes-without-data [
96 local-scope
97 assume-screen 5/width, 3/height
98 run [
99 ¦ e:&:editor <- new-editor 0/data, 2/left, 5/right
100 ¦ 2:editor/raw <- copy *e
101 ]
102 memory-should-contain [
103 ¦
104 ¦
105 ¦ 4 <- 0
106 ¦
107 ¦ 6 <- 2
108 ¦ 7 <- 4
109 ¦ 8 <- 0
110 ¦ 9 <- 1
111 ¦ 10 <- 2
112 ]
113 screen-should-contain [
114 ¦ . .
115 ¦ . .
116 ¦ . .
117 ]
118 ]
119
120
121
122
123 def render screen:&:screen, editor:&:editor -> last-row:num, last-column:num, screen:&:screen, editor:&:editor [
124 local-scope
125 load-ingredients
126 return-unless editor, 1/top, 0/left
127 left:num <- get *editor, left:offset
128 screen-height:num <- screen-height screen
129 right:num <- get *editor, right:offset
130
131 curr:&:duplex-list:char <- get *editor, top-of-screen:offset
132 prev:&:duplex-list:char <- copy curr
133 curr <- next curr
134
135 color:num <- copy 7/white
136 row:num <- copy 1/top
137 column:num <- copy left
138 cursor-row:num <- get *editor, cursor-row:offset
139 cursor-column:num <- get *editor, cursor-column:offset
140 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
141 screen <- move-cursor screen, row, column
142 {
143 ¦ +next-character
144 ¦ break-unless curr
145 ¦ off-screen?:bool <- greater-or-equal row, screen-height
146 ¦ break-if off-screen?
147 ¦
148 ¦
149 ¦
150 ¦ {
151 ¦ ¦ at-cursor-row?:bool <- equal row, cursor-row
152 ¦ ¦ break-unless at-cursor-row?
153 ¦ ¦ at-cursor?:bool <- equal column, cursor-column
154 ¦ ¦ break-unless at-cursor?
155 ¦ ¦ before-cursor <- copy prev
156 ¦ }
157 ¦ c:char <- get *curr, value:offset
158 ¦ <character-c-received>
159 ¦ {
160 ¦ ¦
161 ¦ ¦ newline?:bool <- equal c, 10/newline
162 ¦ ¦ break-unless newline?
163 ¦ ¦
164 ¦ ¦ {
165 ¦ ¦ ¦ at-cursor-row?:bool <- equal row, cursor-row
166 ¦ ¦ ¦ break-unless at-cursor-row?
167 ¦ ¦ ¦ left-of-cursor?:bool <- lesser-than column, cursor-column
168 ¦ ¦ ¦ break-unless left-of-cursor?
169 ¦ ¦ ¦ cursor-column <- copy column
170 ¦ ¦ ¦ before-cursor <- prev curr
171 ¦ ¦ }
172 ¦ ¦
173 ¦ ¦ clear-line-until screen, right
174 ¦ ¦
175 ¦ ¦ row <- add row, 1
176 ¦ ¦ column <- copy left
177 ¦ ¦ screen <- move-cursor screen, row, column
178 ¦ ¦ curr <- next curr
179 ¦ ¦ prev <- next prev
180 ¦ ¦ loop +next-character
181 ¦ }
182 ¦ {
183 ¦ ¦
184 ¦ ¦
185 ¦ ¦ at-right?:bool <- equal column, right
186 ¦ ¦ break-unless at-right?
187 ¦ ¦
188 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left
189 ¦ ¦ print screen, wrap-icon, 245/grey
190 ¦ ¦ column <- copy left
191 ¦ ¦ row <- add row, 1
192 ¦ ¦ screen <- move-cursor screen, row, column
193 ¦ ¦
194 ¦ ¦ loop +next-character
195 ¦ }
196 ¦ print screen, c, color
197 ¦ curr <- next curr
198 ¦ prev <- next prev
199 ¦ column <- add column, 1
200 ¦ loop
201 }
202
203 *editor <- put *editor, bottom-of-screen:offset, curr
204
205 {
206 ¦ at-cursor-row?:bool <- equal row, cursor-row
207 ¦ cursor-outside-line?:bool <- lesser-or-equal column, cursor-column
208 ¦ before-cursor-on-same-line?:bool <- and at-cursor-row?, cursor-outside-line?
209 ¦ above-cursor-row?:bool <- lesser-than row, cursor-row
210 ¦ before-cursor?:bool <- or before-cursor-on-same-line?, above-cursor-row?
211 ¦ break-unless before-cursor?
212 ¦ cursor-row <- copy row
213 ¦ cursor-column <- copy column
214 ¦ before-cursor <- copy prev
215 }
216 *editor <- put *editor, bottom:offset, row
217 *editor <- put *editor, cursor-row:offset, cursor-row
218 *editor <- put *editor, cursor-column:offset, cursor-column
219 *editor <- put *editor, before-cursor:offset, before-cursor
220 return row, column
221 ]
222
223 def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num -> screen:&:screen [
224 local-scope
225 load-ingredients
226
227 {
228 ¦ break-if screen
229 ¦ clear-display-from row, column, left, right
230 ¦ return
231 }
232
233 screen <- move-cursor screen, row, column
234 clear-line-until screen, right
235 clear-rest-of-screen screen, row, left, right
236 ]
237
238 def clear-rest-of-screen screen:&:screen, row:num, left:num, right:num -> screen:&:screen [
239 local-scope
240 load-ingredients
241 row <- add row, 1
242 screen <- move-cursor screen, row, left
243 screen-height:num <- screen-height screen
244 {
245 ¦ at-bottom-of-screen?:bool <- greater-or-equal row, screen-height
246 ¦ break-if at-bottom-of-screen?
247 ¦ screen <- move-cursor screen, row, left
248 ¦ clear-line-until screen, right
249 ¦ row <- add row, 1
250 ¦ loop
251 }
252 ]
253
254 scenario editor-prints-multiple-lines [
255 local-scope
256 assume-screen 5/width, 5/height
257 s:text <- new [abc
258 def]
259 e:&:editor <- new-editor s, 0/left, 5/right
260 run [
261 ¦ render screen, e
262 ]
263 screen-should-contain [
264 ¦ . .
265 ¦ .abc .
266 ¦ .def .
267 ¦ . .
268 ]
269 ]
270
271 scenario editor-handles-offsets [
272 local-scope
273 assume-screen 5/width, 5/height
274 e:&:editor <- new-editor [abc], 1/left, 5/right
275 run [
276 ¦ render screen, e
277 ]
278 screen-should-contain [
279 ¦ . .
280 ¦ . abc .
281 ¦ . .
282 ]
283 ]
284
285 scenario editor-prints-multiple-lines-at-offset [
286 local-scope
287 assume-screen 5/width, 5/height
288 s:text <- new [abc
289 def]
290 e:&:editor <- new-editor s, 1/left, 5/right
291 run [
292 ¦ render screen, e
293 ]
294 screen-should-contain [
295 ¦ . .
296 ¦ . abc .
297 ¦ . def .
298 ¦ . .
299 ]
300 ]
301
302 scenario editor-wraps-long-lines [
303 local-scope
304 assume-screen 5/width, 5/height
305 e:&:editor <- new-editor [abc def], 0/left, 5/right
306 run [
307 ¦ render screen, e
308 ]
309 screen-should-contain [
310 ¦ . .
311 ¦ .abc ↩.
312 ¦ .def .
313 ¦ . .
314 ]
315 screen-should-contain-in-color 245/grey [
316 ¦ . .
317 ¦ . ↩.
318 ¦ . .
319 ¦ . .
320 ]
321 ]
322
323 scenario editor-wraps-barely-long-lines [
324 local-scope
325 assume-screen 5/width, 5/height
326 e:&:editor <- new-editor [abcde], 0/left, 5/right
327 run [
328 ¦ render screen, e
329 ]
330
331
332 screen-should-contain [
333 ¦ . .
334 ¦ .abcd↩.
335 ¦ .e .
336 ¦ . .
337 ]
338 screen-should-contain-in-color 245/grey [
339 ¦ . .
340 ¦ . ↩.
341 ¦ . .
342 ¦ . .
343 ]
344 ]
345
346 scenario editor-with-empty-text [
347 local-scope
348 assume-screen 5/width, 5/height
349 e:&:editor <- new-editor [], 0/left, 5/right
350 run [
351 ¦ render screen, e
352 ¦ 3:num/raw <- get *e, cursor-row:offset
353 ¦ 4:num/raw <- get *e, cursor-column:offset
354 ]
355 screen-should-contain [
356 ¦ . .
357 ¦ . .
358 ¦ . .
359 ]
360 memory-should-contain [
361 ¦ 3 <- 1
362 ¦ 4 <- 0
363 ]
364 ]
365
366
367
368 scenario render-colors-comments [
369 local-scope
370 assume-screen 5/width, 5/height
371 s:text <- new [abc
372 # de
373 f]
374 e:&:editor <- new-editor s, 0/left, 5/right
375 run [
376 ¦ render screen, e
377 ]
378 screen-should-contain [
379 ¦ . .
380 ¦ .abc .
381 ¦ .# de .
382 ¦ .f .
383 ¦ . .
384 ]
385 screen-should-contain-in-color 12/lightblue, [
386 ¦ . .
387 ¦ . .
388 ¦ .# de .
389 ¦ . .
390 ¦ . .
391 ]
392 screen-should-contain-in-color 7/white, [
393 ¦ . .
394 ¦ .abc .
395 ¦ . .
396 ¦ .f .
397 ¦ . .
398 ]
399 ]
400
401 after <character-c-received> [
402 color <- get-color color, c
403 ]
404
405
406 def get-color color:num, c:char -> color:num [
407 local-scope
408 load-ingredients
409 color-is-white?:bool <- equal color, 7/white
410
411 {
412 ¦ break-unless color-is-white?
413 ¦ starting-comment?:bool <- equal c, 35/#
414 ¦ break-unless starting-comment?
415 ¦ trace 90, [app], [switch color back to blue]
416 ¦ return 12/lightblue
417 }
418
419 {
420 ¦ color-is-blue?:bool <- equal color, 12/lightblue
421 ¦ break-unless color-is-blue?
422 ¦ ending-comment?:bool <- equal c, 10/newline
423 ¦ break-unless ending-comment?
424 ¦ trace 90, [app], [switch color back to white]
425 ¦ return 7/white
426 }
427
428 {
429 ¦ break-unless color-is-white?
430 ¦ starting-assignment?:bool <- equal c, 60/<
431 ¦ break-unless starting-assignment?
432 ¦ return 1/red
433 }
434
435 {
436 ¦ color-is-red?:bool <- equal color, 1/red
437 ¦ break-unless color-is-red?
438 ¦ ending-assignment?:bool <- equal c, 32/space
439 ¦ break-unless ending-assignment?
440 ¦ return 7/white
441 }
442
443 return color
444 ]
445
446 scenario render-colors-assignment [
447 local-scope
448 assume-screen 8/width, 5/height
449 s:text <- new [abc
450 d <- e
451 f]
452 e:&:editor <- new-editor s, 0/left, 8/right
453 run [
454 ¦ render screen, e
455 ]
456 screen-should-contain [
457 ¦ . .
458 ¦ .abc .
459 ¦ .d <- e .
460 ¦ .f .
461 ¦ . .
462 ]
463 screen-should-contain-in-color 1/red, [
464 ¦ . .
465 ¦ . .
466 ¦ . <- .
467 ¦ . .
468 ¦ . .
469 ]
470 ]