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 ]