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 editor-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 e:&:editor <- new-editor [abcd], 0/left, 5/right
34 editor-render screen, e
35 $clear-trace
36 assume-console [
37 press tab
38 ]
39 run [
40 editor-event-loop screen, console, e
41 ]
42 screen-should-contain [
43 . .
44 . ab↩ .
45 .cd .
46 ]
47
48 check-trace-count-for-label-greater-than 10, [print-character]
49 ]
50
51 after <handle-special-character> [
52 {
53 tab?:bool <- equal c, 9/tab
54 break-unless tab?
55 <begin-insert-character>
56
57
58 insert-at-cursor editor, 32/space, screen
59 go-render? <- insert-at-cursor editor, 32/space, screen
60 <end-insert-character>
61 return
62 }
63 ]
64
65
66
67 scenario editor-handles-backspace-key [
68 local-scope
69 assume-screen 10/width, 5/height
70 e:&:editor <- new-editor [abc], 0/left, 10/right
71 editor-render screen, e
72 $clear-trace
73 assume-console [
74 left-click 1, 1
75 press backspace
76 ]
77 run [
78 editor-event-loop screen, console, e
79 4:num/raw <- get *e, cursor-row:offset
80 5:num/raw <- get *e, cursor-column:offset
81 ]
82 screen-should-contain [
83 . .
84 .bc .
85 .╌╌╌╌╌╌╌╌╌╌.
86 . .
87 ]
88 memory-should-contain [
89 4 <- 1
90 5 <- 0
91 ]
92 check-trace-count-for-label 3, [print-character]
93 ]
94
95 after <handle-special-character> [
96 {
97 delete-previous-character?:bool <- equal c, 8/backspace
98 break-unless delete-previous-character?
99 <begin-backspace-character>
100 go-render?:bool, backspaced-cell:&:duplex-list:char <- delete-before-cursor editor, screen
101 <end-backspace-character>
102 return
103 }
104 ]
105
106
107
108
109 def delete-before-cursor editor:&:editor, screen:&:screen -> go-render?:bool, backspaced-cell:&:duplex-list:char, editor:&:editor, screen:&:screen [
110 local-scope
111 load-inputs
112 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
113 data:&:duplex-list:char <- get *editor, data:offset
114
115 prev:&:duplex-list:char <- prev before-cursor
116 return-unless prev, 0/no-more-render, 0/nothing-deleted
117 trace 10, [app], [delete-before-cursor]
118 original-row:num <- get *editor, cursor-row:offset
119 scroll?:bool <- move-cursor-coordinates-left editor
120 backspaced-cell:&:duplex-list:char <- copy before-cursor
121 data <- remove before-cursor, data
122 before-cursor <- copy prev
123 *editor <- put *editor, before-cursor:offset, before-cursor
124 return-if scroll?, 1/go-render
125 screen-width:num <- screen-width screen
126 cursor-row:num <- get *editor, cursor-row:offset
127 cursor-column:num <- get *editor, cursor-column:offset
128
129 same-row?:bool <- equal cursor-row, original-row
130 return-unless same-row?, 1/go-render
131 left:num <- get *editor, left:offset
132 right:num <- get *editor, right:offset
133 curr:&:duplex-list:char <- next before-cursor
134 screen <- move-cursor screen, cursor-row, cursor-column
135 curr-column:num <- copy cursor-column
136 {
137
138 at-right?:bool <- greater-or-equal curr-column, right
139 return-if at-right?, 1/go-render
140 break-unless curr
141
142 currc:char <- get *curr, value:offset
143 at-newline?:bool <- equal currc, 10/newline
144 break-if at-newline?
145 screen <- print screen, currc
146 curr-column <- add curr-column, 1
147 curr <- next curr
148 loop
149 }
150
151 space:char <- copy 32/space
152 screen <- print screen, space
153 go-render? <- copy 0/false
154 ]
155
156 def move-cursor-coordinates-left editor:&:editor -> go-render?:bool, editor:&:editor [
157 local-scope
158 load-inputs
159 go-render?:bool <- copy 0/false
160 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
161 cursor-row:num <- get *editor, cursor-row:offset
162 cursor-column:num <- get *editor, cursor-column:offset
163 left:num <- get *editor, left:offset
164
165 {
166 at-left-margin?:bool <- equal cursor-column, left
167 break-if at-left-margin?
168 trace 10, [app], [decrementing cursor column]
169 cursor-column <- subtract cursor-column, 1
170 *editor <- put *editor, cursor-column:offset, cursor-column
171 return
172 }
173
174 top-of-screen?:bool <- equal cursor-row, 1
175 {
176 break-if top-of-screen?
177 cursor-row <- subtract cursor-row, 1
178 *editor <- put *editor, cursor-row:offset, cursor-row
179 }
180 {
181 break-unless top-of-screen?
182 <scroll-up>
183 go-render? <- copy 1/true
184 }
185 {
186
187 previous-character:char <- get *before-cursor, value:offset
188 previous-character-is-newline?:bool <- equal previous-character, 10/newline
189 break-unless previous-character-is-newline?
190
191 trace 10, [app], [switching to previous line]
192 d:&:duplex-list:char <- get *editor, data:offset
193 end-of-line:num <- previous-line-length before-cursor, d
194 right:num <- get *editor, right:offset
195 width:num <- subtract right, left
196 wrap?:bool <- greater-than end-of-line, width
197 {
198 break-unless wrap?
199 _, column-offset:num <- divide-with-remainder end-of-line, width
200 cursor-column <- add left, column-offset
201 *editor <- put *editor, cursor-column:offset, cursor-column
202 }
203 {
204 break-if wrap?
205 cursor-column <- add left, end-of-line
206 *editor <- put *editor, cursor-column:offset, cursor-column
207 }
208 return
209 }
210
211 trace 10, [app], [wrapping to previous line]
212 right:num <- get *editor, right:offset
213 cursor-column <- subtract right, 1
214 *editor <- put *editor, cursor-column:offset, cursor-column
215 ]
216
217
218
219 def previous-line-length curr:&:duplex-list:char, start:&:duplex-list:char -> result:num [
220 local-scope
221 load-inputs
222 result:num <- copy 0
223 return-unless curr
224 at-start?:bool <- equal curr, start
225 return-if at-start?
226 {
227 curr <- prev curr
228 break-unless curr
229 at-start?:bool <- equal curr, start
230 break-if at-start?
231 c:char <- get *curr, value:offset
232 at-newline?:bool <- equal c, 10/newline
233 break-if at-newline?
234 result <- add result, 1
235 loop
236 }
237 ]
238
239 scenario editor-clears-last-line-on-backspace [
240 local-scope
241 assume-screen 10/width, 5/height
242 s:text <- new [ab
243 cd]
244 e:&:editor <- new-editor s, 0/left, 10/right
245 assume-console [
246 left-click 2, 0
247 press backspace
248 ]
249 run [
250 editor-event-loop screen, console, e
251 4:num/raw <- get *e, cursor-row:offset
252 5:num/raw <- get *e, cursor-column:offset
253 ]
254 screen-should-contain [
255 . .
256 .abcd .
257 .╌╌╌╌╌╌╌╌╌╌.
258 . .
259 ]
260 memory-should-contain [
261 4 <- 1
262 5 <- 2
263 ]
264 ]
265
266 scenario editor-joins-and-wraps-lines-on-backspace [
267 local-scope
268 assume-screen 10/width, 5/height
269
270 s:text <- new [abc def
271 ghi jkl]
272 e:&:editor <- new-editor s, 0/left, 10/right
273 editor-render screen, e
274 $clear-trace
275
276 assume-console [
277 left-click 2, 0
278 press backspace
279 ]
280 run [
281 editor-event-loop screen, console, e
282 ]
283
284 screen-should-contain [
285 . .
286 .abc defgh↩.
287 .i jkl .
288 .╌╌╌╌╌╌╌╌╌╌.
289 . .
290 ]
291 ]
292
293 scenario editor-wraps-long-lines-on-backspace [
294 local-scope
295 assume-screen 10/width, 5/height
296
297 e:&:editor <- new-editor [abc def ghij], 0/left, 8/right
298 editor-render screen, e
299
300 screen-should-contain [
301 . .
302 .abc def↩ .
303 . ghij .
304 .╌╌╌╌╌╌╌╌ .
305 ]
306 $clear-trace
307
308 assume-console [
309 left-click 1, 4
310 press backspace
311 ]
312 run [
313 editor-event-loop screen, console, e
314 ]
315
316 screen-should-contain [
317 . .
318 .abcdef ↩ .
319 .ghij .
320 .╌╌╌╌╌╌╌╌ .
321 . .
322 ]
323 ]
324
325
326
327 scenario editor-handles-delete-key [
328 local-scope
329 assume-screen 10/width, 5/height
330 e:&:editor <- new-editor [abc], 0/left, 10/right
331 editor-render screen, e
332 $clear-trace
333 assume-console [
334 press delete
335 ]
336 run [
337 editor-event-loop screen, console, e
338 ]
339 screen-should-contain [
340 . .
341 .bc .
342 .╌╌╌╌╌╌╌╌╌╌.
343 . .
344 ]
345 check-trace-count-for-label 3, [print-character]
346 $clear-trace
347 assume-console [
348 press delete
349 ]
350 run [
351 editor-event-loop screen, console, e
352 ]
353 screen-should-contain [
354 . .
355 .c .
356 .╌╌╌╌╌╌╌╌╌╌.
357 . .
358 ]
359 check-trace-count-for-label 2, [print-character]
360 ]
361
362 after <handle-special-key> [
363 {
364 delete-next-character?:bool <- equal k, 65522/delete
365 break-unless delete-next-character?
366 <begin-delete-character>
367 go-render?:bool, deleted-cell:&:duplex-list:char <- delete-at-cursor editor, screen
368 <end-delete-character>
369 return
370 }
371 ]
372
373 def delete-at-cursor editor:&:editor, screen:&:screen -> go-render?:bool, deleted-cell:&:duplex-list:char, editor:&:editor, screen:&:screen [
374 local-scope
375 load-inputs
376 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
377 data:&:duplex-list:char <- get *editor, data:offset
378 deleted-cell:&:duplex-list:char <- next before-cursor
379 return-unless deleted-cell, 0/don't-render
380 currc:char <- get *deleted-cell, value:offset
381 data <- remove deleted-cell, data
382 deleted-newline?:bool <- equal currc, 10/newline
383 return-if deleted-newline?, 1/go-render
384
385 curr:&:duplex-list:char <- next before-cursor
386 cursor-row:num <- get *editor, cursor-row:offset
387 cursor-column:num <- get *editor, cursor-column:offset
388 screen <- move-cursor screen, cursor-row, cursor-column
389 curr-column:num <- copy cursor-column
390 screen-width:num <- screen-width screen
391 {
392
393 at-right?:bool <- greater-or-equal curr-column, screen-width
394 return-if at-right?, 1/go-render
395 break-unless curr
396 currc:char <- get *curr, value:offset
397 at-newline?:bool <- equal currc, 10/newline
398 break-if at-newline?
399 screen <- print screen, currc
400 curr-column <- add curr-column, 1
401 curr <- next curr
402 loop
403 }
404
405 space:char <- copy 32/space
406 screen <- print screen, space
407 go-render? <- copy 0/false
408 ]
409
410
411
412 scenario editor-moves-cursor-right-with-key [
413 local-scope
414 assume-screen 10/width, 5/height
415 e:&:editor <- new-editor [abc], 0/left, 10/right
416 editor-render screen, e
417 $clear-trace
418 assume-console [
419 press right-arrow
420 type [0]
421 ]
422 run [
423 editor-event-loop screen, console, e
424 ]
425 screen-should-contain [
426 . .
427 .a0bc .
428 .╌╌╌╌╌╌╌╌╌╌.
429 . .
430 ]
431 check-trace-count-for-label 3, [print-character]
432 ]
433
434 after <handle-special-key> [
435 {
436 move-to-next-character?:bool <- equal k, 65514/right-arrow
437 break-unless move-to-next-character?
438
439 next-cursor:&:duplex-list:char <- next before-cursor
440 break-unless next-cursor
441
442 <begin-move-cursor>
443 before-cursor <- copy next-cursor
444 *editor <- put *editor, before-cursor:offset, before-cursor
445 go-render?:bool <- move-cursor-coordinates-right editor, screen-height
446 screen <- move-cursor screen, cursor-row, cursor-column
447 undo-coalesce-tag:num <- copy 2/right-arrow
448 <end-move-cursor>
449 return
450 }
451 ]
452
453 def move-cursor-coordinates-right editor:&:editor, screen-height:num -> go-render?:bool, editor:&:editor [
454 local-scope
455 load-inputs
456 before-cursor:&:duplex-list:char <- get *editor before-cursor:offset
457 cursor-row:num <- get *editor, cursor-row:offset
458 cursor-column:num <- get *editor, cursor-column:offset
459 left:num <- get *editor, left:offset
460 right:num <- get *editor, right:offset
461
462 {
463 old-cursor-character:char <- get *before-cursor, value:offset
464 was-at-newline?:bool <- equal old-cursor-character, 10/newline
465 break-unless was-at-newline?
466 cursor-row <- add cursor-row, 1
467 *editor <- put *editor, cursor-row:offset, cursor-row
468 cursor-column <- copy left
469 *editor <- put *editor, cursor-column:offset, cursor-column
470 below-screen?:bool <- greater-or-equal cursor-row, screen-height
471 return-unless below-screen?, 0/don't-render
472 <scroll-down>
473 cursor-row <- subtract cursor-row, 1
474 *editor <- put *editor, cursor-row:offset, cursor-row
475 return 1/go-render
476 }
477
478 {
479
480 wrap-column:num <- subtract right, 1
481 at-wrap?:bool <- equal cursor-column, wrap-column
482 break-unless at-wrap?
483
484 next:&:duplex-list:char <- next before-cursor
485 break-unless next
486 next-character:char <- get *next, value:offset
487 newline?:bool <- equal next-character, 10/newline
488 break-if newline?
489 cursor-row <- add cursor-row, 1
490 *editor <- put *editor, cursor-row:offset, cursor-row
491 cursor-column <- copy left
492 *editor <- put *editor, cursor-column:offset, cursor-column
493 below-screen?:bool <- greater-or-equal cursor-row, screen-height
494 return-unless below-screen?, 0/no-more-render
495 <scroll-down>
496 cursor-row <- subtract cursor-row, 1
497 *editor <- put *editor, cursor-row:offset, cursor-row
498 return 1/go-render
499 }
500
501 cursor-column <- add cursor-column, 1
502 *editor <- put *editor, cursor-column:offset, cursor-column
503 go-render? <- copy 0/false
504 ]
505
506 scenario editor-moves-cursor-to-next-line-with-right-arrow [
507 local-scope
508 assume-screen 10/width, 5/height
509 s:text <- new [abc
510 d]
511 e:&:editor <- new-editor s, 0/left, 10/right
512 editor-render screen, e
513 $clear-trace
514
515 assume-console [
516 press right-arrow
517 press right-arrow
518 press right-arrow
519 press right-arrow
520 ]
521 run [
522 editor-event-loop screen, console, e
523 ]
524 check-trace-count-for-label 0, [print-character]
525
526 assume-console [
527 type [0]
528 ]
529 run [
530 editor-event-loop screen, console, e
531 ]
532 screen-should-contain [
533 . .
534 .abc .
535 .0d .
536 .╌╌╌╌╌╌╌╌╌╌.
537 . .
538 ]
539 check-trace-count-for-label 2, [print-character]
540 ]
541
542 scenario editor-moves-cursor-to-next-line-with-right-arrow-2 [
543 local-scope
544 assume-screen 10/width, 5/height
545 s:text <- new [abc
546 d]
547 e:&:editor <- new-editor s, 1/left, 10/right
548 editor-render screen, e
549 assume-console [
550 press right-arrow
551 press right-arrow
552 press right-arrow
553 press right-arrow
554 type [0]
555 ]
556 run [
557 editor-event-loop screen, console, e
558 ]
559 screen-should-contain [
560 . .
561 . abc .
562 . 0d .
563 . ╌╌╌╌╌╌╌╌╌.
564 . .
565 ]
566 ]
567
568 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
569 local-scope
570 assume-screen 10/width, 5/height
571 e:&:editor <- new-editor [abcdef], 0/left, 5/right
572 editor-render screen, e
573 $clear-trace
574 assume-console [
575 left-click 1, 3
576 press right-arrow
577 ]
578 run [
579 editor-event-loop screen, console, e
580 3:num/raw <- get *e, cursor-row:offset
581 4:num/raw <- get *e, cursor-column:offset
582 ]
583 screen-should-contain [
584 . .
585 .abcd↩ .
586 .ef .
587 .╌╌╌╌╌ .
588 . .
589 ]
590 memory-should-contain [
591 3 <- 2
592 4 <- 0
593 ]
594 check-trace-count-for-label 0, [print-character]
595 ]
596
597 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
598 local-scope
599 assume-screen 10/width, 5/height
600
601 e:&:editor <- new-editor [abcde], 0/left, 5/right
602 editor-render screen, e
603 $clear-trace
604
605 assume-console [
606 left-click 1, 3
607 press right-arrow
608 ]
609 run [
610 editor-event-loop screen, console, e
611 3:num/raw <- get *e, cursor-row:offset
612 4:num/raw <- get *e, cursor-column:offset
613 ]
614 memory-should-contain [
615 3 <- 2
616 4 <- 0
617 ]
618
619 assume-console [
620 press right-arrow
621 ]
622 run [
623 editor-event-loop screen, console, e
624 3:num/raw <- get *e, cursor-row:offset
625 4:num/raw <- get *e, cursor-column:offset
626 ]
627 memory-should-contain [
628 3 <- 2
629 4 <- 1
630 ]
631 check-trace-count-for-label 0, [print-character]
632 ]
633
634 scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [
635 local-scope
636 assume-screen 10/width, 5/height
637 e:&:editor <- new-editor [abcdef], 1/left, 6/right
638 editor-render screen, e
639 $clear-trace
640 assume-console [
641 left-click 1, 4
642 press right-arrow
643 ]
644 run [
645 editor-event-loop screen, console, e
646 3:num/raw <- get *e, cursor-row:offset
647 4:num/raw <- get *e, cursor-column:offset
648 ]
649 screen-should-contain [
650 . .
651 . abcd↩ .
652 . ef .
653 . ╌╌╌╌╌ .
654 . .
655 ]
656 memory-should-contain [
657 3 <- 2
658 4 <- 1
659 ]
660 check-trace-count-for-label 0, [print-character]
661 ]
662
663 scenario editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [
664 local-scope
665 assume-screen 10/width, 5/height
666 s:text <- new [abc
667 d]
668 e:&:editor <- new-editor s, 0/left, 10/right
669 editor-render screen, e
670 $clear-trace
671
672 assume-console [
673 left-click 1, 3
674 press right-arrow
675 type [0]
676 ]
677 run [
678 editor-event-loop screen, console, e
679 ]
680
681 screen-should-contain [
682 . .
683 .abc .
684 .0d .
685 .╌╌╌╌╌╌╌╌╌╌.
686 . .
687 ]
688 check-trace-count-for-label 2, [print-character]
689 ]
690
691
692
693
694
695 scenario editor-moves-cursor-left-with-key [
696 local-scope
697 assume-screen 10/width, 5/height
698 e:&:editor <- new-editor [abc], 0/left, 10/right
699 editor-render screen, e
700 $clear-trace
701 assume-console [
702 left-click 1, 2
703 press left-arrow
704 type [0]
705 ]
706 run [
707 editor-event-loop screen, console, e
708 ]
709 screen-should-contain [
710 . .
711 .a0bc .
712 .╌╌╌╌╌╌╌╌╌╌.
713 . .
714 ]
715 check-trace-count-for-label 3, [print-character]
716 ]
717
718 after <handle-special-key> [
719 {
720 move-to-previous-character?:bool <- equal k, 65515/left-arrow
721 break-unless move-to-previous-character?
722 trace 10, [app], [left arrow]
723
724 prev:&:duplex-list:char <- prev before-cursor
725 return-unless prev, 0/don't-render
726 <begin-move-cursor>
727 go-render? <- move-cursor-coordinates-left editor
728 before-cursor <- copy prev
729 *editor <- put *editor, before-cursor:offset, before-cursor
730 undo-coalesce-tag:num <- copy 1/left-arrow
731 <end-move-cursor>
732 return
733 }
734 ]
735
736 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [
737 local-scope
738 assume-screen 10/width, 5/height
739
740 s:text <- new [abc
741 d]
742 e:&:editor <- new-editor s, 0/left, 10/right
743 editor-render screen, e
744 $clear-trace
745
746 assume-console [
747 left-click 2, 0
748 press left-arrow
749 ]
750 run [
751 editor-event-loop screen, console, e
752 3:num/raw <- get *e, cursor-row:offset
753 4:num/raw <- get *e, cursor-column:offset
754 ]
755 memory-should-contain [
756 3 <- 1
757 4 <- 3
758 ]
759 check-trace-count-for-label 0, [print-character]
760 ]
761
762 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [
763 local-scope
764 assume-screen 10/width, 5/height
765
766 s:text <- new [abc
767 def
768 g]
769 e:&:editor <- new-editor s:text, 0/left, 10/right
770 editor-render screen, e
771 $clear-trace
772
773
774 assume-console [
775 left-click 3, 0
776 press left-arrow
777 type [0]
778 ]
779 run [
780 editor-event-loop screen, console, e
781 ]
782 screen-should-contain [
783 . .
784 .abc .
785 .def0 .
786 .g .
787 .╌╌╌╌╌╌╌╌╌╌.
788 ]
789 check-trace-count-for-label 1, [print-character]
790 ]
791
792 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [
793 local-scope
794 assume-screen 10/width, 5/height
795 s:text <- new [abc
796 def
797 g]
798 e:&:editor <- new-editor s, 0/left, 10/right
799 editor-render screen, e
800 $clear-trace
801
802 assume-console [
803 left-click 1, 0
804 press left-arrow
805 type [0]
806 ]
807 run [
808 editor-event-loop screen, console, e
809 ]
810
811 screen-should-contain [
812 . .
813 .0abc .
814 .def .
815 .g .
816 .╌╌╌╌╌╌╌╌╌╌.
817 ]
818 check-trace-count-for-label 4, [print-character]
819 ]
820
821 scenario editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [
822 local-scope
823 assume-screen 10/width, 5/height
824
825 s:text <- new [abc
826
827 d]
828 e:&:editor <- new-editor s, 0/left, 10/right
829 editor-render screen, e:&:editor
830 $clear-trace
831
832 assume-console [
833 left-click 3, 0
834 press left-arrow
835 type [0]
836 ]
837 run [
838 editor-event-loop screen, console, e
839 ]
840 screen-should-contain [
841 . .
842 .abc .
843 .0 .
844 .d .
845 .╌╌╌╌╌╌╌╌╌╌.
846 ]
847 check-trace-count-for-label 1, [print-character]
848 ]
849
850 scenario editor-moves-across-screen-lines-across-wrap-with-left-arrow [
851 local-scope
852 assume-screen 10/width, 5/height
853
854 e:&:editor <- new-editor [abcdef], 0/left, 5/right
855 editor-render screen, e
856 $clear-trace
857 screen-should-contain [
858 . .
859 .abcd↩ .
860 .ef .
861 .╌╌╌╌╌ .
862 . .
863 ]
864
865 assume-console [
866 left-click 2, 0
867 press left-arrow
868 ]
869 run [
870 editor-event-loop screen, console, e
871 3:num/raw <- get *e, cursor-row:offset
872 4:num/raw <- get *e, cursor-column:offset
873 ]
874 memory-should-contain [
875 3 <- 1
876 4 <- 3
877 ]
878 check-trace-count-for-label 0, [print-character]
879 ]
880
881 scenario editor-moves-across-screen-lines-to-wrapping-line-with-left-arrow [
882 local-scope
883 assume-screen 10/width, 5/height
884
885 s:text <- new [abcdef
886 g]
887 e:&:editor <- new-editor s, 0/left, 5/right
888 editor-render screen, e
889 $clear-trace
890 screen-should-contain [
891 . .
892 .abcd↩ .
893 .ef .
894 .g .
895 .╌╌╌╌╌ .
896 ]
897
898 assume-console [
899 left-click 3, 0
900 press left-arrow
901 ]
902 run [
903 editor-event-loop screen, console, e
904 3:num/raw <- get *e, cursor-row:offset
905 4:num/raw <- get *e, cursor-column:offset
906 ]
907 memory-should-contain [
908 3 <- 2
909 4 <- 2
910 ]
911 check-trace-count-for-label 0, [print-character]
912 ]
913
914 scenario editor-moves-across-screen-lines-to-non-wrapping-line-with-left-arrow [
915 local-scope
916 assume-screen 10/width, 5/height
917
918 s:text <- new [abcd
919 e]
920 e:&:editor <- new-editor s, 0/left, 5/right
921 editor-render screen, e
922 $clear-trace
923 screen-should-contain [
924 . .
925 .abcd .
926 .e .
927 .╌╌╌╌╌ .
928 . .
929 ]
930
931 assume-console [
932 left-click 2, 0
933 press left-arrow
934 ]
935 run [
936 editor-event-loop screen, console, e
937 3:num/raw <- get *e, cursor-row:offset
938 4:num/raw <- get *e, cursor-column:offset
939 ]
940 memory-should-contain [
941 3 <- 1
942 4 <- 4
943 ]
944 check-trace-count-for-label 0, [print-character]
945 ]
946
947
948
949
950
951 scenario editor-moves-to-previous-line-with-up-arrow [
952 local-scope
953 assume-screen 10/width, 5/height
954 s:text <- new [abc
955 def]
956 e:&:editor <- new-editor s, 0/left, 10/right
957 editor-render screen, e
958 $clear-trace
959 assume-console [
960 left-click 2, 1
961 press up-arrow
962 ]
963 run [
964 editor-event-loop screen, console, e
965 3:num/raw <- get *e, cursor-row:offset
966 4:num/raw <- get *e, cursor-column:offset
967 ]
968 memory-should-contain [
969 3 <- 1
970 4 <- 1
971 ]
972 check-trace-count-for-label 0, [print-character]
973 assume-console [
974 type [0]
975 ]
976 run [
977 editor-event-loop screen, console, e
978 ]
979 screen-should-contain [
980 . .
981 .a0bc .
982 .def .
983 .╌╌╌╌╌╌╌╌╌╌.
984 . .
985 ]
986 ]
987
988 after <handle-special-key> [
989 {
990 move-to-previous-line?:bool <- equal k, 65517/up-arrow
991 break-unless move-to-previous-line?
992 <begin-move-cursor>
993 go-render? <- move-to-previous-line editor
994 undo-coalesce-tag:num <- copy 3/up-arrow
995 <end-move-cursor>
996 return
997 }
998 ]
999
1000 def move-to-previous-line editor:&:editor -> go-render?:bool, editor:&:editor [
1001 local-scope
1002 load-inputs
1003 go-render?:bool <- copy 0/false
1004 cursor-row:num <- get *editor, cursor-row:offset
1005 cursor-column:num <- get *editor, cursor-column:offset
1006 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1007 left:num <- get *editor, left:offset
1008 right:num <- get *editor, right:offset
1009 already-at-top?:bool <- lesser-or-equal cursor-row, 1/top
1010 {
1011
1012 break-if already-at-top?
1013
1014
1015
1016 curr:&:duplex-list:char <- copy before-cursor
1017 old:&:duplex-list:char <- copy curr
1018 {
1019 at-left?:bool <- equal cursor-column, left
1020 break-if at-left?
1021 curr <- before-previous-screen-line curr, editor
1022 no-motion?:bool <- equal curr, old
1023 return-if no-motion?
1024 }
1025 {
1026 curr <- before-previous-screen-line curr, editor
1027 no-motion?:bool <- equal curr, old
1028 return-if no-motion?
1029 }
1030 before-cursor <- copy curr
1031 *editor <- put *editor, before-cursor:offset, before-cursor
1032 cursor-row <- subtract cursor-row, 1
1033 *editor <- put *editor, cursor-row:offset, cursor-row
1034
1035 target-column:num <- copy cursor-column
1036 cursor-column <- copy left
1037 *editor <- put *editor, cursor-column:offset, cursor-column
1038 {
1039 done?:bool <- greater-or-equal cursor-column, target-column
1040 break-if done?
1041 curr:&:duplex-list:char <- next before-cursor
1042 break-unless curr
1043 currc:char <- get *curr, value:offset
1044 at-newline?:bool <- equal currc, 10/newline
1045 break-if at-newline?
1046
1047 before-cursor <- copy curr
1048 *editor <- put *editor, before-cursor:offset, before-cursor
1049 cursor-column <- add cursor-column, 1
1050 *editor <- put *editor, cursor-column:offset, cursor-column
1051 loop
1052 }
1053 return
1054 }
1055 {
1056
1057 break-unless already-at-top?
1058 <scroll-up>
1059 return 1/go-render
1060 }
1061 ]
1062
1063
1064
1065
1066
1067 def before-previous-screen-line in:&:duplex-list:char, editor:&:editor -> out:&:duplex-list:char [
1068 local-scope
1069 load-inputs
1070 curr:&:duplex-list:char <- copy in
1071 c:char <- get *curr, value:offset
1072
1073
1074
1075 left:num <- get *editor, left:offset
1076 right:num <- get *editor, right:offset
1077 max-line-length:num <- subtract right, left, -1/exclusive-right, 1/wrap-icon
1078 sentinel:&:duplex-list:char <- get *editor, data:offset
1079 len:num <- previous-line-length curr, sentinel
1080 {
1081 break-if len
1082
1083 prev:&:duplex-list:char <- prev curr
1084 return-unless prev, curr
1085 return prev
1086 }
1087 _, max:num <- divide-with-remainder len, max-line-length
1088
1089 {
1090 break-if max
1091 max <- copy max-line-length
1092 }
1093 max <- add max, 1
1094 count:num <- copy 0
1095
1096 {
1097 done?:bool <- greater-or-equal count, max
1098 break-if done?
1099 prev:&:duplex-list:char <- prev curr
1100 break-unless prev
1101 curr <- copy prev
1102 count <- add count, 1
1103 loop
1104 }
1105 return curr
1106 ]
1107
1108 scenario editor-adjusts-column-at-previous-line [
1109 local-scope
1110 assume-screen 10/width, 5/height
1111 s:text <- new [ab
1112 def]
1113 e:&:editor <- new-editor s, 0/left, 10/right
1114 editor-render screen, e
1115 $clear-trace
1116 assume-console [
1117 left-click 2, 3
1118 press up-arrow
1119 ]
1120 run [
1121 editor-event-loop screen, console, e
1122 3:num/raw <- get *e, cursor-row:offset
1123 4:num/raw <- get *e, cursor-column:offset
1124 ]
1125 memory-should-contain [
1126 3 <- 1
1127 4 <- 2
1128 ]
1129 check-trace-count-for-label 0, [print-character]
1130 assume-console [
1131 type [0]
1132 ]
1133 run [
1134 editor-event-loop screen, console, e
1135 ]
1136 screen-should-contain [
1137 . .
1138 .ab0 .
1139 .def .
1140 .╌╌╌╌╌╌╌╌╌╌.
1141 . .
1142 ]
1143 ]
1144
1145 scenario editor-adjusts-column-at-empty-line [
1146 local-scope
1147 assume-screen 10/width, 5/height
1148 s:text <- new [
1149 def]
1150 e:&:editor <- new-editor s, 0/left, 10/right
1151 editor-render screen, e
1152 $clear-trace
1153 assume-console [
1154 left-click 2, 3
1155 press up-arrow
1156 ]
1157 run [
1158 editor-event-loop screen, console, e
1159 3:num/raw <- get *e, cursor-row:offset
1160 4:num/raw <- get *e, cursor-column:offset
1161 ]
1162 memory-should-contain [
1163 3 <- 1
1164 4 <- 0
1165 ]
1166 check-trace-count-for-label 0, [print-character]
1167 assume-console [
1168 type [0]
1169 ]
1170 run [
1171 editor-event-loop screen, console, e
1172 ]
1173 screen-should-contain [
1174 . .
1175 .0 .
1176 .def .
1177 .╌╌╌╌╌╌╌╌╌╌.
1178 . .
1179 ]
1180 ]
1181
1182 scenario editor-moves-to-previous-line-from-zero-margin [
1183 local-scope
1184 assume-screen 10/width, 5/height
1185
1186 s:text <- new [abc
1187 def
1188 ghi]
1189 e:&:editor <- new-editor s, 0/left, 10/right
1190 editor-render screen, e
pan class="p">>
<span id="L85" class="LineNr"> 85 </span> curr <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> curr
<span id="L86" class="LineNr"> 86 </span> row:num <span class="Special"><-</span> copy <span class="Constant">1/top</span>
<span id="L87" class="LineNr"> 87 </span> column:num <span class="Special"><-</span> copy left
<span id="L88" class="LineNr"> 88 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-row:offset</span>, target-row
<span id="L89" class="LineNr"> 89 </span> cursor-row:num <span class="Special"><-</span> copy target-row
<span id="L90" class="LineNr"> 90 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-column:offset</span>, target-column
<span id="L91" class="LineNr"> 91 </span> cursor-column:num <span class="Special"><-</span> copy target-column
<span id="L92" class="LineNr"> 92 </span> before-cursor:&:<a href='../065duplex_list.mu.html#L3'>duplex-list</a>:char <span class="Special"><-</span> get *editor, <span class="Constant">before-cursor:offset</span>
<span id="L93" class="LineNr"> 93 </span> <span class="Delimiter">{</span>
<span id="L94" class="LineNr"> 94 </span><span class="Constant"> +next-character</span>
<span id="L95" class="LineNr"> 95 </span> <span class="muControl">break-unless</span> curr
<span id="L96" class="LineNr"> 96 </span> off-screen?:bool <span class="Special"><-</span> greater-or-equal row, <a href='../081print.mu.html#L782'>screen-height</a>
<span id="L97" class="LineNr"> 97 </span> <span class="muControl">break-if</span> off-screen?
<span id="L98" class="LineNr"> 98 </span> <span class="Comment"># update editor.before-cursor</span>
<span id="L99" class="LineNr"> 99 </span> <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
<span id="L100" class="LineNr"> 100 </span> <span class="Comment"># the current character.</span>
<span id="L101" class="LineNr"> 101 </span> <span class="Delimiter">{</span>
<span id="L102" class="LineNr"> 102 </span> at-cursor-row?:bool <span class="Special"><-</span> equal row, cursor-row
<span id="L103" class="LineNr"> 103 </span> <span class="muControl">break-unless</span> at-cursor-row?
<span id="L104" class="LineNr"> 104 </span> at-cursor?:bool <span class="Special"><-</span> equal column, cursor-column
<span id="L105" class="LineNr"> 105 </span> <span class="muControl">break-unless</span> at-cursor?
<span id="L106" class="LineNr"> 106 </span> before-cursor <span class="Special"><-</span> copy <a href='../065duplex_list.mu.html#L32'>prev</a>
<span id="L107" class="LineNr"> 107 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
<span id="L108" class="LineNr"> 108 </span> <span class="Delimiter">}</span>
<span id="L109" class="LineNr"> 109 </span> c:char <span class="Special"><-</span> get *curr, <span class="Constant">value:offset</span>
<span id="L110" class="LineNr"> 110 </span> <span class="Delimiter">{</span>
<span id="L111" class="LineNr"> 111 </span> <span class="Comment"># newline? move to left rather than 0</span>
<span id="L112" class="LineNr"> 112 </span> newline?:bool <span class="Special"><-</span> equal c, <span class="Constant">10/newline</span>
<span id="L113" class="LineNr"> 113 </span> <span class="muControl">break-unless</span> newline?
<span id="L114" class="LineNr"> 114 </span> <span class="Comment"># adjust cursor if necessary</span>
<span id="L115" class="LineNr"> 115 </span> <span class="Delimiter">{</span>
<span id="L116" class="LineNr"> 116 </span> at-cursor-row?:bool <span class="Special"><-</span> equal row, cursor-row
<span id="L117" class="LineNr"> 117 </span> <span class="muControl">break-unless</span> at-cursor-row?
<span id="L118" class="LineNr"> 118 </span> left-of-cursor?:bool <span class="Special"><-</span> lesser-than column, cursor-column
<span id="L119" class="LineNr"> 119 </span> <span class="muControl">break-unless</span> left-of-cursor?
<span id="L120" class="LineNr"> 120 </span> cursor-column <span class="Special"><-</span> copy column
<span id="L121" class="LineNr"> 121 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
<span id="L122" class="LineNr"> 122 </span> before-cursor <span class="Special"><-</span> copy <a href='../065duplex_list.mu.html#L32'>prev</a>
<span id="L123" class="LineNr"> 123 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
<span id="L124" class="LineNr"> 124 </span> <span class="Delimiter">}</span>
<span id="L125" class="LineNr"> 125 </span> <span class="Comment"># skip to next line</span>
<span id="L126" class="LineNr"> 126 </span> row <span class="Special"><-</span> add row,<span class="Constant"> 1</span>
<span id="L127" class="LineNr"> 127 </span> column <span class="Special"><-</span> copy left
<span id="L128" class="LineNr"> 128 </span> curr <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> curr
<span id="L129" class="LineNr"> 129 </span> <a href='../065duplex_list.mu.html#L32'>prev</a> <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> <a href='../065duplex_list.mu.html#L32'>prev</a>
<span id="L130" class="LineNr"> 130 </span> <span class="muControl"> loop</span> <span class="Constant">+next-character</span>
<span id="L131" class="LineNr"> 131 </span> <span class="Delimiter">}</span>
<span id="L132" class="LineNr"> 132 </span> <span class="Delimiter">{</span>
<span id="L133" class="LineNr"> 133 </span> <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
<span id="L134" class="LineNr"> 134 </span> <span class="Comment"># room for clicking on the cursor after it.</span>
<span id="L135" class="LineNr"> 135 </span> at-right?:bool <span class="Special"><-</span> equal column, right
<span id="L136" class="LineNr"> 136 </span> <span class="muControl">break-unless</span> at-right?
<span id="L137" class="LineNr"> 137 </span> column <span class="Special"><-</span> copy left
<span id="L138" class="LineNr"> 138 </span> row <span class="Special"><-</span> add row,<span class="Constant"> 1</span>
<span id="L139" class="LineNr"> 139 </span> <span class="Comment"># don't increment curr/prev</span>
<span id="L140" class="LineNr"> 140 </span> <span class="muControl"> loop</span> <span class="Constant">+next-character</span>
<span id="L141" class="LineNr"> 141 </span> <span class="Delimiter">}</span>
<span id="L142" class="LineNr"> 142 </span> curr <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> curr
<span id="L143" class="LineNr"> 143 </span> <a href='../065duplex_list.mu.html#L32'>prev</a> <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> <a href='../065duplex_list.mu.html#L32'>prev</a>
<span id="L144" class="LineNr"> 144 </span> column <span class="Special"><-</span> add column,<span class="Constant"> 1</span>
<span id="L145" class="LineNr"> 145 </span> <span class="muControl"> loop</span>
<span id="L146" class="LineNr"> 146 </span> <span class="Delimiter">}</span>
<span id="L147" class="LineNr"> 147 </span> <span class="Comment"># is cursor to the right of the last line? move to end</span>
<span id="L148" class="LineNr"> 148 </span> <span class="Delimiter">{</span>
<span id="L149" class="LineNr"> 149 </span> at-cursor-row?:bool <span class="Special"><-</span> equal row, cursor-row
<span id="L150" class="LineNr"> 150 </span> cursor-outside-line?:bool <span class="Special"><-</span> lesser-or-equal column, cursor-column
<span id="L151" class="LineNr"> 151 </span> before-cursor-on-same-line?:bool <span class="Special"><-</span> and at-cursor-row?, cursor-outside-line?
<span id="L152" class="LineNr"> 152 </span> above-cursor-row?:bool <span class="Special"><-</span> lesser-than row, cursor-row
<span id="L153" class="LineNr"> 153 </span> before-cursor?:bool <span class="Special"><-</span> or before-cursor-on-same-line?, above-cursor-row?
<span id="L154" class="LineNr"> 154 </span> <span class="muControl">break-unless</span> before-cursor?
<span id="L155" class="LineNr"> 155 </span> cursor-row <span class="Special"><-</span> copy row
<span id="L156" class="LineNr"> 156 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
<span id="L157" class="LineNr"> 157 </span> cursor-column <span class="Special"><-</span> copy column
<span id="L158" class="LineNr"> 158 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
<span id="L159" class="LineNr"> 159 </span> before-cursor <span class="Special"><-</span> copy <a href='../065duplex_list.mu.html#L32'>prev</a>
<span id="L160" class="LineNr"> 160 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
<span id="L161" class="LineNr"> 161 </span> <span class="Delimiter">}</span>
<span id="L162" class="LineNr"> 162 </span>]
<span id="L163" class="LineNr"> 163 </span>
<span id="L164" class="LineNr"> 164 </span><span class="Comment"># Process an event 'e' and try to minimally update the screen.</span>
<span id="L165" class="LineNr"> 165 </span><span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span>
<span id="L166" class="LineNr"> 166 </span><span class="muRecipe">def</span> <a href='002-typing.mu.html#L166'>handle-keyboard-event</a> <a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a>, editor:&:editor, e:<a href='../084console.mu.html#L4'>event</a><span class="muRecipe"> -> </span>go-render?:bool, <a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a>, editor:&:editor [
<span id="L167" class="LineNr"> 167 </span> <span class="Constant">local-scope</span>
<span id="L168" class="LineNr"> 168 </span> <span class="Constant">load-inputs</span>
<span id="L169" class="LineNr"> 169 </span> <span class="muControl">return-unless</span> editor, <span class="Constant">0/don't-render</span>
<span id="L170" class="LineNr"> 170 </span> <a href='../081print.mu.html#L768'>screen-width</a>:num <span class="Special"><-</span> <a href='../081print.mu.html#L768'>screen-width</a> <a href='../081print.mu.html#L16'>screen</a>
<span id="L171" class="LineNr"> 171 </span> <a href='../081print.mu.html#L782'>screen-height</a>:num <span class="Special"><-</span> <a href='../081print.mu.html#L782'>screen-height</a> <a href='../081print.mu.html#L16'>screen</a>
<span id="L172" class="LineNr"> 172 </span> left:num <span class="Special"><-</span> get *editor, <span class="Constant">left:offset</span>
<span id="L173" class="LineNr"> 173 </span> right:num <span class="Special"><-</span> get *editor, <span class="Constant">right:offset</span>
<span id="L174" class="LineNr"> 174 </span> before-cursor:&:<a href='../065duplex_list.mu.html#L3'>duplex-list</a>:char <span class="Special"><-</span> get *editor, <span class="Constant">before-cursor:offset</span>
<span id="L175" class="LineNr"> 175 </span> cursor-row:num <span class="Special"><-</span> get *editor, <span class="Constant">cursor-row:offset</span>
<span id="L176" class="LineNr"> 176 </span> cursor-column:num <span class="Special"><-</span> get *editor, <span class="Constant">cursor-column:offset</span>
<span id="L177" class="LineNr"> 177 </span> save-row:num <span class="Special"><-</span> copy cursor-row
<span id="L178" class="LineNr"> 178 </span> save-column:num <span class="Special"><-</span> copy cursor-column
<span id="L179" class="LineNr"> 179 </span> <span class="Comment"># character</span>
<span id="L180" class="LineNr"> 180 </span> <span class="Delimiter">{</span>
<span id="L181" class="LineNr"> 181 </span> c:char, is-unicode?:bool <span class="Special"><-</span> maybe-convert e, <span class="Constant">text:variant</span>
<span id="L182" class="LineNr"> 182 </span> <span class="muControl">break-unless</span> is-unicode?
<span id="L183" class="LineNr"> 183 </span> trace<span class="Constant"> 10</span>, <span class="Constant">[app]</span>, <span class="Constant">[handle-keyboard-event: special character]</span>
<span id="L184" class="LineNr"> 184 </span> <span class="Comment"># exceptions for special characters go here</span>
<span id="L185" class="LineNr"> 185 </span><span class="Constant"> <a href='002-typing.mu.html#L185'><handle-special-character></a></span>
<span id="L186" class="LineNr"> 186 </span> <span class="Comment"># ignore any other special characters</span>
<span id="L187" class="LineNr"> 187 </span> regular-character?:bool <span class="Special"><-</span> greater-or-equal c, <span class="Constant">32/space</span>
<span id="L188" class="LineNr"> 188 </span> <span class="muControl">return-unless</span> regular-character?, <span class="Constant">0/don't-render</span>
<span id="L189" class="LineNr"> 189 </span> <span class="Comment"># otherwise type it in</span>
<span id="L190" class="LineNr"> 190 </span><span class="Constant"> <begin-insert-character></span>
<span id="L191" class="LineNr"> 191 </span> go-render? <span class="Special"><-</span> <a href='002-typing.mu.html#L203'>insert-at-cursor</a> editor, c, <a href='../081print.mu.html#L16'>screen</a>
<span id="L192" class="LineNr"> 192 </span><span class="Constant"> <end-insert-character></span>
<span id="L193" class="LineNr"> 193 </span> <span class="muControl"> return</span>
<span id="L194" class="LineNr"> 194 </span> <span class="Delimiter">}</span>
<span id="L195" class="LineNr"> 195 </span> <span class="Comment"># special key to modify the text or move the cursor</span>
<span id="L196" class="LineNr"> 196 </span> k:num, is-keycode?:bool <span class="Special"><-</span> maybe-convert e:<a href='../084console.mu.html#L4'>event</a>, <span class="Constant">keycode:variant</span>
<span id="L197" class="LineNr"> 197 </span> assert is-keycode?, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
<span id="L198" class="LineNr"> 198 </span> <span class="Comment"># handlers for each special key will go here</span>
<span id="L199" class="LineNr"> 199 </span><span class="Constant"> <a href='002-typing.mu.html#L199'><handle-special-key></a></span>
<span id="L200" class="LineNr"> 200 </span> <span class="muControl"> return</span> <span class="Constant">1/go-render</span>
<span id="L201" class="LineNr"> 201 </span>]
<span id="L202" class="LineNr"> 202 </span>
<span id="L203" class="LineNr"> 203 </span><span class="muRecipe">def</span> <a href='002-typing.mu.html#L203'>insert-at-cursor</a> editor:&:editor, c:char, <a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a><span class="muRecipe"> -> </span>go-render?:bool, editor:&:editor, <a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a> [
<span id="L204" class="LineNr"> 204 </span> <span class="Constant">local-scope</span>
<span id="L205" class="LineNr"> 205 </span> <span class="Constant">load-inputs</span>
<span id="L206" class="LineNr"> 206 </span> before-cursor:&:<a href='../065duplex_list.mu.html#L3'>duplex-list</a>:char <span class="Special"><-</span> get *editor, <span class="Constant">before-cursor:offset</span>
<span id="L207" class="LineNr"> 207 </span> insert c, before-cursor
<span id="L208" class="LineNr"> 208 </span> before-cursor <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> before-cursor
<span id="L209" class="LineNr"> 209 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
<span id="L210" class="LineNr"> 210 </span> cursor-row:num <span class="Special"><-</span> get *editor, <span class="Constant">cursor-row:offset</span>
<span id="L211" class="LineNr"> 211 </span> cursor-column:num <span class="Special"><-</span> get *editor, <span class="Constant">cursor-column:offset</span>
<span id="L212" class="LineNr"> 212 </span> left:num <span class="Special"><-</span> get *editor, <span class="Constant">left:offset</span>
<span id="L213" class="LineNr"> 213 </span> right:num <span class="Special"><-</span> get *editor, <span class="Constant">right:offset</span>
<span id="L214" class="LineNr"> 214 </span> save-row:num <span class="Special"><-</span> copy cursor-row
<span id="L215" class="LineNr"> 215 </span> save-column:num <span class="Special"><-</span> copy cursor-column
<span id="L216" class="LineNr"> 216 </span> <a href='../081print.mu.html#L768'>screen-width</a>:num <span class="Special"><-</span> <a href='../081print.mu.html#L768'>screen-width</a> <a href='../081print.mu.html#L16'>screen</a>
<span id="L217" class="LineNr"> 217 </span> <a href='../081print.mu.html#L782'>screen-height</a>:num <span class="Special"><-</span> <a href='../081print.mu.html#L782'>screen-height</a> <a href='../081print.mu.html#L16'>screen</a>
<span id="L218" class="LineNr"> 218 </span> <span class="Comment"># occasionally we'll need to mess with the cursor</span>
<span id="L219" class="LineNr"> 219 </span><span class="Constant"> <a href='002-typing.mu.html#L219'><insert-character-special-case></a></span>
<span id="L220" class="LineNr"> 220 </span> <span class="Comment"># but mostly we'll just move the cursor right</span>
<span id="L221" class="LineNr"> 221 </span> cursor-column <span class="Special"><-</span> add cursor-column,<span class="Constant"> 1</span>
<span id="L222" class="LineNr"> 222 </span> *editor <span class="Special"><-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
<span id="L223" class="LineNr"> 223 </span> <a href='../065duplex_list.mu.html#L25'>next</a>:&:<a href='../065duplex_list.mu.html#L3'>duplex-list</a>:char <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> before-cursor
<span id="L224" class="LineNr"> 224 </span> <span class="Delimiter">{</span>
<span id="L225" class="LineNr"> 225 </span> <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span>
<span id="L226" class="LineNr"> 226 </span> at-end?:bool <span class="Special"><-</span> equal <a href='../065duplex_list.mu.html#L25'>next</a>, <span class="Constant">0/null</span>
<span id="L227" class="LineNr"> 227 </span> <span class="muControl">break-unless</span> at-end?
<span id="L228" class="LineNr"> 228 </span> bottom:num <span class="Special"><-</span> subtract <a href='../081print.mu.html#L782'>screen-height</a>,<span class="Constant"> 1</span>
<span id="L229" class="LineNr"> 229 </span> at-bottom?:bool <span class="Special"><-</span> equal save-row, bottom
<span id="L230" class="LineNr"> 230 </span> at-right?:bool <span class="Special"><-</span> equal save-column, right
<span id="L231" class="LineNr"> 231 </span> overflow?:bool <span class="Special"><-</span> and at-bottom?, at-right?
<span id="L232" class="LineNr"> 232 </span> <span class="muControl">break-if</span> overflow?
<span id="L233" class="LineNr"> 233 </span> move-cursor <a href='../081print.mu.html#L16'>screen</a>, save-row, save-column
<span id="L234" class="LineNr"> 234 </span> print <a href='../081print.mu.html#L16'>screen</a>, c
<span id="L235" class="LineNr"> 235 </span> <span class="muControl"> return</span> <span class="Constant">0/don't-render</span>
<span id="L236" class="LineNr"> 236 </span> <span class="Delimiter">}</span>
<span id="L237" class="LineNr"> 237 </span> <span class="Delimiter">{</span>
<span id="L238" class="LineNr"> 238 </span> <span class="Comment"># not at right margin? print the character and rest of line</span>
<span id="L239" class="LineNr"> 239 </span> <span class="muControl">break-unless</span> <a href='../065duplex_list.mu.html#L25'>next</a>
<span id="L240" class="LineNr"> 240 </span> at-right?:bool <span class="Special"><-</span> greater-or-equal cursor-column, <a href='../081print.mu.html#L768'>screen-width</a>
<span id="L241" class="LineNr"> 241 </span> <span class="muControl">break-if</span> at-right?
<span id="L242" class="LineNr"> 242 </span> curr:&:<a href='../065duplex_list.mu.html#L3'>duplex-list</a>:char <span class="Special"><-</span> copy before-cursor
<span id="L243" class="LineNr"> 243 </span> move-cursor <a href='../081print.mu.html#L16'>screen</a>, save-row, save-column
<span id="L244" class="LineNr"> 244 </span> curr-column:num <span class="Special"><-</span> copy save-column
<span id="L245" class="LineNr"> 245 </span> <span class="Delimiter">{</span>
<span id="L246" class="LineNr"> 246 </span> <span class="Comment"># hit right margin? give up and let caller render</span>
<span id="L247" class="LineNr"> 247 </span> at-right?:bool <span class="Special"><-</span> greater-than curr-column, right
<span id="L248" class="LineNr"> 248 </span> <span class="muControl">return-if</span> at-right?, <span class="Constant">1/go-render</span>
<span id="L249" class="LineNr"> 249 </span> <span class="muControl">break-unless</span> curr
<span id="L250" class="LineNr"> 250 </span> <span class="Comment"># newline? done.</span>
<span id="L251" class="LineNr"> 251 </span> currc:char <span class="Special"><-</span> get *curr, <span class="Constant">value:offset</span>
<span id="L252" class="LineNr"> 252 </span> at-newline?:bool <span class="Special"><-</span> equal currc, <span class="Constant">10/newline</span>
<span id="L253" class="LineNr"> 253 </span> <span class="muControl">break-if</span> at-newline?
<span id="L254" class="LineNr"> 254 </span> print <a href='../081print.mu.html#L16'>screen</a>, currc
<span id="L255" class="LineNr"> 255 </span> curr-column <span class="Special"><-</span> add curr-column,<span class="Constant"> 1</span>
<span id="L256" class="LineNr"> 256 </span> curr <span class="Special"><-</span> <a href='../065duplex_list.mu.html#L25'>next</a> curr
<span id="L257" class="LineNr"> 257 </span> <span class="muControl"> loop</span>
<span id="L258" class="LineNr"> 258 </span> <span class="Delimiter">}</span>
<span id="L259" class="LineNr"> 259 </span> <span class="muControl"> return</span> <span class="Constant">0/don't-render</span>
<span id="L260" class="LineNr"> 260 </span> <span class="Delimiter">}</span>
<span id="L261" class="LineNr"> 261 </span> <span class="muControl"> return</span> <span class="Constant">1/go-render</span>
<span id="L262" class="LineNr"> 262 </span>]
<span id="L263" class="LineNr"> 263 </span>
<span id="L264" class="LineNr"> 264 </span><span class="Comment"># helper for tests</span>
<span id="L265" class="LineNr"> 265 </span><span class="muRecipe">def</span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a>, editor:&:editor<span class="muRecipe"> -> </span><a href='../081print.mu.html#L16'>screen</a>:&:<a href='../081print.mu.html#L16'>screen</a>, editor:&:editor [
<span id="L266" class="LineNr"> 266 </span> <span class="Constant">local-scope</span>
<span id="L267" class="LineNr"> 267 </span> <span class="Constant">load-inputs</span>
<span id="L268" class="LineNr"> 268 </span> old-top-idx:num <span class="Special"><-</span> <a href='../081print.mu.html#L509'>save-top-idx</a> <a href='../081print.mu.html#L16'>screen</a>
<span id="L269" class="LineNr"> 269 </span> left:num <span class="Special"><-</span> get *editor, <span class="Constant">left:offset</span>
<span id="L270" class="LineNr"> 270 </span> right:num <span class="Special"><-</span> get *editor, <span class="Constant">right:offset</span>
<span id="L271" class="LineNr"> 271 </span> row:num, column:num <span class="Special"><-</span> <a href='001-editor.mu.html#L107'>render</a> <a href='../081print.mu.html#L16'>screen</a>, editor
<span id="L272" class="LineNr"> 272 </span> <a href='002-typing.mu.html#L1114'>draw-horizontal</a> <a href='../081print.mu.html#L16'>screen</a>, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
<span id="L273" class="LineNr"> 273 </span> row <span class="Special"><-</span> add row,<span class="Constant"> 1</span>
<span id="L274" class="LineNr"> 274 </span> <a href='001-editor.mu.html#L209'>clear-screen-from</a> <a href='../081print.mu.html#L16'>screen</a>, row, left, left, right
<span id="L275" class="LineNr"> 275 </span> <a href='../081print.mu.html#L515'>assert-no-scroll</a> <a href='../081print.mu.html#L16'>screen</a>, old-top-idx
<span id="L276" class="LineNr"> 276 </span>]
<span id="L277" class="LineNr"> 277 </span>
<span id="L278" class="LineNr"> 278 </span><span class="muScenario">scenario</span> editor-handles-empty-event-queue [
<span id="L279" class="LineNr"> 279 </span> <span class="Constant">local-scope</span>
<span id="L280" class="LineNr"> 280 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L281" class="LineNr"> 281 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L282" class="LineNr"> 282 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L283" class="LineNr"> 283 </span> assume-console <span class="Constant">[]</span>
<span id="L284" class="LineNr"> 284 </span> run [
<span id="L285" class="LineNr"> 285 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L286" class="LineNr"> 286 </span> ]
<span id="L287" class="LineNr"> 287 </span> screen-should-contain [
<span id="L288" class="LineNr"> 288 </span> <span class="Constant"> . .</span>
<span id="L289" class="LineNr"> 289 </span> <span class="Constant"> .abc .</span>
<span id="L290" class="LineNr"> 290 </span><span class="Constant"> .╌╌╌╌╌╌╌╌╌╌.</span>
<span id="L291" class="LineNr"> 291 </span> <span class="Constant"> . .</span>
<span id="L292" class="LineNr"> 292 </span> ]
<span id="L293" class="LineNr"> 293 </span>]
<span id="L294" class="LineNr"> 294 </span>
<span id="L295" class="LineNr"> 295 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks [
<span id="L296" class="LineNr"> 296 </span> <span class="Constant">local-scope</span>
<span id="L297" class="LineNr"> 297 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L298" class="LineNr"> 298 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L299" class="LineNr"> 299 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L300" class="LineNr"> 300 </span> $clear-trace
<span id="L301" class="LineNr"> 301 </span> assume-console [
<span id="L302" class="LineNr"> 302 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 1</span> <span class="Comment"># on the 'b'</span>
<span id="L303" class="LineNr"> 303 </span> ]
<span id="L304" class="LineNr"> 304 </span> run [
<span id="L305" class="LineNr"> 305 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L306" class="LineNr"> 306 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L307" class="LineNr"> 307 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L308" class="LineNr"> 308 </span> ]
<span id="L309" class="LineNr"> 309 </span> screen-should-contain [
<span id="L310" class="LineNr"> 310 </span> <span class="Constant"> . .</span>
<span id="L311" class="LineNr"> 311 </span> <span class="Constant"> .abc .</span>
<span id="L312" class="LineNr"> 312 </span><span class="Constant"> .╌╌╌╌╌╌╌╌╌╌.</span>
<span id="L313" class="LineNr"> 313 </span> <span class="Constant"> . .</span>
<span id="L314" class="LineNr"> 314 </span> ]
<span id="L315" class="LineNr"> 315 </span> memory-should-contain [
<span id="L316" class="LineNr"> 316 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># cursor is at row 0..</span>
<span id="L317" class="LineNr"> 317 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># ..and column 1</span>
<span id="L318" class="LineNr"> 318 </span> ]
<span id="L319" class="LineNr"> 319 </span> check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
<span id="L320" class="LineNr"> 320 </span>]
<span id="L321" class="LineNr"> 321 </span>
<span id="L322" class="LineNr"> 322 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [
<span id="L323" class="LineNr"> 323 </span> <span class="Constant">local-scope</span>
<span id="L324" class="LineNr"> 324 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L325" class="LineNr"> 325 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L326" class="LineNr"> 326 </span> $clear-trace
<span id="L327" class="LineNr"> 327 </span> assume-console [
<span id="L328" class="LineNr"> 328 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 7</span> <span class="Comment"># last line, to the right of text</span>
<span id="L329" class="LineNr"> 329 </span> ]
<span id="L330" class="LineNr"> 330 </span> run [
<span id="L331" class="LineNr"> 331 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L332" class="LineNr"> 332 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L333" class="LineNr"> 333 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L334" class="LineNr"> 334 </span> ]
<span id="L335" class="LineNr"> 335 </span> memory-should-contain [
<span id="L336" class="LineNr"> 336 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># cursor row</span>
<span id="L337" class="LineNr"> 337 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 3</span> <span class="Comment"># cursor column</span>
<span id="L338" class="LineNr"> 338 </span> ]
<span id="L339" class="LineNr"> 339 </span> check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
<span id="L340" class="LineNr"> 340 </span>]
<span id="L341" class="LineNr"> 341 </span>
<span id="L342" class="LineNr"> 342 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [
<span id="L343" class="LineNr"> 343 </span> <span class="Constant">local-scope</span>
<span id="L344" class="LineNr"> 344 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L345" class="LineNr"> 345 </span> s:text <span class="Special"><-</span> new <span class="Constant">[abc</span>
<span id="L346" class="LineNr"> 346 </span><span class="Constant">def]</span>
<span id="L347" class="LineNr"> 347 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L348" class="LineNr"> 348 </span> $clear-trace
<span id="L349" class="LineNr"> 349 </span> assume-console [
<span id="L350" class="LineNr"> 350 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 7</span> <span class="Comment"># interior line, to the right of text</span>
<span id="L351" class="LineNr"> 351 </span> ]
<span id="L352" class="LineNr"> 352 </span> run [
<span id="L353" class="LineNr"> 353 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L354" class="LineNr"> 354 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L355" class="LineNr"> 355 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L356" class="LineNr"> 356 </span> ]
<span id="L357" class="LineNr"> 357 </span> memory-should-contain [
<span id="L358" class="LineNr"> 358 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># cursor row</span>
<span id="L359" class="LineNr"> 359 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 3</span> <span class="Comment"># cursor column</span>
<span id="L360" class="LineNr"> 360 </span> ]
<span id="L361" class="LineNr"> 361 </span> check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
<span id="L362" class="LineNr"> 362 </span>]
<span id="L363" class="LineNr"> 363 </span>
<span id="L364" class="LineNr"> 364 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [
<span id="L365" class="LineNr"> 365 </span> <span class="Constant">local-scope</span>
<span id="L366" class="LineNr"> 366 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L367" class="LineNr"> 367 </span> s:text <span class="Special"><-</span> new <span class="Constant">[abc</span>
<span id="L368" class="LineNr"> 368 </span><span class="Constant">def]</span>
<span id="L369" class="LineNr"> 369 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L370" class="LineNr"> 370 </span> $clear-trace
<span id="L371" class="LineNr"> 371 </span> assume-console [
<span id="L372" class="LineNr"> 372 </span> left-click<span class="Constant"> 3</span>,<span class="Constant"> 7</span> <span class="Comment"># below text</span>
<span id="L373" class="LineNr"> 373 </span> ]
<span id="L374" class="LineNr"> 374 </span> run [
<span id="L375" class="LineNr"> 375 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L376" class="LineNr"> 376 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L377" class="LineNr"> 377 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L378" class="LineNr"> 378 </span> ]
<span id="L379" class="LineNr"> 379 </span> memory-should-contain [
<span id="L380" class="LineNr"> 380 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 2</span> <span class="Comment"># cursor row</span>
<span id="L381" class="LineNr"> 381 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 3</span> <span class="Comment"># cursor column</span>
<span id="L382" class="LineNr"> 382 </span> ]
<span id="L383" class="LineNr"> 383 </span> check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
<span id="L384" class="LineNr"> 384 </span>]
<span id="L385" class="LineNr"> 385 </span>
<span id="L386" class="LineNr"> 386 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [
<span id="L387" class="LineNr"> 387 </span> <span class="Constant">local-scope</span>
<span id="L388" class="LineNr"> 388 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L389" class="LineNr"> 389 </span> <span class="Comment"># editor occupies only left half of screen</span>
<span id="L390" class="LineNr"> 390 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
<span id="L391" class="LineNr"> 391 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L392" class="LineNr"> 392 </span> $clear-trace
<span id="L393" class="LineNr"> 393 </span> assume-console [
<span id="L394" class="LineNr"> 394 </span> <span class="Comment"># click on right half of screen</span>
<span id="L395" class="LineNr"> 395 </span> left-click<span class="Constant"> 3</span>,<span class="Constant"> 8</span>
<span id="L396" class="LineNr"> 396 </span> ]
<span id="L397" class="LineNr"> 397 </span> run [
<span id="L398" class="LineNr"> 398 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L399" class="LineNr"> 399 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L400" class="LineNr"> 400 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L401" class="LineNr"> 401 </span> ]
<span id="L402" class="LineNr"> 402 </span> screen-should-contain [
<span id="L403" class="LineNr"> 403 </span> <span class="Constant"> . .</span>
<span id="L404" class="LineNr"> 404 </span> <span class="Constant"> .abc .</span>
<span id="L405" class="LineNr"> 405 </span> <span class="Constant"> .╌╌╌╌╌ .</span>
<span id="L406" class="LineNr"> 406 </span> <span class="Constant"> . .</span>
<span id="L407" class="LineNr"> 407 </span> ]
<span id="L408" class="LineNr"> 408 </span> memory-should-contain [
<span id="L409" class="LineNr"> 409 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 1</span> <span class="Comment"># no change to cursor row</span>
<span id="L410" class="LineNr"> 410 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 0</span> <span class="Comment"># ..or column</span>
<span id="L411" class="LineNr"> 411 </span> ]
<span id="L412" class="LineNr"> 412 </span> check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
<span id="L413" class="LineNr"> 413 </span>]
<span id="L414" class="LineNr"> 414 </span>
<span id="L415" class="LineNr"> 415 </span><span class="muScenario">scenario</span> editor-handles-mouse-clicks-in-menu-area [
<span id="L416" class="LineNr"> 416 </span> <span class="Constant">local-scope</span>
<span id="L417" class="LineNr"> 417 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L418" class="LineNr"> 418 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
<span id="L419" class="LineNr"> 419 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L420" class="LineNr"> 420 </span> $clear-trace
<span id="L421" class="LineNr"> 421 </span> assume-console [
<span id="L422" class="LineNr"> 422 </span> <span class="Comment"># click on first, 'menu' row</span>
<span id="L423" class="LineNr"> 423 </span> left-click<span class="Constant"> 0</span>,<span class="Constant"> 3</span>
<span id="L424" class="LineNr"> 424 </span> ]
<span id="L425" class="LineNr"> 425 </span> run [
<span id="L426" class="LineNr"> 426 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L427" class="LineNr"> 427 </span> 3:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-row:offset</span>
<span id="L428" class="LineNr"> 428 </span> 4:num/<span class="Special">raw</span> <span class="Special"><-</span> get *e, <span class="Constant">cursor-column:offset</span>
<span id="L429" class="LineNr"> 429 </span> ]
<span id="L430" class="LineNr"> 430 </span> <span class="Comment"># no change to cursor</span>
<span id="L431" class="LineNr"> 431 </span> memory-should-contain [
<span id="L432" class="LineNr"> 432 </span> <span class="Constant"> 3</span> <span class="Special"><-</span><span class="Constant"> 1</span>
<span id="L433" class="LineNr"> 433 </span> <span class="Constant"> 4</span> <span class="Special"><-</span><span class="Constant"> 0</span>
<span id="L434" class="LineNr"> 434 </span> ]
<span id="L435" class="LineNr"> 435 </span>]
<span id="L436" class="LineNr"> 436 </span>
<span id="L437" class="LineNr"> 437 </span><span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [
<span id="L438" class="LineNr"> 438 </span> <span class="Constant">local-scope</span>
<span id="L439" class="LineNr"> 439 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L440" class="LineNr"> 440 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
<span id="L441" class="LineNr"> 441 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L442" class="LineNr"> 442 </span> $clear-trace
<span id="L443" class="LineNr"> 443 </span> assume-console [
<span id="L444" class="LineNr"> 444 </span> type <span class="Constant">[abc]</span>
<span id="L445" class="LineNr"> 445 </span> ]
<span id="L446" class="LineNr"> 446 </span> run [
<span id="L447" class="LineNr"> 447 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L448" class="LineNr"> 448 </span> ]
<span id="L449" class="LineNr"> 449 </span> screen-should-contain [
<span id="L450" class="LineNr"> 450 </span> <span class="Constant"> . .</span>
<span id="L451" class="LineNr"> 451 </span> <span class="Constant"> .abc .</span>
<span id="L452" class="LineNr"> 452 </span> <span class="Constant"> .╌╌╌╌╌ .</span>
<span id="L453" class="LineNr"> 453 </span> <span class="Constant"> . .</span>
<span id="L454" class="LineNr"> 454 </span> ]
<span id="L455" class="LineNr"> 455 </span> check-trace-count-for-label<span class="Constant"> 3</span>, <span class="Constant">[print-character]</span>
<span id="L456" class="LineNr"> 456 </span>]
<span id="L457" class="LineNr"> 457 </span>
<span id="L458" class="LineNr"> 458 </span><span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [
<span id="L459" class="LineNr"> 459 </span> <span class="Constant">local-scope</span>
<span id="L460" class="LineNr"> 460 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L461" class="LineNr"> 461 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L462" class="LineNr"> 462 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L463" class="LineNr"> 463 </span> $clear-trace
<span id="L464" class="LineNr"> 464 </span> <span class="Comment"># type two letters at different places</span>
<span id="L465" class="LineNr"> 465 </span> assume-console [
<span id="L466" class="LineNr"> 466 </span> type <span class="Constant">[0]</span>
<span id="L467" class="LineNr"> 467 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 2</span>
<span id="L468" class="LineNr"> 468 </span> type <span class="Constant">[d]</span>
<span id="L469" class="LineNr"> 469 </span> ]
<span id="L470" class="LineNr"> 470 </span> run [
<span id="L471" class="LineNr"> 471 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L472" class="LineNr"> 472 </span> ]
<span id="L473" class="LineNr"> 473 </span> screen-should-contain [
<span id="L474" class="LineNr"> 474 </span> <span class="Constant"> . .</span>
<span id="L475" class="LineNr"> 475 </span> <span class="Constant"> .0adbc .</span>
<span id="L476" class="LineNr"> 476 </span><span class="Constant"> .╌╌╌╌╌╌╌╌╌╌.</span>
<span id="L477" class="LineNr"> 477 </span> <span class="Constant"> . .</span>
<span id="L478" class="LineNr"> 478 </span> ]
<span id="L479" class="LineNr"> 479 </span> check-trace-count-for-label<span class="Constant"> 7</span>, <span class="Constant">[print-character]</span> <span class="Comment"># 4 for first letter, 3 for second</span>
<span id="L480" class="LineNr"> 480 </span>]
<span id="L481" class="LineNr"> 481 </span>
<span id="L482" class="LineNr"> 482 </span><span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [
<span id="L483" class="LineNr"> 483 </span> <span class="Constant">local-scope</span>
<span id="L484" class="LineNr"> 484 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L485" class="LineNr"> 485 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L486" class="LineNr"> 486 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L487" class="LineNr"> 487 </span> $clear-trace
<span id="L488" class="LineNr"> 488 </span> assume-console [
<span id="L489" class="LineNr"> 489 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 5</span> <span class="Comment"># right of last line</span>
<span id="L490" class="LineNr"> 490 </span> type <span class="Constant">[d]</span>
<span id="L491" class="LineNr"> 491 </span> ]
<span id="L492" class="LineNr"> 492 </span> run [
<span id="L493" class="LineNr"> 493 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L494" class="LineNr"> 494 </span> ]
<span id="L495" class="LineNr"> 495 </span> screen-should-contain [
<span id="L496" class="LineNr"> 496 </span> <span class="Constant"> . .</span>
<span id="L497" class="LineNr"> 497 </span> <span class="Constant"> .abcd .</span>
<span id="L498" class="LineNr"> 498 </span><span class="Constant"> .╌╌╌╌╌╌╌╌╌╌.</span>
<span id="L499" class="LineNr"> 499 </span> <span class="Constant"> . .</span>
<span id="L500" class="LineNr"> 500 </span> ]
<span id="L501" class="LineNr"> 501 </span> check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
<span id="L502" class="LineNr"> 502 </span>]
<span id="L503" class="LineNr"> 503 </span>
<span id="L504" class="LineNr"> 504 </span><span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
<span id="L505" class="LineNr"> 505 </span> <span class="Constant">local-scope</span>
<span id="L506" class="LineNr"> 506 </span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
<span id="L507" class="LineNr"> 507 </span> s:text <span class="Special"><-</span> new <span class="Constant">[abc</span>
<span id="L508" class="LineNr"> 508 </span><span class="Constant">d]</span>
<span id="L509" class="LineNr"> 509 </span> e:&:editor <span class="Special"><-</span> <a href='001-editor.mu.html#L51'>new-editor</a> s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
<span id="L510" class="LineNr"> 510 </span> <a href='002-typing.mu.html#L265'>editor-render</a> <a href='../081print.mu.html#L16'>screen</a>, e
<span id="L511" class="LineNr"> 511 </span> $clear-trace
<span id="L512" class="LineNr"> 512 </span> assume-console [
<span id="L513" class="LineNr"> 513 </span> left-click<span class="Constant"> 1</span>,<span class="Constant"> 5</span> <span class="Comment"># right of non-last line</span>
<span id="L514" class="LineNr"> 514 </span> type <span class="Constant">[e]</span>
<span id="L515" class="LineNr"> 515 </span> ]
<span id="L516" class="LineNr"> 516 </span> run [
<span id="L517" class="LineNr"> 517 </span> <a href='002-typing.mu.html#L16'>editor-event-loop</a> <a href='../081print.mu.html#L16'>screen</a>, <a href='../084console.mu.html#L23'>console</a>, e
<span id="L518" class="LineNr"> 518 </span> ]
<span id="L519" class="LineNr"> 519 </span> screen-should-contain [
<span id="L520" class="LineNr"> 520 </span> <span class="Constant"> . .</span>
<span id="L521" class="LineNr"> 521 </span> <span class="Constant"> .abce .</span>
<span id="L522" class="LineNr"> 522 </span> <span class="Constant"> .d .</span>
<span id="L523" class="LineNr"> 523 </span><span class="Constant"> .╌╌╌╌╌╌╌╌╌╌.</span>
<span id="L524" class="LineNr"> 524 </span> <span class="Constant"> . .</span>
<span id="L525" class="LineNr"> 525 </span> ]
<span id="L526" class="LineNr"> 526 </span> check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
<span id="L527" class="LineNr"> 527 </span>]
<