1
2
3
4
5
6
7 scenario editor-inserts-two-spaces-on-tab [
8 local-scope
9 assume-screen 10/width, 5/height
10 s:text <- new [ab
11 cd]
12 e:&:editor <- new-editor s, 0/left, 5/right
13 render screen, e
14 $clear-trace
15 assume-console [
16 ¦ press tab
17 ]
18 run [
19 ¦ editor-event-loop screen, console, e
20 ]
21 screen-should-contain [
22 ¦ . .
23 ¦ . ab .
24 ¦ .cd .
25 ]
26
27 check-trace-count-for-label-lesser-than 10, [print-character]
28 ]
29
30 scenario editor-inserts-two-spaces-and-wraps-line-on-tab [
31 local-scope
32 assume-screen 10/width, 5/height
33 s:text <- new [abcd]
34 e:&:editor <- new-editor s, 0/left, 5/right
35 render screen, e
36 $clear-trace
37 assume-console [
38 ¦ press tab
39 ]
40 run [
41 ¦ editor-event-loop screen, console, e
42 ]
43 screen-should-contain [
44 ¦ . .
45 ¦ . ab↩ .
46 ¦ .cd .
47 ]
48
49 check-trace-count-for-label-greater-than 10, [print-character]
50 ]
51
52 after <handle-special-character> [
53 {
54 ¦ tab?:bool <- equal c, 9/tab
55 ¦ break-unless tab?
56 ¦ <insert-character-begin>
57 ¦
58 ¦
59 ¦ insert-at-cursor editor, 32/space, screen
60 ¦ go-render? <- insert-at-cursor editor, 32/space, screen
61 ¦ <insert-character-end>
62 ¦ return
63 }
64 ]
65
66
67
68 scenario editor-handles-backspace-key [
69 local-scope
70 assume-screen 10/width, 5/height
71 e:&:editor <- new-editor [abc], 0/left, 10/right
72 editor-render screen, e
73 $clear-trace
74 assume-console [
75 ¦ left-click 1, 1
76 ¦ press backspace
77 ]
78 run [
79 ¦ editor-event-loop screen, console, e
80 ¦ 4:num/raw <- get *e, cursor-row:offset
81 ¦ 5:num/raw <- get *e, cursor-column:offset
82 ]
83 screen-should-contain [
84 ¦ . .
85 ¦ .bc .
86 ¦ .╌╌╌╌╌╌╌╌╌╌.
87 ¦ . .
88 ]
89 memory-should-contain [
90 ¦ 4 <- 1
91 ¦ 5 <- 0
92 ]
93 check-trace-count-for-label 3, [print-character]
94 ]
95
96 after <handle-special-character> [
97 {
98 ¦ delete-previous-character?:bool <- equal c, 8/backspace
99 ¦ break-unless delete-previous-character?
100 ¦ <backspace-character-begin>
101 ¦ go-render?:bool, backspaced-cell:&:duplex-list:char <- delete-before-cursor editor, screen
102 ¦ <backspace-character-end>
103 ¦ return
104 }
105 ]
106
107
108
109
110 def delete-before-cursor editor:&:editor, screen:&:screen -> go-render?:bool, backspaced-cell:&:duplex-list:char, editor:&:editor, screen:&:screen [
111 local-scope
112 load-ingredients
113 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
114 data:&:duplex-list:char <- get *editor, data:offset
115
116 prev:&:duplex-list:char <- prev before-cursor
117 return-unless prev, 0/no-more-render, 0/nothing-deleted
118 trace 10, [app], [delete-before-cursor]
119 original-row:num <- get *editor, cursor-row:offset
120 scroll?:bool <- move-cursor-coordinates-left editor
121 backspaced-cell:&:duplex-list:char <- copy before-cursor
122 data <- remove before-cursor, data
123 before-cursor <- copy prev
124 *editor <- put *editor, before-cursor:offset, before-cursor
125 return-if scroll?, 1/go-render
126 screen-width:num <- screen-width screen
127 cursor-row:num <- get *editor, cursor-row:offset
128 cursor-column:num <- get *editor, cursor-column:offset
129
130 same-row?:bool <- equal cursor-row, original-row
131 return-unless same-row?, 1/go-render
132 left:num <- get *editor, left:offset
133 right:num <- get *editor, right:offset
134 curr:&:duplex-list:char <- next before-cursor
135 screen <- move-cursor screen, cursor-row, cursor-column
136 curr-column:num <- copy cursor-column
137 {
138 ¦
139 ¦ at-right?:bool <- greater-or-equal curr-column, right
140 ¦ return-if at-right?, 1/go-render
141 ¦ break-unless curr
142 ¦
143 ¦ currc:char <- get *curr, value:offset
144 ¦ at-newline?:bool <- equal currc, 10/newline
145 ¦ break-if at-newline?
146 ¦ screen <- print screen, currc
147 ¦ curr-column <- add curr-column, 1
148 ¦ curr <- next curr
149 ¦ loop
150 }
151
152 space:char <- copy 32/space
153 screen <- print screen, space
154 go-render? <- copy 0/false
155 ]
156
157 def move-cursor-coordinates-left editor:&:editor -> go-render?:bool, editor:&:editor [
158 local-scope
159 load-ingredients
160 go-render?:bool <- copy 0/false
161 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
162 cursor-row:num <- get *editor, cursor-row:offset
163 cursor-column:num <- get *editor, cursor-column:offset
164 left:num <- get *editor, left:offset
165
166 {
167 ¦ at-left-margin?:bool <- equal cursor-column, left
168 ¦ break-if at-left-margin?
169 ¦ trace 10, [app], [decrementing cursor column]
170 ¦ cursor-column <- subtract cursor-column, 1
171 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
172 ¦ return
173 }
174
175 top-of-screen?:bool <- equal cursor-row, 1
176 {
177 ¦ break-if top-of-screen?
178 ¦ cursor-row <- subtract cursor-row, 1
179 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
180 }
181 {
182 ¦ break-unless top-of-screen?
183 ¦ <scroll-up>
184 ¦ go-render? <- copy 1/true
185 }
186 {
187 ¦
188 ¦ previous-character:char <- get *before-cursor, value:offset
189 ¦ previous-character-is-newline?:bool <- equal previous-character, 10/newline
190 ¦ break-unless previous-character-is-newline?
191 ¦
192 ¦ trace 10, [app], [switching to previous line]
193 ¦ d:&:duplex-list:char <- get *editor, data:offset
194 ¦ end-of-line:num <- previous-line-length before-cursor, d
195 ¦ right:num <- get *editor, right:offset
196 ¦ width:num <- subtract right, left
197 ¦ wrap?:bool <- greater-than end-of-line, width
198 ¦ {
199 ¦ ¦ break-unless wrap?
200 ¦ ¦ _, column-offset:num <- divide-with-remainder end-of-line, width
201 ¦ ¦ cursor-column <- add left, column-offset
202 ¦ ¦ *editor <- put *editor, cursor-column:offset, cursor-column
203 ¦ }
204 ¦ {
205 ¦ ¦ break-if wrap?
206 ¦ ¦ cursor-column <- add left, end-of-line
207 ¦ ¦ *editor <- put *editor, cursor-column:offset, cursor-column
208 ¦ }
209 ¦ return
210 }
211
212 trace 10, [app], [wrapping to previous line]
213 right:num <- get *editor, right:offset
214 cursor-column <- subtract right, 1
215 *editor <- put *editor, cursor-column:offset, cursor-column
216 ]
217
218
219
220 def previous-line-length curr:&:duplex-list:char, start:&:duplex-list:char -> result:num [
221 local-scope
222 load-ingredients
223 result:num <- copy 0
224 return-unless curr
225 at-start?:bool <- equal curr, start
226 return-if at-start?
227 {
228 ¦ curr <- prev curr
229 ¦ break-unless curr
230 ¦ at-start?:bool <- equal curr, start
231 ¦ break-if at-start?
232 ¦ c:char <- get *curr, value:offset
233 ¦ at-newline?:bool <- equal c, 10/newline
234 ¦ break-if at-newline?
235 ¦ result <- add result, 1
236 ¦ loop
237 }
238 ]
239
240 scenario editor-clears-last-line-on-backspace [
241 local-scope
242 assume-screen 10/width, 5/height
243 s:text <- new [ab
244 cd]
245 e:&:editor <- new-editor s, 0/left, 10/right
246 assume-console [
247 ¦ left-click 2, 0
248 ¦ press backspace
249 ]
250 run [
251 ¦ editor-event-loop screen, console, e
252 ¦ 4:num/raw <- get *e, cursor-row:offset
253 ¦ 5:num/raw <- get *e, cursor-column:offset
254 ]
255 screen-should-contain [
256 ¦ . .
257 ¦ .abcd .
258 ¦ .╌╌╌╌╌╌╌╌╌╌.
259 ¦ . .
260 ]
261 memory-should-contain [
262 ¦ 4 <- 1
263 ¦ 5 <- 2
264 ]
265 ]
266
267 scenario editor-joins-and-wraps-lines-on-backspace [
268 local-scope
269 assume-screen 10/width, 5/height
270
271 s:text <- new [abc def
272 ghi jkl]
273 e:&:editor <- new-editor s, 0/left, 10/right
274 editor-render screen, e
275 $clear-trace
276
277 assume-console [
278 ¦ left-click 2, 0
279 ¦ press backspace
280 ]
281 run [
282 ¦ editor-event-loop screen, console, e
283 ]
284
285 screen-should-contain [
286 ¦ . .
287 ¦ .abc defgh↩.
288 ¦ .i jkl .
289 ¦ .╌╌╌╌╌╌╌╌╌╌.
290 ¦ . .
291 ]
292 ]
293
294 scenario editor-wraps-long-lines-on-backspace [
295 local-scope
296 assume-screen 10/width, 5/height
297
298 e:&:editor <- new-editor [abc def ghij], 0/left, 8/right
299 editor-render screen, e
300
301 screen-should-contain [
302 ¦ . .
303 ¦ .abc def↩ .
304 ¦ . ghij .
305 ¦ .╌╌╌╌╌╌╌╌ .
306 ]
307 $clear-trace
308
309 assume-console [
310 ¦ left-click 1, 4
311 ¦ press backspace
312 ]
313 run [
314 ¦ editor-event-loop screen, console, e
315 ]
316
317 screen-should-contain [
318 ¦ . .
319 ¦ .abcdef ↩ .
320 ¦ .ghij .
321 ¦ .╌╌╌╌╌╌╌╌ .
322 ¦ . .
323 ]
324 ]
325
326
327
328 scenario editor-handles-delete-key [
329 local-scope
330 assume-screen 10/width, 5/height
331 e:&:editor <- new-editor [abc], 0/left, 10/right
332 editor-render screen, e
333 $clear-trace
334 assume-console [
335 ¦ press delete
336 ]
337 run [
338 ¦ editor-event-loop screen, console, e
339 ]
340 screen-should-contain [
341 ¦ . .
342 ¦ .bc .
343 ¦ .╌╌╌╌╌╌╌╌╌╌.
344 ¦ . .
345 ]
346 check-trace-count-for-label 3, [print-character]
347 $clear-trace
348 assume-console [
349 ¦ press delete
350 ]
351 run [
352 ¦ editor-event-loop screen, console, e
353 ]
354 screen-should-contain [
355 ¦ . .
356 ¦ .c .
357 ¦ .╌╌╌╌╌╌╌╌╌╌.
358 ¦ . .
359 ]
360 check-trace-count-for-label 2, [print-character]
361 ]
362
363 after <handle-special-key> [
364 {
365 ¦ delete-next-character?:bool <- equal k, 65522/delete
366 ¦ break-unless delete-next-character?
367 ¦ <delete-character-begin>
368 ¦ go-render?:bool, deleted-cell:&:duplex-list:char <- delete-at-cursor editor, screen
369 ¦ <delete-character-end>
370 ¦ return
371 }
372 ]
373
374 def delete-at-cursor editor:&:editor, screen:&:screen -> go-render?:bool, deleted-cell:&:duplex-list:char, editor:&:editor, screen:&:screen [
375 local-scope
376 load-ingredients
377 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
378 data:&:duplex-list:char <- get *editor, data:offset
379 deleted-cell:&:duplex-list:char <- next before-cursor
380 return-unless deleted-cell, 0/don't-render
381 currc:char <- get *deleted-cell, value:offset
382 data <- remove deleted-cell, data
383 deleted-newline?:bool <- equal currc, 10/newline
384 return-if deleted-newline?, 1/go-render
385
386 curr:&:duplex-list:char <- next before-cursor
387 cursor-row:num <- get *editor, cursor-row:offset
388 cursor-column:num <- get *editor, cursor-column:offset
389 screen <- move-cursor screen, cursor-row, cursor-column
390 curr-column:num <- copy cursor-column
391 screen-width:num <- screen-width screen
392 {
393 ¦
394 ¦ at-right?:bool <- greater-or-equal curr-column, screen-width
395 ¦ return-if at-right?, 1/go-render
396 ¦ break-unless curr
397 ¦
398 ¦ currc:char <- get *curr, value:offset
399 ¦ at-newline?:bool <- equal currc, 10/newline
400 ¦ break-if at-newline?
401 ¦ screen <- print screen, currc
402 ¦ curr-column <- add curr-column, 1
403 ¦ curr <- next curr
404 ¦ loop
405 }
406
407 space:char <- copy 32/space
408 screen <- print screen, space
409 go-render? <- copy 0/false
410 ]
411
412
413
414 scenario editor-moves-cursor-right-with-key [
415 local-scope
416 assume-screen 10/width, 5/height
417 e:&:editor <- new-editor [abc], 0/left, 10/right
418 editor-render screen, e
419 $clear-trace
420 assume-console [
421 ¦ press right-arrow
422 ¦ type [0]
423 ]
424 run [
425 ¦ editor-event-loop screen, console, e
426 ]
427 screen-should-contain [
428 ¦ . .
429 ¦ .a0bc .
430 ¦ .╌╌╌╌╌╌╌╌╌╌.
431 ¦ . .
432 ]
433 check-trace-count-for-label 3, [print-character]
434 ]
435
436 after <handle-special-key> [
437 {
438 ¦ move-to-next-character?:bool <- equal k, 65514/right-arrow
439 ¦ break-unless move-to-next-character?
440 ¦
441 ¦ next-cursor:&:duplex-list:char <- next before-cursor
442 ¦ break-unless next-cursor
443 ¦
444 ¦ <move-cursor-begin>
445 ¦ before-cursor <- copy next-cursor
446 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
447 ¦ go-render?:bool <- move-cursor-coordinates-right editor, screen-height
448 ¦ screen <- move-cursor screen, cursor-row, cursor-column
449 ¦ undo-coalesce-tag:num <- copy 2/right-arrow
450 ¦ <move-cursor-end>
451 ¦ return
452 }
453 ]
454
455 def move-cursor-coordinates-right editor:&:editor, screen-height:num -> go-render?:bool, editor:&:editor [
456 local-scope
457 load-ingredients
458 before-cursor:&:duplex-list:char <- get *editor before-cursor:offset
459 cursor-row:num <- get *editor, cursor-row:offset
460 cursor-column:num <- get *editor, cursor-column:offset
461 left:num <- get *editor, left:offset
462 right:num <- get *editor, right:offset
463
464 {
465 ¦ old-cursor-character:char <- get *before-cursor, value:offset
466 ¦ was-at-newline?:bool <- equal old-cursor-character, 10/newline
467 ¦ break-unless was-at-newline?
468 ¦ cursor-row <- add cursor-row, 1
469 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
470 ¦ cursor-column <- copy left
471 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
472 ¦ below-screen?:bool <- greater-or-equal cursor-row, screen-height
473 ¦ return-unless below-screen?, 0/don't-render
474 ¦ <scroll-down>
475 ¦ cursor-row <- subtract cursor-row, 1
476 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
477 ¦ return 1/go-render
478 }
479
480 {
481 ¦
482 ¦ wrap-column:num <- subtract right, 1
483 ¦ at-wrap?:bool <- equal cursor-column, wrap-column
484 ¦ break-unless at-wrap?
485 ¦
486 ¦ next:&:duplex-list:char <- next before-cursor
487 ¦ break-unless next
488 ¦ next-character:char <- get *next, value:offset
489 ¦ newline?:bool <- equal next-character, 10/newline
490 ¦ break-if newline?
491 ¦ cursor-row <- add cursor-row, 1
492 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
493 ¦ cursor-column <- copy left
494 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
495 ¦ below-screen?:bool <- greater-or-equal cursor-row, screen-height
496 ¦ return-unless below-screen?, 0/no-more-render
497 ¦ <scroll-down>
498 ¦ cursor-row <- subtract cursor-row, 1
499 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
500 ¦ return 1/go-render
501 }
502
503 cursor-column <- add cursor-column, 1
504 *editor <- put *editor, cursor-column:offset, cursor-column
505 go-render? <- copy 0/false
506 ]
507
508 scenario editor-moves-cursor-to-next-line-with-right-arrow [
509 local-scope
510 assume-screen 10/width, 5/height
511 s:text <- new [abc
512 d]
513 e:&:editor <- new-editor s, 0/left, 10/right
514 editor-render screen, e
515 $clear-trace
516
517 assume-console [
518 ¦ press right-arrow
519 ¦ press right-arrow
520 ¦ press right-arrow
521 ¦ press right-arrow
522 ]
523 run [
524 ¦ editor-event-loop screen, console, e
525 ]
526 check-trace-count-for-label 0, [print-character]
527
528 assume-console [
529 ¦ type [0]
530 ]
531 run [
532 ¦ editor-event-loop screen, console, e
533 ]
534 screen-should-contain [
535 ¦ . .
536 ¦ .abc .
537 ¦ .0d .
538 ¦ .╌╌╌╌╌╌╌╌╌╌.
539 ¦ . .
540 ]
541 check-trace-count-for-label 2, [print-character]
542 ]
543
544 scenario editor-moves-cursor-to-next-line-with-right-arrow-2 [
545 local-scope
546 assume-screen 10/width, 5/height
547 s:text <- new [abc
548 d]
549 e:&:editor <- new-editor s, 1/left, 10/right
550 editor-render screen, e
551 assume-console [
552 ¦ press right-arrow
553 ¦ press right-arrow
554 ¦ press right-arrow
555 ¦ press right-arrow
556 ¦ type [0]
557 ]
558 run [
559 ¦ editor-event-loop screen, console, e
560 ]
561 screen-should-contain [
562 ¦ . .
563 ¦ . abc .
564 ¦ . 0d .
565 ¦ . ╌╌╌╌╌╌╌╌╌.
566 ¦ . .
567 ]
568 ]
569
570 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
571 local-scope
572 assume-screen 10/width, 5/height
573 e:&:editor <- new-editor [abcdef], 0/left, 5/right
574 editor-render screen, e
575 $clear-trace
576 assume-console [
577 ¦ left-click 1, 3
578 ¦ press right-arrow
579 ]
580 run [
581 ¦ editor-event-loop screen, console, e
582 ¦ 3:num/raw <- get *e, cursor-row:offset
583 ¦ 4:num/raw <- get *e, cursor-column:offset
584 ]
585 screen-should-contain [
586 ¦ . .
587 ¦ .abcd↩ .
588 ¦ .ef .
589 ¦ .╌╌╌╌╌ .
590 ¦ . .
591 ]
592 memory-should-contain [
593 ¦ 3 <- 2
594 ¦ 4 <- 0
595 ]
596 check-trace-count-for-label 0, [print-character]
597 ]
598
599 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
600 local-scope
601 assume-screen 10/width, 5/height
602
603 e:&:editor <- new-editor [abcde], 0/left, 5/right
604 editor-render screen, e
605 $clear-trace
606
607 assume-console [
608 ¦ left-click 1, 3
609 ¦ press right-arrow
610 ]
611 run [
612 ¦ editor-event-loop screen, console, e
613 ¦ 3:num/raw <- get *e, cursor-row:offset
614 ¦ 4:num/raw <- get *e, cursor-column:offset
615 ]
616 memory-should-contain [
617 ¦ 3 <- 2
618 ¦ 4 <- 0
619 ]
620
621 assume-console [
622 ¦ press right-arrow
623 ]
624 run [
625 ¦ editor-event-loop screen, console, e
626 ¦ 3:num/raw <- get *e, cursor-row:offset
627 ¦ 4:num/raw <- get *e, cursor-column:offset
628 ]
629 memory-should-contain [
630 ¦ 3 <- 2
631 ¦ 4 <- 1
632 ]
633 check-trace-count-for-label 0, [print-character]
634 ]
635
636 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [
637 local-scope
638 assume-screen 10/width, 5/height
639 e:&:editor <- new-editor [abcdef], 1/left, 6/right
640 editor-render screen, e
641 $clear-trace
642 assume-console [
643 ¦ left-click 1, 4
644 ¦ press right-arrow
645 ]
646 run [
647 ¦ editor-event-loop screen, console, e
648 ¦ 3:num/raw <- get *e, cursor-row:offset
649 ¦ 4:num/raw <- get *e, cursor-column:offset
650 ]
651 screen-should-contain [
652 ¦ . .
653 ¦ . abcd↩ .
654 ¦ . ef .
655 ¦ . ╌╌╌╌╌ .
656 ¦ . .
657 ]
658 memory-should-contain [
659 ¦ 3 <- 2
660 ¦ 4 <- 1
661 ]
662 check-trace-count-for-label 0, [print-character]
663 ]
664
665 scenario editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [
666 local-scope
667 assume-screen 10/width, 5/height
668 s:text <- new [abc
669 d]
670 e:&:editor <- new-editor s, 0/left, 10/right
671 editor-render screen, e
672 $clear-trace
673
674 assume-console [
675 ¦ left-click 1, 3
676 ¦ press right-arrow
677 ¦ type [0]
678 ]
679 run [
680 ¦ editor-event-loop screen, console, e
681 ]
682
683 screen-should-contain [
684 ¦ . .
685 ¦ .abc .
686 ¦ .0d .
687 ¦ .╌╌╌╌╌╌╌╌╌╌.
688 ¦ . .
689 ]
690 check-trace-count-for-label 2, [print-character]
691 ]
692
693
694
695
696
697 scenario editor-moves-cursor-left-with-key [
698 local-scope
699 assume-screen 10/width, 5/height
700 e:&:editor <- new-editor [abc], 0/left, 10/right
701 editor-render screen, e
702 $clear-trace
703 assume-console [
704 ¦ left-click 1, 2
705 ¦ press left-arrow
706 ¦ type [0]
707 ]
708 run [
709 ¦ editor-event-loop screen, console, e
710 ]
711 screen-should-contain [
712 ¦ . .
713 ¦ .a0bc .
714 ¦ .╌╌╌╌╌╌╌╌╌╌.
715 ¦ . .
716 ]
717 check-trace-count-for-label 3, [print-character]
718 ]
719
720 after <handle-special-key> [
721 {
722 ¦ move-to-previous-character?:bool <- equal k, 65515/left-arrow
723 ¦ break-unless move-to-previous-character?
724 ¦ trace 10, [app], [left arrow]
725 ¦
726 ¦ prev:&:duplex-list:char <- prev before-cursor
727 ¦ return-unless prev, 0/don't-render
728 ¦ <move-cursor-begin>
729 ¦ go-render? <- move-cursor-coordinates-left editor
730 ¦ before-cursor <- copy prev
731 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
732 ¦ undo-coalesce-tag:num <- copy 1/left-arrow
733 ¦ <move-cursor-end>
734 ¦ return
735 }
736 ]
737
738 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [
739 local-scope
740 assume-screen 10/width, 5/height
741
742 s:text <- new [abc
743 d]
744 e:&:editor <- new-editor s, 0/left, 10/right
745 editor-render screen, e
746 $clear-trace
747
748 assume-console [
749 ¦ left-click 2, 0
750 ¦ press left-arrow
751 ]
752 run [
753 ¦ editor-event-loop screen, console, e
754 ¦ 3:num/raw <- get *e, cursor-row:offset
755 ¦ 4:num/raw <- get *e, cursor-column:offset
756 ]
757 memory-should-contain [
758 ¦ 3 <- 1
759 ¦ 4 <- 3
760 ]
761 check-trace-count-for-label 0, [print-character]
762 ]
763
764 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [
765 local-scope
766 assume-screen 10/width, 5/height
767
768 s:text <- new [abc
769 def
770 g]
771 e:&:editor <- new-editor s:text, 0/left, 10/right
772 editor-render screen, e
773 $clear-trace
774
775
776 assume-console [
777 ¦ left-click 3, 0
778 ¦ press left-arrow
779 ¦ type [0]
780 ]
781 run [
782 ¦ editor-event-loop screen, console, e
783 ]
784 screen-should-contain [
785 ¦ . .
786 ¦ .abc .
787 ¦ .def0 .
788 ¦ .g .
789 ¦ .╌╌╌╌╌╌╌╌╌╌.
790 ]
791 check-trace-count-for-label 1, [print-character]
792 ]
793
794 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [
795 local-scope
796 assume-screen 10/width, 5/height
797 s:text <- new [abc
798 def
799 g]
800 e:&:editor <- new-editor s, 0/left, 10/right
801 editor-render screen, e
802 $clear-trace
803
804 assume-console [
805 ¦ left-click 1, 0
806 ¦ press left-arrow
807 ¦ type [0]
808 ]
809 run [
810 ¦ editor-event-loop screen, console, e
811 ]
812
813 screen-should-contain [
814 ¦ . .
815 ¦ .0abc .
816 ¦ .def .
817 ¦ .g .
818 ¦ .╌╌╌╌╌╌╌╌╌╌.
819 ]
820 check-trace-count-for-label 4, [print-character]
821 ]
822
823 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [
824 local-scope
825 assume-screen 10/width, 5/height
826
827 s:text <- new [abc
828
829 d]
830 e:&:editor <- new-editor s, 0/left, 10/right
831 editor-render screen, e:&:editor
832 $clear-trace
833
834 assume-console [
835 ¦ left-click 3, 0
836 ¦ press left-arrow
837 ¦ type [0]
838 ]
839 run [
840 ¦ editor-event-loop screen, console, e
841 ]
842 screen-should-contain [
843 ¦ . .
844 ¦ .abc .
845 ¦ .0 .
846 ¦ .d .
847 ¦ .╌╌╌╌╌╌╌╌╌╌.
848 ]
849 check-trace-count-for-label 1, [print-character]
850 ]
851
852 scenario editor-moves-across-screen-lines-across-wrap-with-left-arrow [
853 local-scope
854 assume-screen 10/width, 5/height
855
856 e:&:editor <- new-editor [abcdef], 0/left, 5/right
857 editor-render screen, e
858 $clear-trace
859 screen-should-contain [
860 ¦ . .
861 ¦ .abcd↩ .
862 ¦ .ef .
863 ¦ .╌╌╌╌╌ .
864 ¦ . .
865 ]
866
867 assume-console [
868 ¦ left-click 2, 0
869 ¦ press left-arrow
870 ]
871 run [
872 ¦ editor-event-loop screen, console, e
873 ¦ 3:num/raw <- get *e, cursor-row:offset
874 ¦ 4:num/raw <- get *e, cursor-column:offset
875 ]
876 memory-should-contain [
877 ¦ 3 <- 1
878 ¦ 4 <- 3
879 ]
880 check-trace-count-for-label 0, [print-character]
881 ]
882
883 scenario editor-moves-across-screen-lines-to-wrapping-line-with-left-arrow [
884 local-scope
885 assume-screen 10/width, 5/height
886
887 s:text <- new [abcdef
888 g]
889 e:&:editor <- new-editor s, 0/left, 5/right
890 editor-render screen, e
891 $clear-trace
892 screen-should-contain [
893 ¦ . .
894 ¦ .abcd↩ .
895 ¦ .ef .
896 ¦ .g .
897 ¦ .╌╌╌╌╌ .
898 ]
899
900 assume-console [
901 ¦ left-click 3, 0
902 ¦ press left-arrow
903 ]
904 run [
905 ¦ editor-event-loop screen, console, e
906 ¦ 3:num/raw <- get *e, cursor-row:offset
907 ¦ 4:num/raw <- get *e, cursor-column:offset
908 ]
909 memory-should-contain [
910 ¦ 3 <- 2
911 ¦ 4 <- 2
912 ]
913 check-trace-count-for-label 0, [print-character]
914 ]
915
916 scenario editor-moves-across-screen-lines-to-non-wrapping-line-with-left-arrow [
917 local-scope
918 assume-screen 10/width, 5/height
919
920 s:text <- new [abcd
921 e]
922 e:&:editor <- new-editor s, 0/left, 5/right
923 editor-render screen, e
924 $clear-trace
925 screen-should-contain [
926 ¦ . .
927 ¦ .abcd .
928 ¦ .e .
929 ¦ .╌╌╌╌╌ .
930 ¦ . .
931 ]
932
933 assume-console [
934 ¦ left-click 2, 0
935 ¦ press left-arrow
936 ]
937 run [
938 ¦ editor-event-loop screen, console, e
939 ¦ 3:num/raw <- get *e, cursor-row:offset
940 ¦ 4:num/raw <- get *e, cursor-column:offset
941 ]
942 memory-should-contain [
943 ¦ 3 <- 1
944 ¦ 4 <- 4
945 ]
946 check-trace-count-for-label 0, [print-character]
947 ]
948
949
950
951
952
953 scenario editor-moves-to-previous-line-with-up-arrow [
954 local-scope
955 assume-screen 10/width, 5/height
956 s:text <- new [abc
957 def]
958 e:&:editor <- new-editor s, 0/left, 10/right
959 editor-render screen, e
960 $clear-trace
961 assume-console [
962 ¦ left-click 2, 1
963 ¦ press up-arrow
964 ]
965 run [
966 ¦ editor-event-loop screen, console, e
967 ¦ 3:num/raw <- get *e, cursor-row:offset
968 ¦ 4:num/raw <- get *e, cursor-column:offset
969 ]
970 memory-should-contain [
971 ¦ 3 <- 1
972 ¦ 4 <- 1
973 ]
974 check-trace-count-for-label 0, [print-character]
975 assume-console [
976 ¦ type [0]
977 ]
978 run [
979 ¦ editor-event-loop screen, console, e
980 ]
981 screen-should-contain [
982 ¦ . .
983 ¦ .a0bc .
984 ¦ .def .
985 ¦ .╌╌╌╌╌╌╌╌╌╌.
986 ¦ . .
987 ]
988 ]
989
990 after <handle-special-key> [
991 {
992 ¦ move-to-previous-line?:bool <- equal k, 65517/up-arrow
993 ¦ break-unless move-to-previous-line?
994 ¦ <move-cursor-begin>
995 ¦ go-render? <- move-to-previous-line editor
996 ¦ undo-coalesce-tag:num <- copy 3/up-arrow
997 ¦ <move-cursor-end>
998 ¦ return
999 }
1000 ]
1001
1002 def move-to-previous-line editor:&:editor -> go-render?:bool, editor:&:editor [
1003 local-scope
1004 load-ingredients
1005 go-render?:bool <- copy 0/false
1006 cursor-row:num <- get *editor, cursor-row:offset
1007 cursor-column:num <- get *editor, cursor-column:offset
1008 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1009 left:num <- get *editor, left:offset
1010 right:num <- get *editor, right:offset
1011 already-at-top?:bool <- lesser-or-equal cursor-row, 1/top
1012 {
1013 ¦
1014 ¦ break-if already-at-top?
1015 ¦
1016 ¦
1017 ¦
1018 ¦ curr:&:duplex-list:char <- copy before-cursor
1019 ¦ {
1020 ¦ ¦ old:&:duplex-list:char <- copy curr
1021 ¦ ¦ c2:char <- get *curr, value:offset
1022 ¦ ¦ at-newline?:bool <- equal c2, 10/newline
1023 ¦ ¦ break-if at-newline?
1024 ¦ ¦ curr:&:duplex-list:char <- before-previous-line curr, editor
1025 ¦ ¦ no-motion?:bool <- equal curr, old
1026 ¦ ¦ return-if no-motion?
1027 ¦ }
1028 ¦ {
1029 ¦ ¦ old <- copy curr
1030 ¦ ¦ curr <- before-previous-line curr, editor
1031 ¦ ¦ no-motion?:bool <- equal curr, old
1032 ¦ ¦ return-if no-motion?
1033 ¦ }
1034 ¦ before-cursor <- copy curr
1035 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1036 ¦ cursor-row <- subtract cursor-row, 1
1037 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
1038 ¦
1039 ¦ target-column:num <- copy cursor-column
1040 ¦ cursor-column <- copy left
1041 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
1042 ¦ {
1043 ¦ ¦ done?:bool <- greater-or-equal cursor-column, target-column
1044 ¦ ¦ break-if done?
1045 ¦ ¦ curr:&:duplex-list:char <- next before-cursor
1046 ¦ ¦ break-unless curr
1047 ¦ ¦ currc:char <- get *curr, value:offset
1048 ¦ ¦ at-newline?:bool <- equal currc, 10/newline
1049 ¦ ¦ break-if at-newline?
1050 ¦ ¦
1051 ¦ ¦ before-cursor <- copy curr
1052 ¦ ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1053 ¦ ¦ cursor-column <- add cursor-column, 1
1054 ¦ ¦ *editor <- put *editor, cursor-column:offset, cursor-column
1055 ¦ ¦ loop
1056 ¦ }
1057 ¦ return
1058 }
1059 {
1060 ¦
1061 ¦ break-unless already-at-top?
1062 ¦ <scroll-up>
1063 ¦ return 1/go-render
1064 }
1065 ]
1066
1067 scenario editor-adjusts-column-at-previous-line [
1068 local-scope
1069 assume-screen 10/width, 5/height
1070 s:text <- new [ab
1071 def]
1072 e:&:editor <- new-editor s, 0/left, 10/right
1073 editor-render screen, e
1074 $clear-trace
1075 assume-console [
1076 ¦ left-click 2, 3
1077 ¦ press up-arrow
1078 ]
1079 run [
1080 ¦ editor-event-loop screen, console, e
1081 ¦ 3:num/raw <- get *e, cursor-row:offset
1082 ¦ 4:num/raw <- get *e, cursor-column:offset
1083 ]
1084 memory-should-contain [
1085 ¦ 3 <- 1
1086 ¦ 4 <- 2
1087 ]
1088 check-trace-count-for-label 0, [print-character]
1089 assume-console [
1090 ¦ type [0]
1091 ]
1092 run [
1093 ¦ editor-event-loop screen, console, e
1094 ]
1095 screen-should-contain [
1096 ¦ . .
1097 ¦ .ab0 .
1098 ¦ .def .
1099 ¦ .╌╌╌╌╌╌╌╌╌╌.
1100 ¦ . .
1101 ]
1102 ]
1103
1104 scenario editor-adjusts-column-at-empty-line [
1105 local-scope
1106 assume-screen 10/width, 5/height
1107 s:text <- new [
1108 def]
1109 e:&:editor <- new-editor s, 0/left, 10/right
1110 editor-render screen, e
1111 $clear-trace
1112 assume-console [
1113 ¦ left-click 2, 3
1114 ¦ press up-arrow
1115 ]
1116 run [
1117 ¦ editor-event-loop screen, console, e
1118 ¦ 3:num/raw <- get *e, cursor-row:offset
1119 ¦ 4:num/raw <- get *e, cursor-column:offset
1120 ]
1121 memory-should-contain [
1122 ¦ 3 <- 1
1123 ¦ 4 <- 0
1124 ]
1125 check-trace-count-for-label 0, [print-character]
1126 assume-console [
1127 ¦ type [0]
1128 ]
1129 run [
1130 ¦ editor-event-loop screen, console, e
1131 ]
1132 screen-should-contain [
1133 ¦ . .
1134 ¦ .0 .
1135 ¦ .def .
1136 ¦ .╌╌╌╌╌╌╌╌╌╌.
1137 ¦ . .
1138 ]
1139 ]
1140
1141 scenario editor-moves-to-previous-line-from-left-margin [
1142 local-scope
1143 assume-screen 10/width, 5/height
1144
1145 s:text <- new [abc
1146 def
1147 ghi]
1148 e:&:editor <- new-editor s, 0/left, 10/right
1149 editor-render screen, e
1150 $clear-trace
1151
1152 assume-console [
1153 ¦ left-click 3, 0
1154 ¦ press up-arrow
1155 ]
1156 run [
1157 ¦ editor-event-loop screen, console, e
1158 ¦ 3:num/raw <- get *e, cursor-row:offset
1159 ¦ 4:num/raw <- get *e, cursor-column:offset
1160 ]
1161 memory-should-contain [
1162 ¦ 3 <- 2
1163 ¦ 4 <- 0
1164 ]
1165 check-trace-count-for-label 0, [print-character]
1166 assume-console [
1167 ¦ type [0]
1168 ]
1169 run [
1170 ¦ editor-event-loop screen, console, e
1171 ]
1172 screen-should-contain [
1173 ¦ . .
1174 ¦ .abc .
1175 ¦ .0def .
1176 ¦ .ghi .
1177 ¦ .╌╌╌╌╌╌╌╌╌╌.
1178 ]
1179 ]
1180
1181
1182
1183 scenario editor-moves-to-next-line-with-down-arrow [
1184 local-scope
1185 assume-screen 10/width, 5/height
1186 s:text <- new [abc
1187 def]
1188 e:&:editor <- new-editor s, 0/left, 10/right
1189 editor-render screen, e
1190 $clear-trace
1191
1192 assume-console [
1193 ¦ press down-arrow
1194 ]
1195 run [
1196 ¦ editor-event-loop screen, console, e
1197 ¦ 3:num/raw <- get *e, cursor-row:offset
1198 ¦ 4:num/raw <- get *e, cursor-column:offset
1199 ]
1200
1201 memory-should-contain [
1202 ¦ 3 <- 2
1203 ¦ 4 <- 0
1204 ]
1205 check-trace-count-for-label 0, [print-character]
1206 assume-console [
1207 ¦ type [0]
1208 ]
1209 run [
1210 ¦ editor-event-loop screen, console, e
1211 ]
1212 screen-should-contain [
1213 ¦ . .
1214 ¦ .abc .
1215 ¦ .0def .
1216 ¦ .╌╌╌╌╌╌╌╌╌╌.
1217 ¦ . .
1218 ]
1219 ]
1220
1221 after <handle-special-key> [
1222 {
1223 ¦ move-to-next-line?:bool <- equal k, 65516/down-arrow
1224 ¦ break-unless move-to-next-line?
1225 ¦ <move-cursor-begin>
1226 ¦ go-render? <- move-to-next-line editor, screen-height
1227 ¦ undo-coalesce-tag:num <- copy 4/down-arrow
1228 ¦ <move-cursor-end>
1229 ¦ return
1230 }
1231 ]
1232
1233 def move-to-next-line editor:&:editor, screen-height:num -> go-render?:bool, editor:&:editor [
1234 local-scope
1235 load-ingredients
1236 cursor-row:num <- get *editor, cursor-row:offset
1237 cursor-column:num <- get *editor, cursor-column:offset
1238 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1239 left:num <- get *editor, left:offset
1240 right:num <- get *editor, right:offset
1241 last-line:num <- subtract screen-height, 1
1242 already-at-bottom?:bool <- greater-or-equal cursor-row, last-line
1243 {
1244 ¦
1245 ¦ break-if already-at-bottom?
1246 ¦
1247 ¦ max:num <- subtract right, left
1248 ¦ next-line:&:duplex-list:char <- before-start-of-next-line before-cursor, max
1249 ¦ {
1250 ¦ ¦
1251 ¦ ¦
1252 ¦ ¦ no-motion?:bool <- equal next-line, before-cursor
1253 ¦ ¦ break-unless no-motion?
1254 ¦ ¦ scroll?:bool <- greater-than cursor-row, 1
1255 ¦ ¦ break-if scroll?, +try-to-scroll
1256 ¦ ¦ return 0/don't-render
1257 ¦ }
1258 ¦ cursor-row <- add cursor-row, 1
1259 ¦ *editor <- put *editor, cursor-row:offset, cursor-row
1260 ¦ before-cursor <- copy next-line
1261 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1262 ¦ target-column:num <- copy cursor-column
1263 ¦ cursor-column <- copy left
1264 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
1265 ¦ {
1266 ¦ ¦ done?:bool <- greater-or-equal cursor-column, target-column
1267 ¦ ¦ break-if done?
1268 ¦ ¦ curr:&:duplex-list:char <- next before-cursor
1269 ¦ ¦ break-unless curr
1270 ¦ ¦ currc:char <- get *curr, value:offset
1271 ¦ ¦ at-newline?:bool <- equal currc, 10/newline
1272 ¦ ¦ break-if at-newline?
1273 ¦ ¦
1274 ¦ ¦ before-cursor <- copy curr
1275 ¦ ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1276 ¦ ¦ cursor-column <- add cursor-column, 1
1277 ¦ ¦ *editor <- put *editor, cursor-column:offset, cursor-column
1278 ¦ ¦ loop
1279 ¦ }
1280 ¦ return 0/don't-render
1281 }
1282 +try-to-scroll
1283 <scroll-down>
1284 go-render? <- copy 1/true
1285 ]
1286
1287 scenario editor-adjusts-column-at-next-line [
1288 local-scope
1289 assume-screen 10/width, 5/height
1290 s:text <- new [abc
1291 de]
1292 e:&:editor <- new-editor s, 0/left, 10/right
1293 editor-render screen, e
1294 $clear-trace
1295 assume-console [
1296 ¦ left-click 1, 3
1297 ¦ press down-arrow
1298 ]
1299 run [
1300 ¦ editor-event-loop screen, console, e
1301 ¦ 3:num/raw <- get *e, cursor-row:offset
1302 ¦ 4:num/raw <- get *e, cursor-column:offset
1303 ]
1304 memory-should-contain [
1305 ¦ 3 <- 2
1306 ¦ 4 <- 2
1307 ]
1308 check-trace-count-for-label 0, [print-character]
1309 assume-console [
1310 ¦ type [0]
1311 ]
1312 run [
1313 ¦ editor-event-loop screen, console, e
1314 ]
1315 screen-should-contain [
1316 ¦ . .
1317 ¦ .abc .
1318 ¦ .de0 .
1319 ¦ .╌╌╌╌╌╌╌╌╌╌.
1320 ¦ . .
1321 ]
1322 ]
1323
1324
1325
1326 scenario editor-moves-to-start-of-line-with-ctrl-a [
1327 local-scope
1328 assume-screen 10/width, 5/height
1329 s:text <- new [123
1330 456]
1331 e:&:editor <- new-editor s, 0/left, 10/right
1332 editor-render screen, e
1333 $clear-trace
1334
1335 assume-console [
1336 ¦ left-click 2, 3
1337 ¦ press ctrl-a
1338 ]
1339 run [
1340 ¦ editor-event-loop screen, console, e
1341 ¦ 4:num/raw <- get *e, cursor-row:offset
1342 ¦ 5:num/raw <- get *e, cursor-column:offset
1343 ]
1344
1345 memory-should-contain [
1346 ¦ 4 <- 2
1347 ¦ 5 <- 0
1348 ]
1349 check-trace-count-for-label 0, [print-character]
1350 ]
1351
1352 after <handle-special-character> [
1353 {
1354 ¦ move-to-start-of-line?:bool <- equal c, 1/ctrl-a
1355 ¦ break-unless move-to-start-of-line?
1356 ¦ <move-cursor-begin>
1357 ¦ move-to-start-of-line editor
1358 ¦ undo-coalesce-tag:num <- copy 0/never
1359 ¦ <move-cursor-end>
1360 ¦ return 0/don't-render
1361 }
1362 ]
1363
1364 after <handle-special-key> [
1365 {
1366 ¦ move-to-start-of-line?:bool <- equal k, 65521/home
1367 ¦ break-unless move-to-start-of-line?
1368 ¦ <move-cursor-begin>
1369 ¦ move-to-start-of-line editor
1370 ¦ undo-coalesce-tag:num <- copy 0/never
1371 ¦ <move-cursor-end>
1372 ¦ return 0/don't-render
1373 }
1374 ]
1375
1376 def move-to-start-of-line editor:&:editor -> editor:&:editor [
1377 local-scope
1378 load-ingredients
1379
1380 left:num <- get *editor, left:offset
1381 cursor-column:num <- copy left
1382 *editor <- put *editor, cursor-column:offset, cursor-column
1383
1384 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1385 init:&:duplex-list:char <- get *editor, data:offset
1386
1387 {
1388 ¦ at-start-of-text?:bool <- equal before-cursor, init
1389 ¦ break-if at-start-of-text?
1390 ¦ prev:char <- get *before-cursor, value:offset
1391 ¦ at-start-of-line?:bool <- equal prev, 10/newline
1392 ¦ break-if at-start-of-line?
1393 ¦ before-cursor <- prev before-cursor
1394 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1395 ¦ assert before-cursor, [move-to-start-of-line tried to move before start of text]
1396 ¦ loop
1397 }
1398 ]
1399
1400 scenario editor-moves-to-start-of-line-with-ctrl-a-2 [
1401 local-scope
1402 assume-screen 10/width, 5/height
1403 s:text <- new [123
1404 456]
1405 e:&:editor <- new-editor s, 0/left, 10/right
1406 editor-render screen, e
1407 $clear-trace
1408
1409 assume-console [
1410 ¦ left-click 1, 3
1411 ¦ press ctrl-a
1412 ]
1413 run [
1414 ¦ editor-event-loop screen, console, e
1415 ¦ 4:num/raw <- get *e, cursor-row:offset
1416 ¦ 5:num/raw <- get *e, cursor-column:offset
1417 ]
1418
1419 memory-should-contain [
1420 ¦ 4 <- 1
1421 ¦ 5 <- 0
1422 ]
1423 check-trace-count-for-label 0, [print-character]
1424 ]
1425
1426 scenario editor-moves-to-start-of-line-with-home [
1427 local-scope
1428 assume-screen 10/width, 5/height
1429 s:text <- new [123
1430 456]
1431 e:&:editor <- new-editor s, 0/left, 10/right
1432 $clear-trace
1433
1434 assume-console [
1435 ¦ left-click 2, 3
1436 ¦ press home
1437 ]
1438 run [
1439 ¦ editor-event-loop screen, console, e
1440 ¦ 3:num/raw <- get *e, cursor-row:offset
1441 ¦ 4:num/raw <- get *e, cursor-column:offset
1442 ]
1443
1444 memory-should-contain [
1445 ¦ 3 <- 2
1446 ¦ 4 <- 0
1447 ]
1448 check-trace-count-for-label 0, [print-character]
1449 ]
1450
1451 scenario editor-moves-to-start-of-line-with-home-2 [
1452 local-scope
1453 assume-screen 10/width, 5/height
1454 s:text <- new [123
1455 456]
1456 e:&:editor <- new-editor s, 0/left, 10/right
1457 editor-render screen, e
1458 $clear-trace
1459
1460 assume-console [
1461 ¦ left-click 1, 3
1462 ¦ press home
1463 ]
1464 run [
1465 ¦ editor-event-loop screen, console, e
1466 ¦ 3:num/raw <- get *e, cursor-row:offset
1467 ¦ 4:num/raw <- get *e, cursor-column:offset
1468 ]
1469
1470 memory-should-contain [
1471 ¦ 3 <- 1
1472 ¦ 4 <- 0
1473 ]
1474 check-trace-count-for-label 0, [print-character]
1475 ]
1476
1477
1478
1479 scenario editor-moves-to-end-of-line-with-ctrl-e [
1480 local-scope
1481 assume-screen 10/width, 5/height
1482 s:text <- new [123
1483 456]
1484 e:&:editor <- new-editor s, 0/left, 10/right
1485 editor-render screen, e
1486 $clear-trace
1487
1488 assume-console [
1489 ¦ left-click 1, 1
1490 ¦ press ctrl-e
1491 ]
1492 run [
1493 ¦ editor-event-loop screen, console, e
1494 ¦ 4:num/raw <- get *e, cursor-row:offset
1495 ¦ 5:num/raw <- get *e, cursor-column:offset
1496 ]
1497
1498 memory-should-contain [
1499 ¦ 4 <- 1
1500 ¦ 5 <- 3
1501 ]
1502 check-trace-count-for-label 0, [print-character]
1503
1504 assume-console [
1505 ¦ type [z]
1506 ]
1507 run [
1508 ¦ editor-event-loop screen, console, e
1509 ¦ 4:num/raw <- get *e, cursor-row:offset
1510 ¦ 5:num/raw <- get *e, cursor-column:offset
1511 ]
1512 memory-should-contain [
1513 ¦ 4 <- 1
1514 ¦ 5 <- 4
1515 ]
1516 screen-should-contain [
1517 ¦ . .
1518 ¦ .123z .
1519 ¦ .456 .
1520 ¦ .╌╌╌╌╌╌╌╌╌╌.
1521 ¦ . .
1522 ]
1523 check-trace-count-for-label 1, [print-character]
1524 ]
1525
1526 after <handle-special-character> [
1527 {
1528 ¦ move-to-end-of-line?:bool <- equal c, 5/ctrl-e
1529 ¦ break-unless move-to-end-of-line?
1530 ¦ <move-cursor-begin>
1531 ¦ move-to-end-of-line editor
1532 ¦ undo-coalesce-tag:num <- copy 0/never
1533 ¦ <move-cursor-end>
1534 ¦ return 0/don't-render
1535 }
1536 ]
1537
1538 after <handle-special-key> [
1539 {
1540 ¦ move-to-end-of-line?:bool <- equal k, 65520/end
1541 ¦ break-unless move-to-end-of-line?
1542 ¦ <move-cursor-begin>
1543 ¦ move-to-end-of-line editor
1544 ¦ undo-coalesce-tag:num <- copy 0/never
1545 ¦ <move-cursor-end>
1546 ¦ return 0/don't-render
1547 }
1548 ]
1549
1550 def move-to-end-of-line editor:&:editor -> editor:&:editor [
1551 local-scope
1552 load-ingredients
1553 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1554 cursor-column:num <- get *editor, cursor-column:offset
1555
1556 {
1557 ¦ next:&:duplex-list:char <- next before-cursor
1558 ¦ break-unless next
1559 ¦ nextc:char <- get *next, value:offset
1560 ¦ at-end-of-line?:bool <- equal nextc, 10/newline
1561 ¦ break-if at-end-of-line?
1562 ¦ before-cursor <- copy next
1563 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
1564 ¦ cursor-column <- add cursor-column, 1
1565 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
1566 ¦ loop
1567 }
1568 ]
1569
1570 scenario editor-moves-to-end-of-line-with-ctrl-e-2 [
1571 local-scope
1572 assume-screen 10/width, 5/height
1573 s:text <- new [123
1574 456]
1575 e:&:editor <- new-editor s, 0/left, 10/right
1576 editor-render screen, e
1577 $clear-trace
1578
1579 assume-console [
1580 ¦ left-click 2, 1
1581 ¦ press ctrl-e
1582 ]
1583 run [
1584 ¦ editor-event-loop screen, console, e
1585 ¦ 4:num/raw <- get *e, cursor-row:offset
1586 ¦ 5:num/raw <- get *e, cursor-column:offset
1587 ]
1588
1589 memory-should-contain [
1590 ¦ 4 <- 2
1591 ¦ 5 <- 3
1592 ]
1593 check-trace-count-for-label 0, [print-character]
1594 ]
1595
1596 scenario editor-moves-to-end-of-line-with-end [
1597 local-scope
1598 assume-screen 10/width, 5/height
1599 s:text <- new [123
1600 456]
1601 e:&:editor <- new-editor s, 0/left, 10/right
1602 editor-render screen, e
1603 $clear-trace
1604
1605 assume-console [
1606 ¦ left-click 1, 1
1607 ¦ press end
1608 ]
1609 run [
1610 ¦ editor-event-loop screen, console, e
1611 ¦ 3:num/raw <- get *e, cursor-row:offset
1612 ¦ 4:num/raw <- get *e, cursor-column:offset
1613 ]
1614
1615 memory-should-contain [
1616 ¦ 3 <- 1
1617 ¦ 4 <- 3
1618 ]
1619 check-trace-count-for-label 0, [print-character]
1620 ]
1621
1622 scenario editor-moves-to-end-of-line-with-end-2 [
1623 local-scope
1624 assume-screen 10/width, 5/height
1625 s:text <- new [123
1626 456]
1627 e:&:editor <- new-editor s, 0/left, 10/right
1628 editor-render screen, e
1629 $clear-trace
1630
1631 assume-console [
1632 ¦ left-click 2, 1
1633 ¦ press end
1634 ]
1635 run [
1636 ¦ editor-event-loop screen, console, e
1637 ¦ 3:num/raw <- get *e, cursor-row:offset
1638 ¦ 4:num/raw <- get *e, cursor-column:offset
1639 ]
1640
1641 memory-should-contain [
1642 ¦ 3 <- 2
1643 ¦ 4 <- 3
1644 ]
1645 check-trace-count-for-label 0, [print-character]
1646 ]
1647
1648
1649
1650 scenario editor-deletes-to-start-of-line-with-ctrl-u [
1651 local-scope
1652 assume-screen 10/width, 5/height
1653 s:text <- new [123
1654 456]
1655 e:&:editor <- new-editor s, 0/left, 10/right
1656 editor-render screen, e
1657 $clear-trace
1658
1659 assume-console [
1660 ¦ left-click 2, 2
1661 ¦ press ctrl-u
1662 ]
1663 run [
1664 ¦ editor-event-loop screen, console, e
1665 ]
1666
1667 screen-should-contain [
1668 ¦ . .
1669 ¦ .123 .
1670 ¦ .6 .
1671 ¦ .╌╌╌╌╌╌╌╌╌╌.
1672 ¦ . .
1673 ]
1674 check-trace-count-for-label 10, [print-character]
1675 ]
1676
1677 after <handle-special-character> [
1678 {
1679 ¦ delete-to-start-of-line?:bool <- equal c, 21/ctrl-u
1680 ¦ break-unless delete-to-start-of-line?
1681 ¦ <delete-to-start-of-line-begin>
1682 ¦ deleted-cells:&:duplex-list:char <- delete-to-start-of-line editor
1683 ¦ <delete-to-start-of-line-end>
1684 ¦ go-render?:bool <- minimal-render-for-ctrl-u screen, editor
1685 ¦ return
1686 }
1687 ]
1688
1689 def minimal-render-for-ctrl-u screen:&:screen, editor:&:editor -> go-render?:bool, screen:&:screen [
1690 local-scope
1691 load-ingredients
1692 curr-column:num <- get *editor, cursor-column:offset
1693
1694 buf:&:buffer:char <- new-buffer 30
1695 curr:&:duplex-list:char <- get *editor, before-cursor:offset
1696 i:num <- copy curr-column
1697 right:num <- get *editor, right:offset
1698 {
1699 ¦
1700 ¦ wrap?:bool <- greater-or-equal i, right
1701 ¦ return-if wrap?, 1/go-render
1702 ¦ curr <- next curr
1703 ¦ break-unless curr
1704 ¦ c:char <- get *curr, value:offset
1705 ¦ b:bool <- equal c, 10
1706 ¦ break-if b
1707 ¦ buf <- append buf, c
1708 ¦ i <- add i, 1
1709 ¦ loop
1710 }
1711 curr-line:text <- buffer-to-array buf
1712 curr-row:num <- get *editor, cursor-row:offset
1713 render-code screen, curr-line, curr-column, right, curr-row
1714 return 0/dont-render
1715 ]
1716
1717 def delete-to-start-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [
1718 local-scope
1719 load-ingredients
1720
1721 init:&:duplex-list:char <- get *editor, data:offset
1722 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1723 start:&:duplex-list:char <- copy before-cursor
1724 end:&:duplex-list:char <- next before-cursor
1725 {
1726 ¦ at-start-of-text?:bool <- equal start, init
1727 ¦ break-if at-start-of-text?
1728 ¦ curr:char <- get *start, value:offset
1729 ¦ at-start-of-line?:bool <- equal curr, 10/newline
1730 ¦ break-if at-start-of-line?
1731 ¦ start <- prev start
1732 ¦ assert start, [delete-to-start-of-line tried to move before start of text]
1733 ¦ loop
1734 }
1735
1736 result:&:duplex-list:char <- next start
1737 remove-between start, end
1738
1739 before-cursor <- copy start
1740 *editor <- put *editor, before-cursor:offset, before-cursor
1741 left:num <- get *editor, left:offset
1742 *editor <- put *editor, cursor-column:offset, left
1743 ]
1744
1745 def render-code screen:&:screen, s:text, left:num, right:num, row:num -> row:num, screen:&:screen [
1746 local-scope
1747 load-ingredients
1748 return-unless s
1749 color:num <- copy 7/white
1750 column:num <- copy left
1751 screen <- move-cursor screen, row, column
1752 screen-height:num <- screen-height screen
1753 i:num <- copy 0
1754 len:num <- length *s
1755 {
1756 ¦ +next-character
1757 ¦ done?:bool <- greater-or-equal i, len
1758 ¦ break-if done?
1759 ¦ done? <- greater-or-equal row, screen-height
1760 ¦ break-if done?
1761 ¦ c:char <- index *s, i
1762 ¦ <character-c-received>
1763 ¦ {
1764 ¦ ¦
1765 ¦ ¦ newline?:bool <- equal c, 10/newline
1766 ¦ ¦ break-unless newline?
1767 ¦ ¦
1768 ¦ ¦ {
1769 ¦ ¦ ¦ done?:bool <- greater-than column, right
1770 ¦ ¦ ¦ break-if done?
1771 ¦ ¦ ¦ space:char <- copy 32/space
1772 ¦ ¦ ¦ print screen, space
1773 ¦ ¦ ¦ column <- add column, 1
1774 ¦ ¦ ¦ loop
1775 ¦ ¦ }
1776 ¦ ¦ row <- add row, 1
1777 ¦ ¦ column <- copy left
1778 ¦ ¦ screen <- move-cursor screen, row, column
1779 ¦ ¦ i <- add i, 1
1780 ¦ ¦ loop +next-character
1781 ¦ }
1782 ¦ {
1783 ¦ ¦
1784 ¦ ¦ at-right?:bool <- equal column, right
1785 ¦ ¦ break-unless at-right?
1786 ¦ ¦
1787 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left
1788 ¦ ¦ print screen, wrap-icon, 245/grey
1789 ¦ ¦ column <- copy left
1790 ¦ ¦ row <- add row, 1
1791 ¦ ¦ screen <- move-cursor screen, row, column
1792 ¦ ¦
1793 ¦ ¦ loop +next-character
1794 ¦ }
1795 ¦ i <- add i, 1
1796 ¦ print screen, c, color
1797 ¦ column <- add column, 1
1798 ¦ loop
1799 }
1800 was-at-left?:bool <- equal column, left
1801 clear-line-until screen, right
1802 {
1803 ¦ break-if was-at-left?
1804 ¦ row <- add row, 1
1805 }
1806 move-cursor screen, row, left
1807 ]
1808
1809 scenario editor-deletes-to-start-of-line-with-ctrl-u-2 [
1810 local-scope
1811 assume-screen 10/width, 5/height
1812 s:text <- new [123
1813 456]
1814 e:&:editor <- new-editor s, 0/left, 10/right
1815 editor-render screen, e
1816 $clear-trace
1817
1818 assume-console [
1819 ¦ left-click 1, 2
1820 ¦ press ctrl-u
1821 ]
1822 run [
1823 ¦ editor-event-loop screen, console, e
1824 ]
1825
1826 screen-should-contain [
1827 ¦ . .
1828 ¦ .3 .
1829 ¦ .456 .
1830 ¦ .╌╌╌╌╌╌╌╌╌╌.
1831 ¦ . .
1832 ]
1833 check-trace-count-for-label 10, [print-character]
1834 ]
1835
1836 scenario editor-deletes-to-start-of-line-with-ctrl-u-3 [
1837 local-scope
1838 assume-screen 10/width, 5/height
1839 s:text <- new [123
1840 456]
1841 e:&:editor <- new-editor s, 0/left, 10/right
1842 editor-render screen, e
1843 $clear-trace
1844
1845 assume-console [
1846 ¦ left-click 1, 3
1847 ¦ press ctrl-u
1848 ]
1849 run [
1850 ¦ editor-event-loop screen, console, e
1851 ]
1852
1853 screen-should-contain [
1854 ¦ . .
1855 ¦ . .
1856 ¦ .456 .
1857 ¦ .╌╌╌╌╌╌╌╌╌╌.
1858 ¦ . .
1859 ]
1860 check-trace-count-for-label 10, [print-character]
1861 ]
1862
1863 scenario editor-deletes-to-start-of-final-line-with-ctrl-u [
1864 local-scope
1865 assume-screen 10/width, 5/height
1866 s:text <- new [123
1867 456]
1868 e:&:editor <- new-editor s, 0/left, 10/right
1869 editor-render screen, e
1870 $clear-trace
1871
1872 assume-console [
1873 ¦ left-click 2, 3
1874 ¦ press ctrl-u
1875 ]
1876 run [
1877 ¦ editor-event-loop screen, console, e
1878 ]
1879
1880 screen-should-contain [
1881 ¦ . .
1882 ¦ .123 .
1883 ¦ . .
1884 ¦ .╌╌╌╌╌╌╌╌╌╌.
1885 ¦ . .
1886 ]
1887 check-trace-count-for-label 10, [print-character]
1888 ]
1889
1890
1891
1892 scenario editor-deletes-to-end-of-line-with-ctrl-k [
1893 local-scope
1894 assume-screen 10/width, 5/height
1895 s:text <- new [123
1896 456]
1897 e:&:editor <- new-editor s, 0/left, 10/right
1898 editor-render screen, e
1899 $clear-trace
1900
1901 assume-console [
1902 ¦ left-click 1, 1
1903 ¦ press ctrl-k
1904 ]
1905 run [
1906 ¦ editor-event-loop screen, console, e
1907 ]
1908
1909 screen-should-contain [
1910 ¦ . .
1911 ¦ .1 .
1912 ¦ .456 .
1913 ¦ .╌╌╌╌╌╌╌╌╌╌.
1914 ¦ . .
1915 ]
1916 check-trace-count-for-label 9, [print-character]
1917 ]
1918
1919 after <handle-special-character> [
1920 {
1921 ¦ delete-to-end-of-line?:bool <- equal c, 11/ctrl-k
1922 ¦ break-unless delete-to-end-of-line?
1923 ¦ <delete-to-end-of-line-begin>
1924 ¦ deleted-cells:&:duplex-list:char <- delete-to-end-of-line editor
1925 ¦ <delete-to-end-of-line-end>
1926 ¦
1927 ¦ go-render?:bool <- minimal-render-for-ctrl-k screen, editor, deleted-cells
1928 ¦ return
1929 }
1930 ]
1931
1932 def minimal-render-for-ctrl-k screen:&:screen, editor:&:editor, deleted-cells:&:duplex-list:char -> go-render?:bool, screen:&:screen [
1933 local-scope
1934 load-ingredients
1935
1936 return-unless deleted-cells, 0/dont-render
1937
1938 curr-column:num <- get *editor, cursor-column:offset
1939 num-deleted-cells:num <- length, deleted-cells
1940 old-row-len:num <- add curr-column, num-deleted-cells
1941 left:num <- get *editor, left:offset
1942 right:num <- get *editor, right:offset
1943 end:num <- subtract right, left
1944 wrap?:bool <- greater-or-equal old-row-len, end
1945 return-if wrap?, 1/go-render
1946
1947 buf:&:buffer:char <- new-buffer 30
1948 curr:&:duplex-list:char <- get *editor, before-cursor:offset
1949 {
1950 ¦
1951 ¦ curr <- next curr
1952 ¦ break-unless curr
1953 ¦ c:char <- get *curr, value:offset
1954 ¦
1955 ¦ b:bool <- equal c, 10
1956 ¦ break-if b
1957 ¦ buf <- append buf, c
1958 ¦ loop
1959 }
1960 curr-line:text <- buffer-to-array buf
1961 curr-row:num <- get *editor, cursor-row:offset
1962 render-code screen, curr-line, curr-column, right, curr-row
1963 return 0/dont-render
1964 ]
1965
1966 def delete-to-end-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [
1967 local-scope
1968 load-ingredients
1969
1970 start:&:duplex-list:char <- get *editor, before-cursor:offset
1971 end:&:duplex-list:char <- next start
1972 {
1973 ¦ at-end-of-text?:bool <- equal end, 0/null
1974 ¦ break-if at-end-of-text?
1975 ¦ curr:char <- get *end, value:offset
1976 ¦ at-end-of-line?:bool <- equal curr, 10/newline
1977 ¦ break-if at-end-of-line?
1978 ¦ end <- next end
1979 ¦ loop
1980 }
1981
1982 result <- next start
1983 remove-between start, end
1984 ]
1985
1986 scenario editor-deletes-to-end-of-line-with-ctrl-k-2 [
1987 local-scope
1988 assume-screen 10/width, 5/height
1989 s:text <- new [123
1990 456]
1991 e:&:editor <- new-editor s, 0/left, 10/right
1992 editor-render screen, e
1993 $clear-trace
1994
1995 assume-console [
1996 ¦ left-click 2, 1
1997 ¦ press ctrl-k
1998 ]
1999 run [
2000 ¦ editor-event-loop screen, console, e
2001 ]
2002
2003 screen-should-contain [
2004 ¦ . .
2005 ¦ .123 .
2006 ¦ .4 .
2007 ¦ .╌╌╌╌╌╌╌╌╌╌.
2008 ¦ . .
2009 ]
2010 check-trace-count-for-label 9, [print-character]
2011 ]
2012
2013 scenario editor-deletes-to-end-of-line-with-ctrl-k-3 [
2014 local-scope
2015 assume-screen 10/width, 5/height
2016 s:text <- new [123
2017 456]
2018 e:&:editor <- new-editor s, 0/left, 10/right
2019 editor-render screen, e
2020 $clear-trace
2021
2022 assume-console [
2023 ¦ left-click 1, 2
2024 ¦ press ctrl-k
2025 ]
2026 run [
2027 ¦ editor-event-loop screen, console, e
2028 ]
2029
2030 screen-should-contain [
2031 ¦ . .
2032 ¦ .12 .
2033 ¦ .456 .
2034 ¦ .╌╌╌╌╌╌╌╌╌╌.
2035 ¦ . .
2036 ]
2037 check-trace-count-for-label 8, [print-character]
2038 ]
2039
2040 scenario editor-deletes-to-end-of-line-with-ctrl-k-4 [
2041 local-scope
2042 assume-screen 10/width, 5/height
2043 s:text <- new [123
2044 456]
2045 e:&:editor <- new-editor s, 0/left, 10/right
2046 editor-render screen, e
2047 $clear-trace
2048
2049 assume-console [
2050 ¦ left-click 1, 3
2051 ¦ press ctrl-k
2052 ]
2053 run [
2054 ¦ editor-event-loop screen, console, e
2055 ]
2056
2057 screen-should-contain [
2058 ¦ . .
2059 ¦ .123 .
2060 ¦ .456 .
2061 ¦ .╌╌╌╌╌╌╌╌╌╌.
2062 ¦ . .
2063 ]
2064 check-trace-count-for-label 7, [print-character]
2065 ]
2066
2067 scenario editor-deletes-to-end-of-line-with-ctrl-k-5 [
2068 local-scope
2069 assume-screen 10/width, 5/height
2070 s:text <- new [123
2071 456]
2072 e:&:editor <- new-editor s, 0/left, 10/right
2073 editor-render screen, e
2074 $clear-trace
2075
2076 assume-console [
2077 ¦ left-click 2, 2
2078 ¦ press ctrl-k
2079 ]
2080 run [
2081 ¦ editor-event-loop screen, console, e
2082 ]
2083
2084 screen-should-contain [
2085 ¦ . .
2086 ¦ .123 .
2087 ¦ .45 .
2088 ¦ .╌╌╌╌╌╌╌╌╌╌.
2089 ¦ . .
2090 ]
2091 check-trace-count-for-label 8, [print-character]
2092 ]
2093
2094 scenario editor-deletes-to-end-of-line-with-ctrl-k-6 [
2095 local-scope
2096 assume-screen 10/width, 5/height
2097 s:text <- new [123
2098 456]
2099 e:&:editor <- new-editor s, 0/left, 10/right
2100 editor-render screen, e
2101 $clear-trace
2102
2103 assume-console [
2104 ¦ left-click 2, 3
2105 ¦ press ctrl-k
2106 ]
2107 run [
2108 ¦ editor-event-loop screen, console, e
2109 ]
2110
2111 screen-should-contain [
2112 ¦ . .
2113 ¦ .123 .
2114 ¦ .456 .
2115 ¦ .╌╌╌╌╌╌╌╌╌╌.
2116 ¦ . .
2117 ]
2118
2119 check-trace-count-for-label 0, [print-character]
2120 ]
2121
2122 scenario editor-deletes-to-end-of-wrapped-line-with-ctrl-k [
2123 local-scope
2124 assume-screen 10/width, 5/height
2125
2126 s:text <- new [1234
2127 567]
2128 e:&:editor <- new-editor s, 0/left, 4/right
2129 editor-render screen, e
2130 $clear-trace
2131
2132 assume-console [
2133 ¦ press ctrl-k
2134 ]
2135 run [
2136 ¦ editor-event-loop screen, console, e
2137 ]
2138
2139 screen-should-contain [
2140 ¦ . .
2141 ¦ . .
2142 ¦ .567 .
2143 ¦ .╌╌╌╌ .
2144 ¦ . .
2145 ]
2146
2147 check-trace-count-for-label 16, [print-character]
2148 ]
2149
2150
2151
2152 scenario editor-can-scroll-down-using-arrow-keys [
2153 local-scope
2154
2155 assume-screen 10/width, 4/height
2156
2157 s:text <- new [a
2158 b
2159 c
2160 d]
2161 e:&:editor <- new-editor s, 0/left, 10/right
2162 editor-render screen, e
2163 screen-should-contain [
2164 ¦ . .
2165 ¦ .a .
2166 ¦ .b .
2167 ¦ .c .
2168 ]
2169
2170 assume-console [
2171 ¦ left-click 3, 0
2172 ¦ press down-arrow
2173 ]
2174 run [
2175 ¦ editor-event-loop screen, console, e
2176 ]
2177
2178 screen-should-contain [
2179 ¦ . .
2180 ¦ .b .
2181 ¦ .c .
2182 ¦ .d .
2183 ]
2184 ]
2185
2186 after <scroll-down> [
2187 trace 10, [app], [scroll down]
2188 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
2189 left:num <- get *editor, left:offset
2190 right:num <- get *editor, right:offset
2191 max:num <- subtract right, left
2192 old-top:&:duplex-list:char <- copy top-of-screen
2193 top-of-screen <- before-start-of-next-line top-of-screen, max
2194 *editor <- put *editor, top-of-screen:offset, top-of-screen
2195 no-movement?:bool <- equal old-top, top-of-screen
2196 return-if no-movement?, 0/don't-render
2197 ]
2198
2199
2200
2201
2202
2203 def before-start-of-next-line original:&:duplex-list:char, max:num -> curr:&:duplex-list:char [
2204 local-scope
2205 load-ingredients
2206 count:num <- copy 0
2207 curr:&:duplex-list:char <- copy original
2208
2209 {
2210 ¦ c:char <- get *curr, value:offset
2211 ¦ at-newline?:bool <- equal c, 10/newline
2212 ¦ break-unless at-newline?
2213 ¦ curr <- next curr
2214 ¦ count <- add count, 1
2215 }
2216 {
2217 ¦ return-unless curr, original
2218 ¦ done?:bool <- greater-or-equal count, max
2219 ¦ break-if done?
2220 ¦ c:char <- get *curr, value:offset
2221 ¦ at-newline?:bool <- equal c, 10/newline
2222 ¦ break-if at-newline?
2223 ¦ curr <- next curr
2224 ¦ count <- add count, 1
2225 ¦ loop
2226 }
2227 return-unless curr, original
2228 return curr
2229 ]
2230
2231 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys [
2232 local-scope
2233
2234 assume-screen 10/width, 4/height
2235
2236
2237 s:text <- new [abcdef
2238 g
2239 h
2240 i]
2241 e:&:editor <- new-editor s, 0/left, 5/right
2242 editor-render screen, e
2243 screen-should-contain [
2244 ¦ . .
2245 ¦ .abcd↩ .
2246 ¦ .ef .
2247 ¦ .g .
2248 ]
2249
2250 assume-console [
2251 ¦ left-click 3, 0
2252 ¦ press down-arrow
2253 ]
2254 run [
2255 ¦ editor-event-loop screen, console, e
2256 ]
2257
2258 screen-should-contain [
2259 ¦ . .
2260 ¦ .ef .
2261 ¦ .g .
2262 ¦ .h .
2263 ]
2264 ]
2265
2266 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys-2 [
2267 local-scope
2268
2269 assume-screen 10/width, 4/height
2270
2271 s:text <- new [abcdefghij
2272 k
2273 l
2274 m]
2275 e:&:editor <- new-editor s, 0/left, 5/right
2276
2277 assume-console [
2278 ¦ left-click 3, 0
2279 ¦ press down-arrow
2280 ]
2281 run [
2282 ¦ editor-event-loop screen, console, e
2283 ]
2284
2285 screen-should-contain [
2286 ¦ . .
2287 ¦ .efgh↩ .
2288 ¦ .ij .
2289 ¦ .k .
2290 ]
2291
2292 assume-console [
2293 ¦ press down-arrow
2294 ]
2295 run [
2296 ¦ editor-event-loop screen, console, e
2297 ]
2298
2299 screen-should-contain [
2300 ¦ . .
2301 ¦ .ij .
2302 ¦ .k .
2303 ¦ .l .
2304 ]
2305 ]
2306
2307 scenario editor-scrolls-down-when-line-wraps [
2308 local-scope
2309
2310 assume-screen 5/width, 4/height
2311
2312 s:text <- new [a
2313 b
2314 cdef]
2315 e:&:editor <- new-editor s, 0/left, 5/right
2316
2317 assume-console [
2318 ¦ left-click 3, 4
2319 ¦ type [g]
2320 ]
2321 run [
2322 ¦ editor-event-loop screen, console, e
2323 ¦ 3:num/raw <- get *e, cursor-row:offset
2324 ¦ 4:num/raw <- get *e, cursor-column:offset
2325 ]
2326
2327 screen-should-contain [
2328 ¦ . .
2329 ¦ .b .
2330 ¦ .cdef↩.
2331 ¦ .g .
2332 ]
2333 memory-should-contain [
2334 ¦ 3 <- 3
2335 ¦ 4 <- 1
2336 ]
2337 ]
2338
2339 scenario editor-scrolls-down-on-newline [
2340 local-scope
2341 assume-screen 5/width, 4/height
2342
2343 s:text <- new [a
2344 b
2345 c]
2346 e:&:editor <- new-editor s, 0/left, 5/right
2347 assume-console [
2348 ¦ left-click 3, 4
2349 ¦ type [
2350 ]
2351 ]
2352 run [
2353 ¦ editor-event-loop screen, console, e
2354 ¦ 3:num/raw <- get *e, cursor-row:offset
2355 ¦ 4:num/raw <- get *e, cursor-column:offset
2356 ]
2357
2358 screen-should-contain [
2359 ¦ . .
2360 ¦ .b .
2361 ¦ .c .
2362 ¦ . .
2363 ]
2364 memory-should-contain [
2365 ¦ 3 <- 3
2366 ¦ 4 <- 0
2367 ]
2368 ]
2369
2370 scenario editor-scrolls-down-on-right-arrow [
2371 local-scope
2372
2373 assume-screen 5/width, 4/height
2374
2375 s:text <- new [a
2376 b
2377 cdefgh]
2378 e:&:editor <- new-editor s, 0/left, 5/right
2379
2380 assume-console [
2381 ¦ left-click 3, 3
2382 ¦ press right-arrow
2383 ]
2384 run [
2385 ¦ editor-event-loop screen, console, e
2386 ¦ 3:num/raw <- get *e, cursor-row:offset
2387 ¦ 4:num/raw <- get *e, cursor-column:offset
2388 ]
2389
2390 screen-should-contain [
2391 ¦ . .
2392 ¦ .b .
2393 ¦ .cdef↩.
2394 ¦ .gh .
2395 ]
2396 memory-should-contain [
2397 ¦ 3 <- 3
2398 ¦ 4 <- 0
2399 ]
2400 ]
2401
2402 scenario editor-scrolls-down-on-right-arrow-2 [
2403 local-scope
2404
2405 assume-screen 5/width, 4/height
2406
2407 s:text <- new [a
2408 b
2409 c
2410 d]
2411 e:&:editor <- new-editor s, 0/left, 5/right
2412
2413 assume-console [
2414 ¦ left-click 3, 3
2415 ¦ press right-arrow
2416 ]
2417 run [
2418 ¦ editor-event-loop screen, console, e
2419 ¦ 3:num/raw <- get *e, cursor-row:offset
2420 ¦ 4:num/raw <- get *e, cursor-column:offset
2421 ]
2422
2423 screen-should-contain [
2424 ¦ . .
2425 ¦ .b .
2426 ¦ .c .
2427 ¦ .d .
2428 ]
2429 memory-should-contain [
2430 ¦ 3 <- 3
2431 ¦ 4 <- 0
2432 ]
2433 ]
2434
2435 scenario editor-scrolls-at-end-on-down-arrow [
2436 local-scope
2437 assume-screen 10/width, 5/height
2438 s:text <- new [abc
2439 de]
2440 e:&:editor <- new-editor s, 0/left, 10/right
2441 editor-render screen, e
2442 $clear-trace
2443
2444 assume-console [
2445 ¦ left-click 2, 0
2446 ¦ press down-arrow
2447 ]
2448 run [
2449 ¦ editor-event-loop screen, console, e
2450 ¦ 3:num/raw <- get *e, cursor-row:offset
2451 ¦ 4:num/raw <- get *e, cursor-column:offset
2452 ]
2453
2454 memory-should-contain [
2455 ¦ 3 <- 1
2456 ¦ 4 <- 2
2457 ]
2458 assume-console [
2459 ¦ type [0]
2460 ]
2461 run [
2462 ¦ editor-event-loop screen, console, e
2463 ]
2464 screen-should-contain [
2465 ¦ . .
2466 ¦ .de0 .
2467 ¦ .╌╌╌╌╌╌╌╌╌╌.
2468 ¦ . .
2469 ]
2470
2471 $clear-trace
2472 assume-console [
2473 ¦ left-click 2, 0
2474 ¦ press down-arrow
2475 ]
2476 run [
2477 ¦ editor-event-loop screen, console, e
2478 ¦ 3:num/raw <- get *e, cursor-row:offset
2479 ¦ 4:num/raw <- get *e, cursor-column:offset
2480 ]
2481
2482 memory-should-contain [
2483 ¦ 3 <- 1
2484 ¦ 4 <- 3
2485 ]
2486 check-trace-count-for-label 0, [print-character]
2487 assume-console [
2488 ¦ type [1]
2489 ]
2490 run [
2491 ¦ editor-event-loop screen, console, e
2492 ]
2493 screen-should-contain [
2494 ¦ . .
2495 ¦ .de01 .
2496 ¦ .╌╌╌╌╌╌╌╌╌╌.
2497 ¦ . .
2498 ]
2499 ]
2500
2501 scenario editor-combines-page-and-line-scroll [
2502 local-scope
2503
2504 assume-screen 10/width, 4/height
2505
2506 s:text <- new [a
2507 b
2508 c
2509 d
2510 e
2511 f
2512 g]
2513 e:&:editor <- new-editor s, 0/left, 5/right
2514 editor-render screen, e
2515
2516 assume-console [
2517 ¦ press page-down
2518 ¦ left-click 3, 0
2519 ¦ press down-arrow
2520 ]
2521 run [
2522 ¦ editor-event-loop screen, console, e
2523 ]
2524
2525 screen-should-contain [
2526 ¦ . .
2527 ¦ .d .
2528 ¦ .e .
2529 ¦ .f .
2530 ]
2531 ]
2532
2533
2534
2535 scenario editor-can-scroll-up-using-arrow-keys [
2536 local-scope
2537
2538 assume-screen 10/width, 4/height
2539
2540 s:text <- new [a
2541 b
2542 c
2543 d]
2544 e:&:editor <- new-editor s, 0/left, 10/right
2545 editor-render screen, e
2546 screen-should-contain [
2547 ¦ . .
2548 ¦ .a .
2549 ¦ .b .
2550 ¦ .c .
2551 ]
2552
2553 assume-console [
2554 ¦ press page-down
2555 ¦ press up-arrow
2556 ]
2557 run [
2558 ¦ editor-event-loop screen, console, e
2559 ]
2560
2561 screen-should-contain [
2562 ¦ . .
2563 ¦ .b .
2564 ¦ .c .
2565 ¦ .d .
2566 ]
2567 ]
2568
2569 after <scroll-up> [
2570 trace 10, [app], [scroll up]
2571 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
2572 old-top:&:duplex-list:char <- copy top-of-screen
2573 top-of-screen <- before-previous-line top-of-screen, editor
2574 *editor <- put *editor, top-of-screen:offset, top-of-screen
2575 no-movement?:bool <- equal old-top, top-of-screen
2576 return-if no-movement?, 0/don't-render
2577 ]
2578
2579
2580
2581
2582
2583 def before-previous-line in:&:duplex-list:char, editor:&:editor -> out:&:duplex-list:char [
2584 local-scope
2585 load-ingredients
2586 curr:&:duplex-list:char <- copy in
2587 c:char <- get *curr, value:offset
2588
2589
2590
2591 left:num <- get *editor, left:offset
2592 right:num <- get *editor, right:offset
2593 max-line-length:num <- subtract right, left, -1/exclusive-right, 1/wrap-icon
2594 sentinel:&:duplex-list:char <- get *editor, data:offset
2595 len:num <- previous-line-length curr, sentinel
2596 {
2597 ¦ break-if len
2598 ¦
2599 ¦ prev:&:duplex-list:char <- prev curr
2600 ¦ return-unless prev, curr
2601 ¦ return prev
2602 }
2603 _, max:num <- divide-with-remainder len, max-line-length
2604
2605 {
2606 ¦ break-if max
2607 ¦ max <- copy max-line-length
2608 }
2609 max <- add max, 1
2610 count:num <- copy 0
2611
2612 {
2613 ¦ done?:bool <- greater-or-equal count, max
2614 ¦ break-if done?
2615 ¦ prev:&:duplex-list:char <- prev curr
2616 ¦ break-unless prev
2617 ¦ curr <- copy prev
2618 ¦ count <- add count, 1
2619 ¦ loop
2620 }
2621 return curr
2622 ]
2623
2624 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys [
2625 local-scope
2626
2627 assume-screen 10/width, 4/height
2628
2629
2630 s:text <- new [abcdef
2631 g
2632 h
2633 i]
2634 e:&:editor <- new-editor s, 0/left, 5/right
2635 editor-render screen, e
2636 screen-should-contain [
2637 ¦ . .
2638 ¦ .abcd↩ .
2639 ¦ .ef .
2640 ¦ .g .
2641 ]
2642
2643 assume-console [
2644 ¦ press page-down
2645 ]
2646 run [
2647 ¦ editor-event-loop screen, console, e
2648 ]
2649 screen-should-contain [
2650 ¦ . .
2651 ¦ .g .
2652 ¦ .h .
2653 ¦ .i .
2654 ]
2655
2656 assume-console [
2657 ¦ press up-arrow
2658 ]
2659 run [
2660 ¦ editor-event-loop screen, console, e
2661 ]
2662
2663 screen-should-contain [
2664 ¦ . .
2665 ¦ .ef .
2666 ¦ .g .
2667 ¦ .h .
2668 ]
2669 ]
2670
2671 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-2 [
2672 local-scope
2673
2674 assume-screen 10/width, 5/height
2675
2676 s:text <- new [abcdefghij
2677 k
2678 l
2679 m]
2680 e:&:editor <- new-editor s, 0/left, 5/right
2681 editor-render screen, e
2682
2683 assume-console [
2684 ¦ press page-down
2685 ]
2686 run [
2687 ¦ editor-event-loop screen, console, e
2688 ]
2689 screen-should-contain [
2690 ¦ . .
2691 ¦ .k .
2692 ¦ .l .
2693 ¦ .m .
2694 ¦ .╌╌╌╌╌ .
2695 ]
2696
2697 assume-console [
2698 ¦ press up-arrow
2699 ]
2700 run [
2701 ¦ editor-event-loop screen, console, e
2702 ]
2703
2704 screen-should-contain [
2705 ¦ . .
2706 ¦ .ij .
2707 ¦ .k .
2708 ¦ .l .
2709 ¦ .m .
2710 ]
2711
2712 assume-console [
2713 ¦ press up-arrow
2714 ]
2715 run [
2716 ¦ editor-event-loop screen, console, e
2717 ]
2718
2719 screen-should-contain [
2720 ¦ . .
2721 ¦ .efgh↩ .
2722 ¦ .ij .
2723 ¦ .k .
2724 ¦ .l .
2725 ]
2726
2727 assume-console [
2728 ¦ press up-arrow
2729 ]
2730 run [
2731 ¦ editor-event-loop screen, console, e
2732 ]
2733
2734 screen-should-contain [
2735 ¦ . .
2736 ¦ .abcd↩ .
2737 ¦ .efgh↩ .
2738 ¦ .ij .
2739 ¦ .k .
2740 ]
2741 ]
2742
2743
2744
2745 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-3 [
2746 local-scope
2747
2748 assume-screen 10/width, 4/height
2749
2750
2751 s:text <- new [abcdef
2752 g
2753 h
2754 i]
2755 e:&:editor <- new-editor s, 0/left, 6/right
2756 editor-render screen, e
2757 screen-should-contain [
2758 ¦ . .
2759 ¦ .abcde↩ .
2760 ¦ .f .
2761 ¦ .g .
2762 ]
2763
2764 assume-console [
2765 ¦ press page-down
2766 ]
2767 run [
2768 ¦ editor-event-loop screen, console, e
2769 ]
2770 screen-should-contain [
2771 ¦ . .
2772 ¦ .g .
2773 ¦ .h .
2774 ¦ .i .
2775 ]
2776
2777 assume-console [
2778 ¦ press up-arrow
2779 ]
2780 run [
2781 ¦ editor-event-loop screen, console, e
2782 ]
2783
2784 screen-should-contain [
2785 ¦ . .
2786 ¦ .f .
2787 ¦ .g .
2788 ¦ .h .
2789 ]
2790 ]
2791
2792
2793 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [
2794 local-scope
2795 assume-screen 10/width, 4/height
2796
2797 s:text <- new [a
2798 b
2799
2800 c
2801 d
2802 e]
2803 e:&:editor <- new-editor s, 0/left, 6/right
2804 editor-render screen, e
2805 assume-console [
2806 ¦ press page-down
2807 ]
2808 run [
2809 ¦ editor-event-loop screen, console, e
2810 ]
2811 screen-should-contain [
2812 ¦ . .
2813 ¦ . .
2814 ¦ .c .
2815 ¦ .d .
2816 ]
2817 assume-console [
2818 ¦ press page-down
2819 ]
2820 run [
2821 ¦ editor-event-loop screen, console, e
2822 ]
2823 screen-should-contain [
2824 ¦ . .
2825 ¦ .d .
2826 ¦ .e .
2827 ¦ .╌╌╌╌╌╌ .
2828 ]
2829 assume-console [
2830 ¦ press page-up
2831 ]
2832 run [
2833 ¦ editor-event-loop screen, console, e
2834 ]
2835 screen-should-contain [
2836 ¦ . .
2837 ¦ . .
2838 ¦ .c .
2839 ¦ .d .
2840 ]
2841 ]
2842
2843 scenario editor-scrolls-up-on-left-arrow [
2844 local-scope
2845
2846 assume-screen 5/width, 4/height
2847
2848 s:text <- new [a
2849 b
2850 c
2851 d
2852 e]
2853 e:&:editor <- new-editor s, 0/left, 5/right
2854 editor-render screen, e
2855
2856 assume-console [
2857 ¦ press page-down
2858 ]
2859 run [
2860 ¦ editor-event-loop screen, console, e
2861 ]
2862 screen-should-contain [
2863 ¦ . .
2864 ¦ .c .
2865 ¦ .d .
2866 ¦ .e .
2867 ]
2868
2869 assume-console [
2870 ¦ press left-arrow
2871 ]
2872 run [
2873 ¦ editor-event-loop screen, console, e
2874 ¦ 3:num/raw <- get *e, cursor-row:offset
2875 ¦ 4:num/raw <- get *e, cursor-column:offset
2876 ]
2877
2878 screen-should-contain [
2879 ¦ . .
2880 ¦ .b .
2881 ¦ .c .
2882 ¦ .d .
2883 ]
2884 memory-should-contain [
2885 ¦ 3 <- 1
2886 ¦ 4 <- 1
2887 ]
2888 ]
2889
2890 scenario editor-can-scroll-up-to-start-of-file [
2891 local-scope
2892
2893 assume-screen 10/width, 4/height
2894
2895 s:text <- new [a
2896 b
2897 c
2898 d]
2899 e:&:editor <- new-editor s, 0/left, 10/right
2900 editor-render screen, e
2901 screen-should-contain [
2902 ¦ . .
2903 ¦ .a .
2904 ¦ .b .
2905 ¦ .c .
2906 ]
2907
2908
2909 assume-console [
2910 ¦ press page-down
2911 ¦ press up-arrow
2912 ¦ press up-arrow
2913 ]
2914 run [
2915 ¦ editor-event-loop screen, console, e
2916 ]
2917
2918 screen-should-contain [
2919 ¦ . .
2920 ¦ .a .
2921 ¦ .b .
2922 ¦ .c .
2923 ]
2924
2925 assume-console [
2926 ¦ press up-arrow
2927 ]
2928 run [
2929 ¦ editor-event-loop screen, console, e
2930 ]
2931
2932 screen-should-contain [
2933 ¦ . .
2934 ¦ .a .
2935 ¦ .b .
2936 ¦ .c .
2937 ]
2938 ]
2939
2940
2941
2942 scenario editor-can-scroll [
2943 local-scope
2944 assume-screen 10/width, 4/height
2945 s:text <- new [a
2946 b
2947 c
2948 d]
2949 e:&:editor <- new-editor s, 0/left, 10/right
2950 editor-render screen, e
2951 screen-should-contain [
2952 ¦ . .
2953 ¦ .a .
2954 ¦ .b .
2955 ¦ .c .
2956 ]
2957
2958 assume-console [
2959 ¦ press page-down
2960 ]
2961 run [
2962 ¦ editor-event-loop screen, console, e
2963 ]
2964
2965 screen-should-contain [
2966 ¦ . .
2967 ¦ .c .
2968 ¦ .d .
2969 ¦ .╌╌╌╌╌╌╌╌╌╌.
2970 ]
2971 ]
2972
2973 after <handle-special-character> [
2974 {
2975 ¦ page-down?:bool <- equal c, 6/ctrl-f
2976 ¦ break-unless page-down?
2977 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
2978 ¦ <move-cursor-begin>
2979 ¦ page-down editor
2980 ¦ undo-coalesce-tag:num <- copy 0/never
2981 ¦ <move-cursor-end>
2982 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
2983 ¦ movement?:bool <- not-equal top-of-screen, old-top
2984 ¦ return movement?/go-render
2985 }
2986 ]
2987
2988 after <handle-special-key> [
2989 {
2990 ¦ page-down?:bool <- equal k, 65518/page-down
2991 ¦ break-unless page-down?
2992 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
2993 ¦ <move-cursor-begin>
2994 ¦ page-down editor
2995 ¦ undo-coalesce-tag:num <- copy 0/never
2996 ¦ <move-cursor-end>
2997 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
2998 ¦ movement?:bool <- not-equal top-of-screen, old-top
2999 ¦ return movement?/go-render
3000 }
3001 ]
3002
3003
3004
3005 def page-down editor:&:editor -> editor:&:editor [
3006 local-scope
3007 load-ingredients
3008
3009 bottom-of-screen:&:duplex-list:char <- get *editor, bottom-of-screen:offset
3010 return-unless bottom-of-screen
3011
3012 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
3013 before-cursor:&:duplex-list:char <- prev bottom-of-screen
3014 *editor <- put *editor, before-cursor:offset, before-cursor
3015
3016 {
3017 ¦ last:char <- get *before-cursor, value:offset
3018 ¦ newline?:bool <- equal last, 10/newline
3019 ¦ break-unless newline?:bool
3020 ¦ before-cursor <- prev before-cursor
3021 ¦ *editor <- put *editor, before-cursor:offset, before-cursor
3022 }
3023
3024 move-to-start-of-line editor
3025 before-cursor <- get *editor, before-cursor:offset
3026 *editor <- put *editor, top-of-screen:offset, before-cursor
3027 ]
3028
3029 scenario editor-does-not-scroll-past-end [
3030 local-scope
3031 assume-screen 10/width, 4/height
3032 s:text <- new [a
3033 b]
3034 e:&:editor <- new-editor s, 0/left, 10/right
3035 editor-render screen, e
3036 screen-should-contain [
3037 ¦ . .
3038 ¦ .a .
3039 ¦ .b .
3040 ¦ .╌╌╌╌╌╌╌╌╌╌.
3041 ]
3042
3043 assume-console [
3044 ¦ press page-down
3045 ]
3046 run [
3047 ¦ editor-event-loop screen, console, e
3048 ]
3049
3050 screen-should-contain [
3051 ¦ . .
3052 ¦ .a .
3053 ¦ .b .
3054 ¦ .╌╌╌╌╌╌╌╌╌╌.
3055 ]
3056 ]
3057
3058 scenario editor-starts-next-page-at-start-of-wrapped-line [
3059 local-scope
3060
3061 assume-screen 10/width, 4/height
3062
3063 s:text <- new [a
3064 b
3065 cdefgh]
3066
3067 e:&:editor <- new-editor s, 0/left, 4/right
3068 editor-render screen, e
3069
3070 screen-should-contain [
3071 ¦ . .
3072 ¦ .a .
3073 ¦ .b .
3074 ¦ .cde↩ .
3075 ]
3076
3077 assume-console [
3078 ¦ press page-down
3079 ]
3080 run [
3081 ¦ editor-event-loop screen, console, e
3082 ]
3083
3084 screen-should-contain [
3085 ¦ . .
3086 ¦ .cde↩ .
3087 ¦ .fgh .
3088 ¦ .╌╌╌╌ .
3089 ]
3090 ]
3091
3092 scenario editor-starts-next-page-at-start-of-wrapped-line-2 [
3093 local-scope
3094
3095 assume-screen 10/width, 4/height
3096
3097
3098 s:text <- new [a
3099 bcdefgh]
3100 e:&:editor <- new-editor s, 0/left, 4/right
3101 editor-render screen, e
3102
3103 screen-should-contain [
3104 ¦ . .
3105 ¦ .a .
3106 ¦ .bcd↩ .
3107 ¦ .efg↩ .
3108 ]
3109
3110 assume-console [
3111 ¦ press page-down
3112 ]
3113 run [
3114 ¦ editor-event-loop screen, console, e
3115 ]
3116
3117 screen-should-contain [
3118 ¦ . .
3119 ¦ .bcd↩ .
3120 ¦ .efg↩ .
3121 ¦ .h .
3122 ]
3123 ]
3124
3125
3126
3127 scenario editor-can-scroll-up [
3128 local-scope
3129 assume-screen 10/width, 4/height
3130 s:text <- new [a
3131 b
3132 c
3133 d]
3134 e:&:editor <- new-editor s, 0/left, 10/right
3135 editor-render screen, e
3136 screen-should-contain [
3137 ¦ . .
3138 ¦ .a .
3139 ¦ .b .
3140 ¦ .c .
3141 ]
3142
3143 assume-console [
3144 ¦ press page-down
3145 ]
3146 run [
3147 ¦ editor-event-loop screen, console, e
3148 ]
3149
3150 screen-should-contain [
3151 ¦ . .
3152 ¦ .c .
3153 ¦ .d .
3154 ¦ .╌╌╌╌╌╌╌╌╌╌.
3155 ]
3156
3157 assume-console [
3158 ¦ press page-up
3159 ]
3160 run [
3161 ¦ editor-event-loop screen, console, e
3162 ]
3163
3164 screen-should-contain [
3165 ¦ . .
3166 ¦ .a .
3167 ¦ .b .
3168 ¦ .c .
3169 ]
3170 ]
3171
3172 after <handle-special-character> [
3173 {
3174 ¦ page-up?:bool <- equal c, 2/ctrl-b
3175 ¦ break-unless page-up?
3176 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
3177 ¦ <move-cursor-begin>
3178 ¦ editor <- page-up editor, screen-height
3179 ¦ undo-coalesce-tag:num <- copy 0/never
3180 ¦ <move-cursor-end>
3181 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
3182 ¦ movement?:bool <- not-equal top-of-screen, old-top
3183 ¦ return movement?/go-render
3184 }
3185 ]
3186
3187 after <handle-special-key> [
3188 {
3189 ¦ page-up?:bool <- equal k, 65519/page-up
3190 ¦ break-unless page-up?
3191 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
3192 ¦ <move-cursor-begin>
3193 ¦ editor <- page-up editor, screen-height
3194 ¦ undo-coalesce-tag:num <- copy 0/never
3195 ¦ <move-cursor-end>
3196 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
3197 ¦ movement?:bool <- not-equal top-of-screen, old-top
3198 ¦
3199 ¦ return movement?/go-render
3200 }
3201 ]
3202
3203 def page-up editor:&:editor, screen-height:num -> editor:&:editor [
3204 local-scope
3205 load-ingredients
3206 max:num <- subtract screen-height, 1/menu-bar, 1/overlapping-line
3207 count:num <- copy 0
3208 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset
3209 {
3210 ¦ done?:bool <- greater-or-equal count, max
3211 ¦ break-if done?
3212 ¦ prev:&:duplex-list:char <- before-previous-line top-of-screen, editor
3213 ¦ break-unless prev
3214 ¦ top-of-screen <- copy prev
3215 ¦ *editor <- put *editor, top-of-screen:offset, top-of-screen
3216 ¦ count <- add count, 1
3217 ¦ loop
3218 }
3219 ]
3220
3221 scenario editor-can-scroll-up-multiple-pages [
3222 local-scope
3223
3224 assume-screen 10/width, 4/height
3225
3226 s:text <- new [a
3227 b
3228 c
3229 d
3230 e
3231 f
3232 g
3233 h]
3234 e:&:editor <- new-editor s, 0/left, 10/right
3235 editor-render screen, e
3236 screen-should-contain [
3237 ¦ . .
3238 ¦ .a .
3239 ¦ .b .
3240 ¦ .c .
3241 ]
3242
3243 assume-console [
3244 ¦ press page-down
3245 ¦ press page-down
3246 ]
3247 run [
3248 ¦ editor-event-loop screen, console, e
3249 ]
3250
3251 screen-should-contain [
3252 ¦ . .
3253 ¦ .e .
3254 ¦ .f .
3255 ¦ .g .
3256 ]
3257
3258 assume-console [
3259 ¦ press page-up
3260 ]
3261 run [
3262 ¦ editor-event-loop screen, console, e
3263 ]
3264
3265 screen-should-contain [
3266 ¦ . .
3267 ¦ .c .
3268 ¦ .d .
3269 ¦ .e .
3270 ]
3271
3272 assume-console [
3273 ¦ press page-up
3274 ]
3275 run [
3276 ¦ editor-event-loop screen, console, e
3277 ]
3278
3279 screen-should-contain [
3280 ¦ . .
3281 ¦ .a .
3282 ¦ .b .
3283 ¦ .c .
3284 ]
3285 ]
3286
3287 scenario editor-can-scroll-up-wrapped-lines [
3288 local-scope
3289
3290 assume-screen 10/width, 6/height
3291
3292 s:text <- new [a
3293 b
3294 cdefgh
3295 i
3296 j
3297 k
3298 l
3299 m
3300 n
3301 o]
3302
3303 e:&:editor <- new-editor s, 0/left, 4/right
3304 editor-render screen, e
3305
3306 screen-should-contain [
3307 ¦ . .
3308 ¦ .a .
3309 ¦ .b .
3310 ¦ .cde↩ .
3311 ¦ .fgh .
3312 ¦ .i .
3313 ]
3314
3315 assume-console [
3316 ¦ press page-down
3317 ¦ left-click 5, 0
3318 ¦ press down-arrow
3319 ]
3320 run [
3321 ¦ editor-event-loop screen, console, e
3322 ]
3323
3324 screen-should-contain [
3325 ¦ . .
3326 ¦ .j .
3327 ¦ .k .
3328 ¦ .l .
3329 ¦ .m .
3330 ¦ .n .
3331 ]
3332
3333 assume-console [
3334 ¦ press page-up
3335 ]
3336 run [
3337 ¦ editor-event-loop screen, console, e
3338 ]
3339
3340 screen-should-contain [
3341 ¦ . .
3342 ¦ .b .
3343 ¦ .cde↩ .
3344 ¦ .fgh .
3345 ¦ .i .
3346 ¦ .j .
3347 ]
3348 ]
3349
3350 scenario editor-can-scroll-up-wrapped-lines-2 [
3351 local-scope
3352
3353 assume-screen 10/width, 4/height
3354
3355
3356 s:text <- new [a
3357 bcdefgh]
3358 e:&:editor <- new-editor s, 0/left, 4/right
3359 editor-render screen, e
3360
3361 screen-should-contain [
3362 ¦ . .
3363 ¦ .a .
3364 ¦ .bcd↩ .
3365 ¦ .efg↩ .
3366 ]
3367
3368 assume-console [
3369 ¦ press page-down
3370 ]
3371 run [
3372 ¦ editor-event-loop screen, console, e
3373 ]
3374
3375 screen-should-contain [
3376 ¦ . .
3377 ¦ .bcd↩ .
3378 ¦ .efg↩ .
3379 ¦ .h .
3380 ]
3381
3382 assume-console [
3383 ¦ press page-up
3384 ]
3385 run [
3386 ¦ editor-event-loop screen, console, e
3387 ]
3388
3389 screen-should-contain [
3390 ¦ . .
3391 ¦ .a .
3392 ¦ .bcd↩ .
3393 ¦ .efg↩ .
3394 ]
3395 ]
3396
3397 scenario editor-can-scroll-up-past-nonempty-lines [
3398 local-scope
3399 assume-screen 10/width, 4/height
3400
3401 s:text <- new [axx
3402 bxx
3403 cxx
3404 dxx
3405 exx
3406 fxx
3407 gxx
3408 hxx
3409 ]
3410 e:&:editor <- new-editor s, 0/left, 4/right
3411 editor-render screen, e
3412 screen-should-contain [
3413 ¦ . .
3414 ¦ .axx .
3415 ¦ .bxx .
3416 ¦ .cxx .
3417 ]
3418 assume-console [
3419 ¦ press page-down
3420 ]
3421 run [
3422 ¦ editor-event-loop screen, console, e
3423 ]
3424 screen-should-contain [
3425 ¦ . .
3426 ¦ .cxx .
3427 ¦ .dxx .
3428 ¦ .exx .
3429 ]
3430 assume-console [
3431 ¦ press page-down
3432 ]
3433 run [
3434 ¦ editor-event-loop screen, console, e
3435 ]
3436 screen-should-contain [
3437 ¦ . .
3438 ¦ .exx .
3439 ¦ .fxx .
3440 ¦ .gxx .
3441 ]
3442
3443 assume-console [
3444 ¦ press page-up
3445 ]
3446 run [
3447 ¦ editor-event-loop screen, console, e
3448 ]
3449 screen-should-contain [
3450 ¦ . .
3451 ¦ .cxx .
3452 ¦ .dxx .
3453 ¦ .exx .
3454 ]
3455 ]
3456
3457 scenario editor-can-scroll-up-past-empty-lines [
3458 local-scope
3459 assume-screen 10/width, 4/height
3460
3461 s:text <- new [axy
3462 bxy
3463 cxy
3464
3465 dxy
3466 exy
3467 fxy
3468 gxy
3469 ]
3470 e:&:editor <- new-editor s, 0/left, 4/right
3471 editor-render screen, e
3472 screen-should-contain [
3473 ¦ . .
3474 ¦ .axy .
3475 ¦ .bxy .
3476 ¦ .cxy .
3477 ]
3478 assume-console [
3479 ¦ press page-down
3480 ]
3481 run [
3482 ¦ editor-event-loop screen, console, e
3483 ]
3484 screen-should-contain [
3485 ¦ . .
3486 ¦ .cxy .
3487 ¦ . .
3488 ¦ .dxy .
3489 ]
3490 assume-console [
3491 ¦ press page-down
3492 ]
3493 run [
3494 ¦ editor-event-loop screen, console, e
3495 ]
3496 screen-should-contain [
3497 ¦ . .
3498 ¦ .dxy .
3499 ¦ .exy .
3500 ¦ .fxy .
3501 ]
3502
3503 assume-console [
3504 ¦ press page-up
3505 ]
3506 run [
3507 ¦ editor-event-loop screen, console, e
3508 ]
3509 screen-should-contain [
3510 ¦ . .
3511 ¦ .cxy .
3512 ¦ . .
3513 ¦ .dxy .
3514 ]
3515 ]
3516
3517
3518
3519
3520 after <handle-special-character> [
3521 {
3522 ¦ scroll-up?:bool <- equal c, 19/ctrl-s
3523 ¦ break-unless scroll-up?
3524 ¦ <move-cursor-begin>
3525 ¦ go-render?:bool, editor <- line-up editor, screen-height
3526 ¦ undo-coalesce-tag:num <- copy 5/line-up
3527 ¦ <move-cursor-end>
3528 ¦ return go-render?
3529 }
3530 ]
3531
3532 def line-up editor:&:editor, screen-height:num -> go-render?:bool, editor:&:editor [
3533 local-scope
3534 load-ingredients
3535 left:num <- get *editor, left:offset
3536 right:num <- get *editor, right:offset
3537 max:num <- subtract right, left
3538 old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
3539 new-top:&:duplex-list:char <- before-start-of-next-line old-top, max
3540 movement?:bool <- not-equal old-top, new-top
3541 {
3542 ¦ break-unless movement?
3543 ¦ *editor <- put *editor, top-of-screen:offset, new-top
3544 }
3545 return movement?
3546 ]
3547
3548
3549
3550
3551 after <handle-special-character> [
3552 {
3553 ¦ scroll-down?:bool <- equal c, 24/ctrl-x
3554 ¦ break-unless scroll-down?
3555 ¦ <move-cursor-begin>
3556 ¦ go-render?:bool, editor <- line-down editor, screen-height
3557 ¦ undo-coalesce-tag:num <- copy 6/line-down
3558 ¦ <move-cursor-end>
3559 ¦ return go-render?
3560 }
3561 ]
3562
3563 def line-down editor:&:editor, screen-height:num -> go-render?:bool, editor:&:editor [
3564 local-scope
3565 load-ingredients
3566 old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
3567 new-top:&:duplex-list:char <- before-previous-line old-top, editor
3568 movement?:bool <- not-equal old-top, new-top
3569 {
3570 ¦ break-unless movement?
3571 ¦ *editor <- put *editor, top-of-screen:offset, new-top
3572 }
3573 return movement?
3574 ]
3575
3576
3577
3578
3579 after <handle-special-character> [
3580 {
3581 ¦ scroll-down?:bool <- equal c, 20/ctrl-t
3582 ¦ break-unless scroll-down?
3583 ¦ <move-cursor-begin>
3584 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset
3585 ¦ cursor:&:duplex-list:char <- get *editor, before-cursor:offset
3586 ¦ cursor <- next cursor
3587 ¦ new-top:&:duplex-list:char <- before-previous-line cursor, editor
3588 ¦ *editor <- put *editor, top-of-screen:offset, new-top
3589 ¦ *editor <- put *editor, cursor-row:offset, 1
3590 ¦ go-render?:bool <- not-equal new-top, old-top
3591 ¦ undo-coalesce-tag:num <- copy 0/never
3592 ¦ <move-cursor-end>
3593 ¦ return go-render?
3594 }
3595 ]
3596
3597
3598
3599
3600 after <handle-special-character> [
3601 {
3602 ¦ comment-toggle?:bool <- equal c, 31/ctrl-slash
3603 ¦ break-unless comment-toggle?
3604 ¦ cursor-column:num <- get *editor, cursor-column:offset
3605 ¦ data:&:duplex-list:char <- get *editor, data:offset
3606 ¦ <insert-character-begin>
3607 ¦ cursor:&:duplex-list:char <- get *editor, before-cursor:offset
3608 ¦ {
3609 ¦ ¦ next:&:duplex-list:char <- next cursor
3610 ¦ ¦ break-unless next
3611 ¦ ¦ cursor <- copy next
3612 ¦ }
3613 ¦ before-line-start:&:duplex-list:char <- before-previous-line cursor, editor
3614 ¦ line-start:&:duplex-list:char <- next before-line-start
3615 ¦ commented-out?:bool <- match line-start, [#? ]
3616 ¦ {
3617 ¦ ¦ break-unless commented-out?
3618 ¦ ¦
3619 ¦ ¦ data <- remove line-start, 3/length-comment-prefix, data
3620 ¦ ¦ cursor-column <- subtract cursor-column, 3/length-comment-prefix
3621 ¦ }
3622 ¦ {
3623 ¦ ¦ break-if commented-out?
3624 ¦ ¦
3625 ¦ ¦ insert before-line-start, [#? ]
3626 ¦ ¦ cursor-column <- add cursor-column, 3/length-comment-prefix
3627 ¦ }
3628 ¦ *editor <- put *editor, cursor-column:offset, cursor-column
3629 ¦ <insert-character-end>
3630 ¦ return 1/do-render
3631 }
3632 ]
3633
3634 scenario editor-comments-empty-line [
3635 local-scope
3636 assume-screen 10/width, 5/height
3637 e:&:editor <- new-editor [], 0/left, 5/right
3638 assume-console [
3639 ¦ press ctrl-slash
3640 ]
3641 run [
3642 ¦ editor-event-loop screen, console, e
3643 ¦ 4:num/raw <- get *e, cursor-row:offset
3644 ¦ 5:num/raw <- get *e, cursor-column:offset
3645 ]
3646 screen-should-contain [
3647 ¦ . .
3648 ¦ .#? .
3649 ¦ .╌╌╌╌╌ .
3650 ¦ . .
3651 ]
3652 memory-should-contain [
3653 ¦ 4 <- 1
3654 ¦ 5 <- 3
3655 ]
3656 ]
3657
3658 scenario editor-comments-at-start-of-contents [
3659 local-scope
3660 assume-screen 10/width, 5/height
3661 e:&:editor <- new-editor [ab], 0/left, 10/right
3662 assume-console [
3663 ¦ press ctrl-slash
3664 ]
3665 run [
3666 ¦ editor-event-loop screen, console, e
3667 ¦ 4:num/raw <- get *e, cursor-row:offset
3668 ¦ 5:num/raw <- get *e, cursor-column:offset
3669 ]
3670 screen-should-contain [
3671 ¦ . .
3672 ¦ .#? ab .
3673 ¦ .╌╌╌╌╌╌╌╌╌╌.
3674 ¦ . .
3675 ]
3676 memory-should-contain [
3677 ¦ 4 <- 1
3678 ¦ 5 <- 3
3679 ]
3680 ]
3681
3682 scenario editor-comments-at-end-of-contents [
3683 local-scope
3684 assume-screen 10/width, 5/height
3685 e:&:editor <- new-editor [ab], 0/left, 10/right
3686 assume-console [
3687 ¦ left-click 1, 7
3688 ¦ press ctrl-slash
3689 ]
3690 run [
3691 ¦ editor-event-loop screen, console, e
3692 ¦ 4:num/raw <- get *e, cursor-row:offset
3693 ¦ 5:num/raw <- get *e, cursor-column:offset
3694 ]
3695 screen-should-contain [
3696 ¦ . .
3697 ¦ .#? ab .
3698 ¦ .╌╌╌╌╌╌╌╌╌╌.
3699 ¦ . .
3700 ]
3701 memory-should-contain [
3702 ¦ 4 <- 1
3703 ¦ 5 <- 5
3704 ]
3705 ]