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