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