1
2
3
4
5 exclusive-container operation [
6 typing:insert-operation
7 move:move-operation
8 delete:delete-operation
9 ]
10
11 container insert-operation [
12 before-row:num
13 before-column:num
14 before-top-of-screen:&:duplex-list:char
15 after-row:num
16 after-column:num
17 after-top-of-screen:&:duplex-list:char
18
19 insert-from:&:duplex-list:char
20 insert-until:&:duplex-list:char
21 tag:num
22
23
24 ]
25
26 container move-operation [
27 before-row:num
28 before-column:num
29 before-top-of-screen:&:duplex-list:char
30 after-row:num
31 after-column:num
32 after-top-of-screen:&:duplex-list:char
33 tag:num
34
35
36
37
38
39 ]
40
41 container delete-operation [
42 before-row:num
43 before-column:num
44 before-top-of-screen:&:duplex-list:char
45 after-row:num
46 after-column:num
47 after-top-of-screen:&:duplex-list:char
48 deleted-text:&:duplex-list:char
49 delete-from:&:duplex-list:char
50 delete-until:&:duplex-list:char
51 tag:num
52
53
54
55 ]
56
57
58 container editor [
59 undo:&:list:&:operation
60 redo:&:list:&:operation
61 ]
62
63
64 after <handle-special-character> [
65 {
66 undo?:bool <- equal c, 26/ctrl-z
67 break-unless undo?
68 undo:&:list:&:operation <- get *editor, undo:offset
69 break-unless undo
70 op:&:operation <- first undo
71 undo <- rest undo
72 *editor <- put *editor, undo:offset, undo
73 redo:&:list:&:operation <- get *editor, redo:offset
74 redo <- push op, redo
75 *editor <- put *editor, redo:offset, redo
76 <handle-undo>
77 return 1/go-render
78 }
79 ]
80
81
82 after <handle-special-character> [
83 {
84 redo?:bool <- equal c, 25/ctrl-y
85 break-unless redo?
86 redo:&:list:&:operation <- get *editor, redo:offset
87 break-unless redo
88 op:&:operation <- first redo
89 redo <- rest redo
90 *editor <- put *editor, redo:offset, redo
91 undo:&:list:&:operation <- get *editor, undo:offset
92 undo <- push op, undo
93 *editor <- put *editor, undo:offset, undo
94 <handle-redo>
95 return 1/go-render
96 }
97 ]
98
99
100
101 scenario editor-can-undo-typing [
102 local-scope
103
104 assume-screen 10/width, 5/height
105 e:&:editor <- new-editor [], 0/left, 10/right
106 editor-render screen, e
107 assume-console [
108 type [0]
109 ]
110 editor-event-loop screen, console, e
111
112 assume-console [
113 press ctrl-z
114 ]
115 run [
116 editor-event-loop screen, console, e
117 ]
118
119 screen-should-contain [
120 . .
121 . .
122 .╌╌╌╌╌╌╌╌╌╌.
123 . .
124 ]
125
126 assume-console [
127 type [1]
128 ]
129 run [
130 editor-event-loop screen, console, e
131 ]
132 screen-should-contain [
133 . .
134 .1 .
135 .╌╌╌╌╌╌╌╌╌╌.
136 . .
137 ]
138 ]
139
140
141 after <insert-character-begin> [
142 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
143 cursor-before:&:duplex-list:char <- get *editor, before-cursor:offset
144 ]
145 before <insert-character-end> [
146 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
147 cursor-row:num <- get *editor, cursor-row:offset
148 cursor-column:num <- get *editor, cursor-column:offset
149 undo:&:list:&:operation <- get *editor, undo:offset
150 {
151
152 break-unless undo
153 op:&:operation <- first undo
154 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant
155 break-unless is-insert?
156 previous-coalesce-tag:num <- get typing, tag:offset
157 break-unless previous-coalesce-tag
158 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
159 insert-until:&:duplex-list:char <- next before-cursor
160 typing <- put typing, insert-until:offset, insert-until
161 typing <- put typing, after-row:offset, cursor-row
162 typing <- put typing, after-column:offset, cursor-column
163 typing <- put typing, after-top-of-screen:offset, top-after
164 *op <- merge 0/insert-operation, typing
165 break +done-adding-insert-operation
166 }
167
168 insert-from:&:duplex-list:char <- next cursor-before
169 insert-to:&:duplex-list:char <- next insert-from
170 op:&:operation <- new operation:type
171 *op <- merge 0/insert-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, insert-from, insert-to, 1/coalesce
172 editor <- add-operation editor, op
173 +done-adding-insert-operation
174 ]
175
176
177 after <insert-enter-begin> [
178 cursor-row-before:num <- copy cursor-row
179 cursor-column-before:num <- copy cursor-column
180 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
181 cursor-before:&:duplex-list:char <- get *editor, before-cursor:offset
182 ]
183 before <insert-enter-end> [
184 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
185 cursor-row:num <- get *editor, cursor-row:offset
186 cursor-column:num <- get *editor, cursor-row:offset
187
188 insert-from:&:duplex-list:char <- next cursor-before
189 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
190 insert-to:&:duplex-list:char <- next before-cursor
191 op:&:operation <- new operation:type
192 *op <- merge 0/insert-operation, cursor-row-before, cursor-column-before, top-before, cursor-row/after, cursor-column/after, top-after, insert-from, insert-to, 0/never-coalesce
193 editor <- add-operation editor, op
194 ]
195
196
197
198
199
200 def add-operation editor:&:editor, op:&:operation -> editor:&:editor [
201 local-scope
202 load-ingredients
203 undo:&:list:&:operation <- get *editor, undo:offset
204 undo <- push op undo
205 *editor <- put *editor, undo:offset, undo
206 redo:&:list:&:operation <- get *editor, redo:offset
207 redo <- copy 0
208 *editor <- put *editor, redo:offset, redo
209 ]
210
211 after <handle-undo> [
212 {
213 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant
214 break-unless is-insert?
215 start:&:duplex-list:char <- get typing, insert-from:offset
216 end:&:duplex-list:char <- get typing, insert-until:offset
217
218 before-cursor:&:duplex-list:char <- prev start
219 *editor <- put *editor, before-cursor:offset, before-cursor
220 remove-between before-cursor, end
221 cursor-row <- get typing, before-row:offset
222 *editor <- put *editor, cursor-row:offset, cursor-row
223 cursor-column <- get typing, before-column:offset
224 *editor <- put *editor, cursor-column:offset, cursor-column
225 top:&:duplex-list:char <- get typing, before-top-of-screen:offset
226 *editor <- put *editor, top-of-screen:offset, top
227 }
228 ]
229
230 scenario editor-can-undo-typing-multiple [
231 local-scope
232
233 assume-screen 10/width, 5/height
234 e:&:editor <- new-editor [], 0/left, 10/right
235 editor-render screen, e
236 assume-console [
237 type [012]
238 ]
239 editor-event-loop screen, console, e
240
241 assume-console [
242 press ctrl-z
243 ]
244 run [
245 editor-event-loop screen, console, e
246 ]
247
248 screen-should-contain [
249 . .
250 . .
251 .╌╌╌╌╌╌╌╌╌╌.
252 . .
253 ]
254 ]
255
256 scenario editor-can-undo-typing-multiple-2 [
257 local-scope
258
259 assume-screen 10/width, 5/height
260 e:&:editor <- new-editor [a], 0/left, 10/right
261 editor-render screen, e
262
263 assume-console [
264 type [012]
265 ]
266 editor-event-loop screen, console, e
267 screen-should-contain [
268 . .
269 .012a .
270 .╌╌╌╌╌╌╌╌╌╌.
271 . .
272 ]
273
274 assume-console [
275 press ctrl-z
276 ]
277 run [
278 editor-event-loop screen, console, e
279 ]
280
281 screen-should-contain [
282 . .
283 .a .
284 .╌╌╌╌╌╌╌╌╌╌.
285 . .
286 ]
287
288 assume-console [
289 type [3]
290 ]
291 run [
292 editor-event-loop screen, console, e
293 ]
294 screen-should-contain [
295 . .
296 .3a .
297 .╌╌╌╌╌╌╌╌╌╌.
298 . .
299 ]
300 ]
301
302 scenario editor-can-undo-typing-enter [
303 local-scope
304
305 assume-screen 10/width, 5/height
306 e:&:editor <- new-editor [ abc], 0/left, 10/right
307 editor-render screen, e
308
309 assume-console [
310 left-click 1, 8
311 press enter
312 ]
313 editor-event-loop screen, console, e
314 screen-should-contain [
315 . .
316 . abc .
317 . .
318 .╌╌╌╌╌╌╌╌╌╌.
319 . .
320 ]
321
322 3:num/raw <- get *e, cursor-row:offset
323 4:num/raw <- get *e, cursor-column:offset
324 memory-should-contain [
325 3 <- 2
326 4 <- 2
327 ]
328
329 assume-console [
330 press ctrl-z
331 ]
332 run [
333 editor-event-loop screen, console, e
334 ]
335 3:num/raw <- get *e, cursor-row:offset
336 4:num/raw <- get *e, cursor-column:offset
337 memory-should-contain [
338 3 <- 1
339 4 <- 5
340 ]
341
342 screen-should-contain [
343 . .
344 . abc .
345 .╌╌╌╌╌╌╌╌╌╌.
346 . .
347 ]
348
349 assume-console [
350 type [1]
351 ]
352 run [
353 editor-event-loop screen, console, e
354 ]
355 screen-should-contain [
356 . .
357 . abc1 .
358 .╌╌╌╌╌╌╌╌╌╌.
359 . .
360 ]
361 ]
362
363
364
365 scenario editor-redo-typing [
366 local-scope
367
368 assume-screen 10/width, 5/height
369 e:&:editor <- new-editor [a], 0/left, 10/right
370 editor-render screen, e
371 assume-console [
372 type [012]
373 press ctrl-z
374 ]
375 editor-event-loop screen, console, e
376 screen-should-contain [
377 . .
378 .a .
379 .╌╌╌╌╌╌╌╌╌╌.
380 . .
381 ]
382
383 assume-console [
384 press ctrl-y
385 ]
386 run [
387 editor-event-loop screen, console, e
388 ]
389
390 screen-should-contain [
391 . .
392 .012a .
393 .╌╌╌╌╌╌╌╌╌╌.
394 . .
395 ]
396
397 assume-console [
398 type [3]
399 ]
400 run [
401 editor-event-loop screen, console, e
402 ]
403 screen-should-contain [
404 . .
405 .0123a .
406 .╌╌╌╌╌╌╌╌╌╌.
407 . .
408 ]
409 ]
410
411 after <handle-redo> [
412 {
413 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant
414 break-unless is-insert?
415 before-cursor <- get *editor, before-cursor:offset
416 insert-from:&:duplex-list:char <- get typing, insert-from:offset
417
418 insert-range before-cursor, insert-from
419
420 cursor-row <- get typing, after-row:offset
421 *editor <- put *editor, cursor-row:offset, cursor-row
422 cursor-column <- get typing, after-column:offset
423 *editor <- put *editor, cursor-column:offset, cursor-column
424 top:&:duplex-list:char <- get typing, after-top-of-screen:offset
425 *editor <- put *editor, top-of-screen:offset, top
426 }
427 ]
428
429 scenario editor-redo-typing-empty [
430 local-scope
431
432 assume-screen 10/width, 5/height
433 e:&:editor <- new-editor [], 0/left, 10/right
434 editor-render screen, e
435 assume-console [
436 type [012]
437 press ctrl-z
438 ]
439 editor-event-loop screen, console, e
440 screen-should-contain [
441 . .
442 . .
443 .╌╌╌╌╌╌╌╌╌╌.
444 . .
445 ]
446
447 assume-console [
448 press ctrl-y
449 ]
450 run [
451 editor-event-loop screen, console, e
452 ]
453
454 screen-should-contain [
455 . .
456 .012 .
457 .╌╌╌╌╌╌╌╌╌╌.
458 . .
459 ]
460
461 assume-console [
462 type [3]
463 ]
464 run [
465 editor-event-loop screen, console, e
466 ]
467 screen-should-contain [
468 . .
469 .0123 .
470 .╌╌╌╌╌╌╌╌╌╌.
471 . .
472 ]
473 ]
474
475 scenario editor-work-clears-redo-stack [
476 local-scope
477
478 assume-screen 10/width, 5/height
479 contents:text <- new [abc
480 def
481 ghi]
482 e:&:editor <- new-editor contents, 0/left, 10/right
483 editor-render screen, e
484 assume-console [
485 type [1]
486 press ctrl-z
487 ]
488 editor-event-loop screen, console, e
489
490 assume-console [
491 type [0]
492 ]
493 editor-event-loop screen, console, e
494 screen-should-contain [
495 . .
496 .0abc .
497 .def .
498 .ghi .
499 .╌╌╌╌╌╌╌╌╌╌.
500 ]
501
502 assume-console [
503 press ctrl-y
504 ]
505 run [
506 editor-event-loop screen, console, e
507 ]
508
509 screen-should-contain [
510 . .
511 .0abc .
512 .def .
513 .ghi .
514 .╌╌╌╌╌╌╌╌╌╌.
515 ]
516 ]
517
518 scenario editor-can-redo-typing-and-enter-and-tab [
519 local-scope
520
521 assume-screen 10/width, 5/height
522 e:&:editor <- new-editor [], 0/left, 10/right
523 editor-render screen, e
524
525 assume-console [
526 press tab
527 type [ab]
528 press tab
529 type [cd]
530 press enter
531 press tab
532 type [efg]
533 ]
534 editor-event-loop screen, console, e
535 screen-should-contain [
536 . .
537 . ab cd .
538 . efg .
539 .╌╌╌╌╌╌╌╌╌╌.
540 . .
541 ]
542 3:num/raw <- get *e, cursor-row:offset
543 4:num/raw <- get *e, cursor-column:offset
544 memory-should-contain [
545 3 <- 2
546 4 <- 7
547 ]
548
549 assume-console [
550 press ctrl-z
551 ]
552 run [
553 editor-event-loop screen, console, e
554 ]
555
556 3:num/raw <- get *e, cursor-row:offset
557 4:num/raw <- get *e, cursor-column:offset
558 memory-should-contain [
559 3 <- 2
560 4 <- 2
561 ]
562 screen-should-contain [
563 . .
564 . ab cd .
565 . .
566 .╌╌╌╌╌╌╌╌╌╌.
567 . .
568 ]
569
570 assume-console [
571 press ctrl-z
572 ]
573 run [
574 editor-event-loop screen, console, e
575 ]
576
577 3:num/raw <- get *e, cursor-row:offset
578 4:num/raw <- get *e, cursor-column:offset
579 memory-should-contain [
580 3 <- 1
581 4 <- 8
582 ]
583 screen-should-contain [
584 . .
585 . ab cd .
586 .╌╌╌╌╌╌╌╌╌╌.
587 . .
588 ]
589
590 assume-console [
591 press ctrl-z
592 ]
593 run [
594 editor-event-loop screen, console, e
595 ]
596
597 3:num/raw <- get *e, cursor-row:offset
598 4:num/raw <- get *e, cursor-column:offset
599 memory-should-contain [
600 3 <- 1
601 4 <- 0
602 ]
603 screen-should-contain [
604 . .
605 . .
606 .╌╌╌╌╌╌╌╌╌╌.
607 . .
608 ]
609
610 assume-console [
611 press ctrl-y
612 ]
613 run [
614 editor-event-loop screen, console, e
615 ]
616
617 3:num/raw <- get *e, cursor-row:offset
618 4:num/raw <- get *e, cursor-column:offset
619 memory-should-contain [
620 3 <- 1
621 4 <- 8
622 ]
623 screen-should-contain [
624 . .
625 . ab cd .
626 .╌╌╌╌╌╌╌╌╌╌.
627 . .
628 ]
629
630 assume-console [
631 press ctrl-y
632 ]
633 run [
634 editor-event-loop screen, console, e
635 ]
636
637 3:num/raw <- get *e, cursor-row:offset
638 4:num/raw <- get *e, cursor-column:offset
639 memory-should-contain [
640 3 <- 2
641 4 <- 2
642 ]
643 screen-should-contain [
644 . .
645 . ab cd .
646 . .
647 .╌╌╌╌╌╌╌╌╌╌.
648 . .
649 ]
650
651 assume-console [
652 press ctrl-y
653 ]
654 run [
655 editor-event-loop screen, console, e
656 ]
657
658 3:num/raw <- get *e, cursor-row:offset
659 4:num/raw <- get *e, cursor-column:offset
660 memory-should-contain [
661 3 <- 2
662 4 <- 7
663 ]
664 screen-should-contain [
665 . .
666 . ab cd .
667 . efg .
668 .╌╌╌╌╌╌╌╌╌╌.
669 . .
670 ]
671 ]
672
673
674
675 scenario editor-can-undo-touch [
676 local-scope
677
678 assume-screen 10/width, 5/height
679 contents:text <- new [abc
680 def
681 ghi]
682 e:&:editor <- new-editor contents, 0/left, 10/right
683 editor-render screen, e
684
685 assume-console [
686 left-click 3, 1
687 ]
688 editor-event-loop screen, console, e
689
690 assume-console [
691 press ctrl-z
692 ]
693 run [
694 editor-event-loop screen, console, e
695 ]
696
697 3:num/raw <- get *e, cursor-row:offset
698 4:num/raw <- get *e, cursor-column:offset
699 memory-should-contain [
700 3 <- 1
701 4 <- 0
702 ]
703
704 assume-console [
705 type [1]
706 ]
707 run [
708 editor-event-loop screen, console, e
709 ]
710 screen-should-contain [
711 . .
712 .1abc .
713 .def .
714 .ghi .
715 .╌╌╌╌╌╌╌╌╌╌.
716 ]
717 ]
718
719 after <move-cursor-begin> [
720 cursor-row-before:num <- get *editor, cursor-row:offset
721 cursor-column-before:num <- get *editor, cursor-column:offset
722 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
723 ]
724 before <move-cursor-end> [
725 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
726 cursor-row:num <- get *editor, cursor-row:offset
727 cursor-column:num <- get *editor, cursor-column:offset
728 {
729 break-unless undo-coalesce-tag
730
731
732 undo:&:list:&:operation <- get *editor, undo:offset
733 break-unless undo
734 op:&:operation <- first undo
735 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant
736 break-unless is-move?
737 previous-coalesce-tag:num <- get move, tag:offset
738 coalesce?:bool <- equal undo-coalesce-tag, previous-coalesce-tag
739 break-unless coalesce?
740 move <- put move, after-row:offset, cursor-row
741 move <- put move, after-column:offset, cursor-column
742 move <- put move, after-top-of-screen:offset, top-after
743 *op <- merge 1/move-operation, move
744 break +done-adding-move-operation
745 }
746 op:&:operation <- new operation:type
747 *op <- merge 1/move-operation, cursor-row-before, cursor-column-before, top-before, cursor-row/after, cursor-column/after, top-after, undo-coalesce-tag
748 editor <- add-operation editor, op
749 +done-adding-move-operation
750 ]
751
752 after <handle-undo> [
753 {
754 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant
755 break-unless is-move?
756
757 cursor-row <- get move, before-row:offset
758 *editor <- put *editor, cursor-row:offset, cursor-row
759 cursor-column <- get move, before-column:offset
760 *editor <- put *editor, cursor-column:offset, cursor-column
761 top:&:duplex-list:char <- get move, before-top-of-screen:offset
762 *editor <- put *editor, top-of-screen:offset, top
763 }
764 ]
765
766 scenario editor-can-undo-scroll [
767 local-scope
768
769 assume-screen 5/width, 4/height
770
771 contents:text <- new [a
772 b
773 cdefgh]
774 e:&:editor <- new-editor contents, 0/left, 5/right
775
776 assume-console [
777 left-click 3, 3
778 press right-arrow
779 ]
780 editor-event-loop screen, console, e
781 3:num/raw <- get *e, cursor-row:offset
782 4:num/raw <- get *e, cursor-column:offset
783
784 screen-should-contain [
785 . .
786 .b .
787 .cdef↩.
788 .gh .
789 ]
790 memory-should-contain [
791 3 <- 3
792 4 <- 0
793 ]
794
795 assume-console [
796 press ctrl-z
797 ]
798 run [
799 editor-event-loop screen, console, e
800 ]
801
802 3:num/raw <- get *e, cursor-row:offset
803 4:num/raw <- get *e, cursor-column:offset
804 memory-should-contain [
805 3 <- 3
806 4 <- 3
807 ]
808
809 screen-should-contain [
810 . .
811 .a .
812 .b .
813 .cdef↩.
814 ]
815
816 assume-console [
817 type [1]
818 ]
819 run [
820 editor-event-loop screen, console, e
821 ]
822 screen-should-contain [
823 . .
824 .b .
825 .cde1↩.
826 .fgh .
827 ]
828 ]
829
830 scenario editor-can-undo-left-arrow [
831 local-scope
832
833 assume-screen 10/width, 5/height
834 contents:text <- new [abc
835 def
836 ghi]
837 e:&:editor <- new-editor contents, 0/left, 10/right
838 editor-render screen, e
839
840 assume-console [
841 left-click 3, 1
842 press left-arrow
843 ]
844 editor-event-loop screen, console, e
845
846 assume-console [
847 press ctrl-z
848 ]
849 run [
850 editor-event-loop screen, console, e
851 ]
852
853 3:num/raw <- get *e, cursor-row:offset
854 4:num/raw <- get *e, cursor-column:offset
855 memory-should-contain [
856 3 <- 3
857 4 <- 1
858 ]
859
860 assume-console [
861 type [1]
862 ]
863 run [
864 editor-event-loop screen, console, e
865 ]
866 screen-should-contain [
867 . .
868 .abc .
869 .def .
870 .g1hi .
871 .╌╌╌╌╌╌╌╌╌╌.
872 ]
873 ]
874
875 scenario editor-can-undo-up-arrow [
876 local-scope
877
878 assume-screen 10/width, 5/height
879 contents:text <- new [abc
880 def
881 ghi]
882 e:&:editor <- new-editor contents, 0/left, 10/right
883 editor-render screen, e
884
885 assume-console [
886 left-click 3, 1
887 press up-arrow
888 ]
889 editor-event-loop screen, console, e
890 3:num/raw <- get *e, cursor-row:offset
891 4:num/raw <- get *e, cursor-column:offset
892 memory-should-contain [
893 3 <- 2
894 4 <- 1
895 ]
896
897 assume-console [
898 press ctrl-z
899 ]
900 run [
901 editor-event-loop screen, console, e
902 ]
903
904 3:num/raw <- get *e, cursor-row:offset
905 4:num/raw <- get *e, cursor-column:offset
906 memory-should-contain [
907 3 <- 3
908 4 <- 1
909 ]
910
911 assume-console [
912 type [1]
913 ]
914 run [
915 editor-event-loop screen, console, e
916 ]
917 screen-should-contain [
918 . .
919 .abc .
920 .def .
921 .g1hi .
922 .╌╌╌╌╌╌╌╌╌╌.
923 ]
924 ]
925
926 scenario editor-can-undo-down-arrow [
927 local-scope
928
929 assume-screen 10/width, 5/height
930 contents:text <- new [abc
931 def
932 ghi]
933 e:&:editor <- new-editor contents, 0/left, 10/right
934 editor-render screen, e
935
936 assume-console [
937 left-click 2, 1
938 press down-arrow
939 ]
940 editor-event-loop screen, console, e
941
942 assume-console [
943 press ctrl-z
944 ]
945 run [
946 editor-event-loop screen, console, e
947 ]
948
949 3:num/raw <- get *e, cursor-row:offset
950 4:num/raw <- get *e, cursor-column:offset
951 memory-should-contain [
952 3 <- 2
953 4 <- 1
954 ]
955
956 assume-console [
957 type [1]
958 ]
959 run [
960 editor-event-loop screen, console, e
961 ]
962 screen-should-contain [
963 . .
964 .abc .
965 .d1ef .
966 .ghi .
967 .╌╌╌╌╌╌╌╌╌╌.
968 ]
969 ]
970
971 scenario editor-can-undo-ctrl-f [
972 local-scope
973
974 assume-screen 10/width, 5/height
975 contents:text <- new [a
976 b
977 c
978 d
979 e
980 f]
981 e:&:editor <- new-editor contents, 0/left, 10/right
982 editor-render screen, e
983
984 assume-console [
985 press ctrl-f
986 ]
987 editor-event-loop screen, console, e
988
989 assume-console [
990 press ctrl-z
991 ]
992 run [
993 editor-event-loop screen, console, e
994 ]
995
996 screen-should-contain [
997 . .
998 .a .
999 .b .
1000 .c .
1001 .d .
1002 ]
1003 ]
1004
1005 scenario editor-can-undo-page-down [
1006 local-scope
1007
1008 assume-screen 10/width, 5/height
1009 contents:text <- new [a
1010 b
1011 c
1012 d
1013 e
1014 f]
1015 e:&:editor <- new-editor contents, 0/left, 10/right
1016 editor-render screen, e
1017
1018 assume-console [
1019 press page-down
1020 ]
1021 editor-event-loop screen, console, e
1022
1023 assume-console [
1024 press ctrl-z
1025 ]
1026 run [
1027 editor-event-loop screen, console, e
1028 ]
1029
1030 screen-should-contain [
1031 . .
1032 .a .
1033 .b .
1034 .c .
1035 .d .
1036 ]
1037 ]
1038
1039 scenario editor-can-undo-ctrl-b [
1040 local-scope
1041
1042 assume-screen 10/width, 5/height
1043 contents:text <- new [a
1044 b
1045 c
1046 d
1047 e
1048 f]
1049 e:&:editor <- new-editor contents, 0/left, 10/right
1050 editor-render screen, e
1051
1052 assume-console [
1053 press page-down
1054 press ctrl-b
1055 ]
1056 editor-event-loop screen, console, e
1057
1058 assume-console [
1059 press ctrl-z
1060 ]
1061 run [
1062 editor-event-loop screen, console, e
1063 ]
1064
1065 screen-should-contain [
1066 . .
1067 .d .
1068 .e .
1069 .f .
1070 .╌╌╌╌╌╌╌╌╌╌.
1071 ]
1072 ]
1073
1074 scenario editor-can-undo-page-up [
1075 local-scope
1076
1077 assume-screen 10/width, 5/height
1078 contents:text <- new [a
1079 b
1080 c
1081 d
1082 e
1083 f]
1084 e:&:editor <- new-editor contents, 0/left, 10/right
1085 editor-render screen, e
1086
1087 assume-console [
1088 press page-down
1089 press page-up
1090 ]
1091 editor-event-loop screen, console, e
1092
1093 assume-console [
1094 press ctrl-z
1095 ]
1096 run [
1097 editor-event-loop screen, console, e
1098 ]
1099
1100 screen-should-contain [
1101 . .
1102 .d .
1103 .e .
1104 .f .
1105 .╌╌╌╌╌╌╌╌╌╌.
1106 ]
1107 ]
1108
1109 scenario editor-can-undo-ctrl-a [
1110 local-scope
1111
1112 assume-screen 10/width, 5/height
1113 contents:text <- new [abc
1114 def
1115 ghi]
1116 e:&:editor <- new-editor contents, 0/left, 10/right
1117 editor-render screen, e
1118
1119 assume-console [
1120 left-click 2, 1
1121 press ctrl-a
1122 ]
1123 editor-event-loop screen, console, e
1124
1125 assume-console [
1126 press ctrl-z
1127 ]
1128 run [
1129 editor-event-loop screen, console, e
1130 ]
1131
1132 3:num/raw <- get *e, cursor-row:offset
1133 4:num/raw <- get *e, cursor-column:offset
1134 memory-should-contain [
1135 3 <- 2
1136 4 <- 1
1137 ]
1138
1139 assume-console [
1140 type [1]
1141 ]
1142 run [
1143 editor-event-loop screen, console, e
1144 ]
1145 screen-should-contain [
1146 . .
1147 .abc .
1148 .d1ef .
1149 .ghi .
1150 .╌╌╌╌╌╌╌╌╌╌.
1151 ]
1152 ]
1153
1154 scenario editor-can-undo-home [
1155 local-scope
1156
1157 assume-screen 10/width, 5/height
1158 contents:text <- new [abc
1159 def
1160 ghi]
1161 e:&:editor <- new-editor contents, 0/left, 10/right
1162 editor-render screen, e
1163
1164 assume-console [
1165 left-click 2, 1
1166 press home
1167 ]
1168 editor-event-loop screen, console, e
1169
1170 assume-console [
1171 press ctrl-z
1172 ]
1173 run [
1174 editor-event-loop screen, console, e
1175 ]
1176
1177 3:num/raw <- get *e, cursor-row:offset
1178 4:num/raw <- get *e, cursor-column:offset
1179 memory-should-contain [
1180 3 <- 2
1181 4 <- 1
1182 ]
1183
1184 assume-console [
1185 type [1]
1186 ]
1187 run [
1188 editor-event-loop screen, console, e
1189 ]
1190 screen-should-contain [
1191 . .
1192 .abc .
1193 .d1ef .
1194 .ghi .
1195 .╌╌╌╌╌╌╌╌╌╌.
1196 ]
1197 ]
1198
1199 scenario editor-can-undo-ctrl-e [
1200 local-scope
1201
1202 assume-screen 10/width, 5/height
1203 contents:text <- new [abc
1204 def
1205 ghi]
1206 e:&:editor <- new-editor contents, 0/left, 10/right
1207 editor-render screen, e
1208
1209 assume-console [
1210 left-click 2, 1
1211 press ctrl-e
1212 ]
1213 editor-event-loop screen, console, e
1214
1215 assume-console [
1216 press ctrl-z
1217 ]
1218 run [
1219 editor-event-loop screen, console, e
1220 ]
1221
1222 3:num/raw <- get *e, cursor-row:offset
1223 4:num/raw <- get *e, cursor-column:offset
1224 memory-should-contain [
1225 3 <- 2
1226 4 <- 1
1227 ]
1228
1229 assume-console [
1230 type [1]
1231 ]
1232 run [
1233 editor-event-loop screen, console, e
1234 ]
1235 screen-should-contain [
1236 . .
1237 .abc .
1238 .d1ef .
1239 .ghi .
1240 .╌╌╌╌╌╌╌╌╌╌.
1241 ]
1242 ]
1243
1244 scenario editor-can-undo-end [
1245 local-scope
1246
1247 assume-screen 10/width, 5/height
1248 contents:text <- new [abc
1249 def
1250 ghi]
1251 e:&:editor <- new-editor contents, 0/left, 10/right
1252 editor-render screen, e
1253
1254 assume-console [
1255 left-click 2, 1
1256 press end
1257 ]
1258 editor-event-loop screen, console, e
1259
1260 assume-console [
1261 press ctrl-z
1262 ]
1263 run [
1264 editor-event-loop screen, console, e
1265 ]
1266
1267 3:num/raw <- get *e, cursor-row:offset
1268 4:num/raw <- get *e, cursor-column:offset
1269 memory-should-contain [
1270 3 <- 2
1271 4 <- 1
1272 ]
1273
1274 assume-console [
1275 type [1]
1276 ]
1277 run [
1278 editor-event-loop screen, console, e
1279 ]
1280 screen-should-contain [
1281 . .
1282 .abc .
1283 .d1ef .
1284 .ghi .
1285 .╌╌╌╌╌╌╌╌╌╌.
1286 ]
1287 ]
1288
1289 scenario editor-can-undo-multiple-arrows-in-the-same-direction [
1290 local-scope
1291
1292 assume-screen 10/width, 5/height
1293 contents:text <- new [abc
1294 def
1295 ghi]
1296 e:&:editor <- new-editor contents, 0/left, 10/right
1297 editor-render screen, e
1298
1299 assume-console [
1300 left-click 2, 1
1301 press right-arrow
1302 press right-arrow
1303 press up-arrow
1304 ]
1305 editor-event-loop screen, console, e
1306 3:num/raw <- get *e, cursor-row:offset
1307 4:num/raw <- get *e, cursor-column:offset
1308 memory-should-contain [
1309 3 <- 1
1310 4 <- 3
1311 ]
1312
1313 assume-console [
1314 press ctrl-z
1315 ]
1316 run [
1317 editor-event-loop screen, console, e
1318 ]
1319
1320 3:num/raw <- get *e, cursor-row:offset
1321 4:num/raw <- get *e, cursor-column:offset
1322 memory-should-contain [
1323 3 <- 2
1324 4 <- 3
1325 ]
1326
1327 assume-console [
1328 press ctrl-z
1329 ]
1330 run [
1331 editor-event-loop screen, console, e
1332 ]
1333
1334 3:num/raw <- get *e, cursor-row:offset
1335 4:num/raw <- get *e, cursor-column:offset
1336 memory-should-contain [
1337 3 <- 2
1338 4 <- 1
1339 ]
1340 ]
1341
1342
1343
1344 scenario editor-redo-touch [
1345 local-scope
1346
1347 assume-screen 10/width, 5/height
1348 contents:text <- new [abc
1349 def
1350 ghi]
1351 e:&:editor <- new-editor contents, 0/left, 10/right
1352 editor-render screen, e
1353 assume-console [
1354 left-click 3, 1
1355 press ctrl-z
1356 ]
1357 editor-event-loop screen, console, e
1358
1359 assume-console [
1360 press ctrl-y
1361 ]
1362 run [
1363 editor-event-loop screen, console, e
1364 ]
1365
1366 3:num/raw <- get *e, cursor-row:offset
1367 4:num/raw <- get *e, cursor-column:offset
1368 memory-should-contain [
1369 3 <- 3
1370 4 <- 1
1371 ]
1372
1373 assume-console [
1374 type [1]
1375 ]
1376 run [
1377 editor-event-loop screen, console, e
1378 ]
1379 screen-should-contain [
1380 . .
1381 .abc .
1382 .def .
1383 .g1hi .
1384 .╌╌╌╌╌╌╌╌╌╌.
1385 ]
1386 ]
1387
1388 after <handle-redo> [
1389 {
1390 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant
1391 break-unless is-move?
1392
1393 cursor-row <- get move, after-row:offset
1394 *editor <- put *editor, cursor-row:offset, cursor-row
1395 cursor-column <- get move, after-column:offset
1396 *editor <- put *editor, cursor-column:offset, cursor-column
1397 top:&:duplex-list:char <- get move, after-top-of-screen:offset
1398 *editor <- put *editor, top-of-screen:offset, top
1399 }
1400 ]
1401
1402 scenario editor-separates-undo-insert-from-undo-cursor-move [
1403 local-scope
1404
1405 assume-screen 10/width, 5/height
1406 e:&:editor <- new-editor [], 0/left, 10/right
1407 editor-render screen, e
1408 assume-console [
1409 type [abc]
1410 left-click 1, 1
1411 type [d]
1412 ]
1413 editor-event-loop screen, console, e
1414 3:num/raw <- get *e, cursor-row:offset
1415 4:num/raw <- get *e, cursor-column:offset
1416 screen-should-contain [
1417 . .
1418 .adbc .
1419 .╌╌╌╌╌╌╌╌╌╌.
1420 . .
1421 ]
1422 memory-should-contain [
1423 3 <- 1
1424 4 <- 2
1425 ]
1426
1427 assume-console [
1428 press ctrl-z
1429 ]
1430 run [
1431 editor-event-loop screen, console, e
1432 3:num/raw <- get *e, cursor-row:offset
1433 4:num/raw <- get *e, cursor-column:offset
1434 ]
1435
1436 screen-should-contain [
1437 . .
1438 .abc .
1439 .╌╌╌╌╌╌╌╌╌╌.
1440 . .
1441 ]
1442 memory-should-contain [
1443 3 <- 1
1444 4 <- 1
1445 ]
1446
1447 assume-console [
1448 press ctrl-z
1449 ]
1450 run [
1451 editor-event-loop screen, console, e
1452 3:num/raw <- get *e, cursor-row:offset
1453 4:num/raw <- get *e, cursor-column:offset
1454 ]
1455
1456 screen-should-contain [
1457 . .
1458 .abc .
1459 .╌╌╌╌╌╌╌╌╌╌.
1460 . .
1461 ]
1462 memory-should-contain [
1463 3 <- 1
1464 4 <- 3
1465 ]
1466
1467 assume-console [
1468 press ctrl-z
1469 ]
1470 run [
1471 editor-event-loop screen, console, e
1472 3:num/raw <- get *e, cursor-row:offset
1473 4:num/raw <- get *e, cursor-column:offset
1474 ]
1475
1476 screen-should-contain [
1477 . .
1478 . .
1479 .╌╌╌╌╌╌╌╌╌╌.
1480 . .
1481 ]
1482 memory-should-contain [
1483 3 <- 1
1484 4 <- 0
1485 ]
1486
1487 assume-console [
1488 press ctrl-y
1489 ]
1490 run [
1491 editor-event-loop screen, console, e
1492 3:num/raw <- get *e, cursor-row:offset
1493 4:num/raw <- get *e, cursor-column:offset
1494 ]
1495
1496 screen-should-contain [
1497 . .
1498 .abc .
1499 .╌╌╌╌╌╌╌╌╌╌.
1500 . .
1501 ]
1502 memory-should-contain [
1503 3 <- 1
1504 4 <- 3
1505 ]
1506
1507 assume-console [
1508 press ctrl-y
1509 ]
1510 run [
1511 editor-event-loop screen, console, e
1512 3:num/raw <- get *e, cursor-row:offset
1513 4:num/raw <- get *e, cursor-column:offset
1514 ]
1515
1516 screen-should-contain [
1517 . .
1518 .abc .
1519 .╌╌╌╌╌╌╌╌╌╌.
1520 . .
1521 ]
1522
1523 memory-should-contain [
1524 3 <- 1
1525 4 <- 1
1526 ]
1527
1528 assume-console [
1529 press ctrl-y
1530 ]
1531 run [
1532 editor-event-loop screen, console, e
1533 3:num/raw <- get *e, cursor-row:offset
1534 4:num/raw <- get *e, cursor-column:offset
1535 ]
1536
1537 screen-should-contain [
1538 . .
1539 .adbc .
1540 .╌╌╌╌╌╌╌╌╌╌.
1541 . .
1542 ]
1543 memory-should-contain [
1544 3 <- 1
1545 4 <- 2
1546 ]
1547 ]
1548
1549
1550
1551 scenario editor-can-undo-and-redo-backspace [
1552 local-scope
1553
1554 assume-screen 10/width, 5/height
1555 e:&:editor <- new-editor [], 0/left, 10/right
1556 editor-render screen, e
1557
1558 assume-console [
1559 type [abc]
1560 press backspace
1561 press backspace
1562 ]
1563 editor-event-loop screen, console, e
1564 screen-should-contain [
1565 . .
1566 .a .
1567 .╌╌╌╌╌╌╌╌╌╌.
1568 . .
1569 ]
1570 3:num/raw <- get *e, cursor-row:offset
1571 4:num/raw <- get *e, cursor-column:offset
1572 memory-should-contain [
1573 3 <- 1
1574 4 <- 1
1575 ]
1576
1577 assume-console [
1578 press ctrl-z
1579 ]
1580 run [
1581 editor-event-loop screen, console, e
1582 ]
1583 3:num/raw <- get *e, cursor-row:offset
1584 4:num/raw <- get *e, cursor-column:offset
1585 memory-should-contain [
1586 3 <- 1
1587 4 <- 3
1588 ]
1589 screen-should-contain [
1590 . .
1591 .abc .
1592 .╌╌╌╌╌╌╌╌╌╌.
1593 . .
1594 ]
1595
1596 assume-console [
1597 press ctrl-y
1598 ]
1599 run [
1600 editor-event-loop screen, console, e
1601 ]
1602 3:num/raw <- get *e, cursor-row:offset
1603 4:num/raw <- get *e, cursor-column:offset
1604 memory-should-contain [
1605 3 <- 1
1606 4 <- 1
1607 ]
1608 screen-should-contain [
1609 . .
1610 .a .
1611 .╌╌╌╌╌╌╌╌╌╌.
1612 . .
1613 ]
1614 ]
1615
1616
1617 after <backspace-character-begin> [
1618 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
1619 ]
1620 before <backspace-character-end> [
1621 {
1622 break-unless backspaced-cell
1623 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
1624 cursor-row:num <- get *editor, cursor-row:offset
1625 cursor-column:num <- get *editor, cursor-row:offset
1626 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1627 undo:&:list:&:operation <- get *editor, undo:offset
1628 {
1629
1630 break-unless undo
1631 op:&:operation <- first undo
1632 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant
1633 break-unless is-delete?
1634 previous-coalesce-tag:num <- get deletion, tag:offset
1635 coalesce?:bool <- equal previous-coalesce-tag, 1/coalesce-backspace
1636 break-unless coalesce?
1637 deletion <- put deletion, delete-from:offset, before-cursor
1638 backspaced-so-far:&:duplex-list:char <- get deletion, deleted-text:offset
1639 insert-range backspaced-cell, backspaced-so-far
1640 deletion <- put deletion, deleted-text:offset, backspaced-cell
1641 deletion <- put deletion, after-row:offset, cursor-row
1642 deletion <- put deletion, after-column:offset, cursor-column
1643 deletion <- put deletion, after-top-of-screen:offset, top-after
1644 *op <- merge 2/delete-operation, deletion
1645 break +done-adding-backspace-operation
1646 }
1647
1648 op:&:operation <- new operation:type
1649 deleted-until:&:duplex-list:char <- next before-cursor
1650 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, backspaced-cell/deleted, before-cursor/delete-from, deleted-until, 1/coalesce-backspace
1651 editor <- add-operation editor, op
1652 +done-adding-backspace-operation
1653 }
1654 ]
1655
1656 after <handle-undo> [
1657 {
1658 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant
1659 break-unless is-delete?
1660 anchor:&:duplex-list:char <- get deletion, delete-from:offset
1661 break-unless anchor
1662 deleted:&:duplex-list:char <- get deletion, deleted-text:offset
1663 old-cursor:&:duplex-list:char <- last deleted
1664 insert-range anchor, deleted
1665
1666 before-cursor <- copy old-cursor
1667 cursor-row <- get deletion, before-row:offset
1668 *editor <- put *editor, cursor-row:offset, cursor-row
1669 cursor-column <- get deletion, before-column:offset
1670 *editor <- put *editor, cursor-column:offset, cursor-column
1671 top:&:duplex-list:char <- get deletion, before-top-of-screen:offset
1672 *editor <- put *editor, top-of-screen:offset, top
1673 }
1674 ]
1675
1676 after <handle-redo> [
1677 {
1678 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant
1679 break-unless is-delete?
1680 start:&:duplex-list:char <- get deletion, delete-from:offset
1681 end:&:duplex-list:char <- get deletion, delete-until:offset
1682 data:&:duplex-list:char <- get *editor, data:offset
1683 remove-between start, end
1684
1685 cursor-row <- get deletion, after-row:offset
1686 *editor <- put *editor, cursor-row:offset, cursor-row
1687 cursor-column <- get deletion, after-column:offset
1688 *editor <- put *editor, cursor-column:offset, cursor-column
1689 top:&:duplex-list:char <- get deletion, before-top-of-screen:offset
1690 *editor <- put *editor, top-of-screen:offset, top
1691 }
1692 ]
1693
1694
1695
1696 scenario editor-can-undo-and-redo-delete [
1697 local-scope
1698
1699 assume-screen 10/width, 5/height
1700 e:&:editor <- new-editor [], 0/left, 10/right
1701 editor-render screen, e
1702
1703 assume-console [
1704 type [abcdef]
1705 left-click 1, 2
1706 press delete
1707 press backspace
1708 press delete
1709 press delete
1710 ]
1711 editor-event-loop screen, console, e
1712 screen-should-contain [
1713 . .
1714 .af .
1715 .╌╌╌╌╌╌╌╌╌╌.
1716 . .
1717 ]
1718 3:num/raw <- get *e, cursor-row:offset
1719 4:num/raw <- get *e, cursor-column:offset
1720 memory-should-contain [
1721 3 <- 1
1722 4 <- 1
1723 ]
1724
1725 assume-console [
1726 press ctrl-z
1727 ]
1728 run [
1729 editor-event-loop screen, console, e
1730 ]
1731 3:num/raw <- get *e, cursor-row:offset
1732 4:num/raw <- get *e, cursor-column:offset
1733 memory-should-contain [
1734 3 <- 1
1735 4 <- 1
1736 ]
1737 screen-should-contain [
1738 . .
1739 .adef .
1740 .╌╌╌╌╌╌╌╌╌╌.
1741 . .
1742 ]
1743
1744 assume-console [
1745 press ctrl-z
1746 ]
1747 run [
1748 editor-event-loop screen, console, e
1749 ]
1750 3:num/raw <- get *e, cursor-row:offset
1751 4:num/raw <- get *e, cursor-column:offset
1752 memory-should-contain [
1753 3 <- 1
1754 4 <- 2
1755 ]
1756 screen-should-contain [
1757 . .
1758 .abdef .
1759 .╌╌╌╌╌╌╌╌╌╌.
1760 . .
1761 ]
1762
1763 assume-console [
1764 press ctrl-z
1765 ]
1766 run [
1767 editor-event-loop screen, console, e
1768 ]
1769 3:num/raw <- get *e, cursor-row:offset
1770 4:num/raw <- get *e, cursor-column:offset
1771 memory-should-contain [
1772 3 <- 1
1773 4 <- 2
1774 ]
1775 screen-should-contain [
1776 . .
1777 .abcdef .
1778 .╌╌╌╌╌╌╌╌╌╌.
1779 . .
1780 ]
1781
1782 assume-console [
1783 press ctrl-y
1784 ]
1785 run [
1786 editor-event-loop screen, console, e
1787 ]
1788
1789 3:num/raw <- get *e, cursor-row:offset
1790 4:num/raw <- get *e, cursor-column:offset
1791 memory-should-contain [
1792 3 <- 1
1793 4 <- 2
1794 ]
1795 screen-should-contain [
1796 . .
1797 .abdef .
1798 .╌╌╌╌╌╌╌╌╌╌.
1799 . .
1800 ]
1801
1802 assume-console [
1803 press ctrl-y
1804 ]
1805 run [
1806 editor-event-loop screen, console, e
1807 ]
1808
1809 3:num/raw <- get *e, cursor-row:offset
1810 4:num/raw <- get *e, cursor-column:offset
1811 memory-should-contain [
1812 3 <- 1
1813 4 <- 1
1814 ]
1815 screen-should-contain [
1816 . .
1817 .adef .
1818 .╌╌╌╌╌╌╌╌╌╌.
1819 . .
1820 ]
1821
1822 assume-console [
1823 press ctrl-y
1824 ]
1825 run [
1826 editor-event-loop screen, console, e
1827 ]
1828
1829 3:num/raw <- get *e, cursor-row:offset
1830 4:num/raw <- get *e, cursor-column:offset
1831 memory-should-contain [
1832 3 <- 1
1833 4 <- 1
1834 ]
1835 screen-should-contain [
1836 . .
1837 .af .
1838 .╌╌╌╌╌╌╌╌╌╌.
1839 . .
1840 ]
1841 ]
1842
1843 after <delete-character-begin> [
1844 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
1845 ]
1846 before <delete-character-end> [
1847 {
1848 break-unless deleted-cell
1849 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
1850 cursor-row:num <- get *editor, cursor-row:offset
1851 cursor-column:num <- get *editor, cursor-column:offset
1852 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
1853 undo:&:list:&:operation <- get *editor, undo:offset
1854 {
1855
1856 break-unless undo
1857 op:&:operation <- first undo
1858 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant
1859 break-unless is-delete?
1860 previous-coalesce-tag:num <- get deletion, tag:offset
1861 coalesce?:bool <- equal previous-coalesce-tag, 2/coalesce-delete
1862 break-unless coalesce?
1863 delete-until:&:duplex-list:char <- next before-cursor
1864 deletion <- put deletion, delete-until:offset, delete-until
1865 deleted-so-far:&:duplex-list:char <- get deletion, deleted-text:offset
1866 deleted-so-far <- append deleted-so-far, deleted-cell
1867 deletion <- put deletion, deleted-text:offset, deleted-so-far
1868 deletion <- put deletion, after-row:offset, cursor-row
1869 deletion <- put deletion, after-column:offset, cursor-column
1870 deletion <- put deletion, after-top-of-screen:offset, top-after
1871 *op <- merge 2/delete-operation, deletion
1872 break +done-adding-delete-operation
1873 }
1874
1875 op:&:operation <- new operation:type
1876 deleted-until:&:duplex-list:char <- next before-cursor
1877 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cell/deleted, before-cursor/delete-from, deleted-until, 2/coalesce-delete
1878 editor <- add-operation editor, op
1879 +done-adding-delete-operation
1880 }
1881 ]
1882
1883
1884
1885 scenario editor-can-undo-and-redo-ctrl-k [
1886 local-scope
1887
1888 assume-screen 10/width, 5/height
1889 contents:text <- new [abc
1890 def]
1891 e:&:editor <- new-editor contents, 0/left, 10/right
1892 editor-render screen, e
1893
1894 assume-console [
1895 left-click 1, 1
1896 press ctrl-k
1897 ]
1898 editor-event-loop screen, console, e
1899 screen-should-contain [
1900 . .
1901 .a .
1902 .def .
1903 .╌╌╌╌╌╌╌╌╌╌.
1904 . .
1905 ]
1906 3:num/raw <- get *e, cursor-row:offset
1907 4:num/raw <- get *e, cursor-column:offset
1908 memory-should-contain [
1909 3 <- 1
1910 4 <- 1
1911 ]
1912
1913 assume-console [
1914 press ctrl-z
1915 ]
1916 run [
1917 editor-event-loop screen, console, e
1918 ]
1919 screen-should-contain [
1920 . .
1921 .abc .
1922 .def .
1923 .╌╌╌╌╌╌╌╌╌╌.
1924 . .
1925 ]
1926 3:num/raw <- get *e, cursor-row:offset
1927 4:num/raw <- get *e, cursor-column:offset
1928 memory-should-contain [
1929 3 <- 1
1930 4 <- 1
1931 ]
1932
1933 assume-console [
1934 press ctrl-y
1935 ]
1936 run [
1937 editor-event-loop screen, console, e
1938 ]
1939
1940 screen-should-contain [
1941 . .
1942 .a .
1943 .def .
1944 .╌╌╌╌╌╌╌╌╌╌.
1945 . .
1946 ]
1947 3:num/raw <- get *e, cursor-row:offset
1948 4:num/raw <- get *e, cursor-column:offset
1949 memory-should-contain [
1950 3 <- 1
1951 4 <- 1
1952 ]
1953
1954 assume-console [
1955 type [1]
1956 ]
1957 run [
1958 editor-event-loop screen, console, e
1959 ]
1960 screen-should-contain [
1961 . .
1962 .a1 .
1963 .def .
1964 .╌╌╌╌╌╌╌╌╌╌.
1965 . .
1966 ]
1967 ]
1968
1969 after <delete-to-end-of-line-begin> [
1970 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
1971 ]
1972 before <delete-to-end-of-line-end> [
1973 {
1974 break-unless deleted-cells
1975 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
1976 cursor-row:num <- get *editor, cursor-row:offset
1977 cursor-column:num <- get *editor, cursor-column:offset
1978 deleted-until:&:duplex-list:char <- next before-cursor
1979 op:&:operation <- new operation:type
1980 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce
1981 editor <- add-operation editor, op
1982 +done-adding-delete-operation
1983 }
1984 ]
1985
1986
1987
1988 scenario editor-can-undo-and-redo-ctrl-u [
1989 local-scope
1990
1991 assume-screen 10/width, 5/height
1992 contents:text <- new [abc
1993 def]
1994 e:&:editor <- new-editor contents, 0/left, 10/right
1995 editor-render screen, e
1996
1997 assume-console [
1998 left-click 1, 2
1999 press ctrl-u
2000 ]
2001 editor-event-loop screen, console, e
2002 screen-should-contain [
2003 . .
2004 .c .
2005 .def .
2006 .╌╌╌╌╌╌╌╌╌╌.
2007 . .
2008 ]
2009 3:num/raw <- get *e, cursor-row:offset
2010 4:num/raw <- get *e, cursor-column:offset
2011 memory-should-contain [
2012 3 <- 1
2013 4 <- 0
2014 ]
2015
2016 assume-console [
2017 press ctrl-z
2018 ]
2019 run [
2020 editor-event-loop screen, console, e
2021 ]
2022 screen-should-contain [
2023 . .
2024 .abc .
2025 .def .
2026 .╌╌╌╌╌╌╌╌╌╌.
2027 . .
2028 ]
2029 3:num/raw <- get *e, cursor-row:offset
2030 4:num/raw <- get *e, cursor-column:offset
2031 memory-should-contain [
2032 3 <- 1
2033 4 <- 2
2034 ]
2035
2036 assume-console [
2037 press ctrl-y
2038 ]
2039 run [
2040 editor-event-loop screen, console, e
2041 ]
2042
2043 screen-should-contain [
2044 . .
2045 .c .
2046 .def .
2047 .╌╌╌╌╌╌╌╌╌╌.
2048 . .
2049 ]
2050 3:num/raw <- get *e, cursor-row:offset
2051 4:num/raw <- get *e, cursor-column:offset
2052 memory-should-contain [
2053 3 <- 1
2054 4 <- 0
2055 ]
2056
2057 assume-console [
2058 type [1]
2059 ]
2060 run [
2061 editor-event-loop screen, console, e
2062 ]
2063 screen-should-contain [
2064 . .
2065 .1c .
2066 .def .
2067 .╌╌╌╌╌╌╌╌╌╌.
2068 . .
2069 ]
2070 ]
2071
2072 after <delete-to-start-of-line-begin> [
2073 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset
2074 ]
2075 before <delete-to-start-of-line-end> [
2076 {
2077 break-unless deleted-cells
2078 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset
2079 op:&:operation <- new operation:type
2080 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
2081 deleted-until:&:duplex-list:char <- next before-cursor
2082 cursor-row:num <- get *editor, cursor-row:offset
2083 cursor-column:num <- get *editor, cursor-column:offset
2084 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce
2085 editor <- add-operation editor, op
2086 +done-adding-delete-operation
2087 }
2088 ]
2089
2090 scenario editor-can-undo-and-redo-ctrl-u-2 [
2091 local-scope
2092
2093 assume-screen 10/width, 5/height
2094 e:&:editor <- new-editor [], 0/left, 10/right
2095 editor-render screen, e
2096
2097 assume-console [
2098 type [abc]
2099 press ctrl-u
2100 press ctrl-z
2101 ]
2102 editor-event-loop screen, console, e
2103 screen-should-contain [
2104 . .
2105 .abc .
2106 .╌╌╌╌╌╌╌╌╌╌.
2107 . .
2108 ]
2109 ]