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