1
2
3
4
5
6
7
8
9
10 def! main [
11 local-scope
12 open-console
13 clear-screen 0/screen
14 env:&:environment <- new-programming-environment 0/filesystem, 0/screen
15 env <- restore-sandboxes env, 0/filesystem
16 render-all 0/screen, env, render
17 event-loop 0/screen, 0/console, env, 0/filesystem
18 ]
19
20 container environment [
21 sandbox:&:sandbox
22 render-from:num
23 number-of-sandboxes:num
24 ]
25
26 after <programming-environment-initialization> [
27 *result <- put *result, render-from:offset, -1
28 ]
29
30 container sandbox [
31 data:text
32 response:text
33
34
35 starting-row-on-screen:num
36 code-ending-row-on-screen:num
37 screen:&:screen
38 next-sandbox:&:sandbox
39 ]
40
41 scenario run-and-show-results [
42 local-scope
43 trace-until 100/app
44 assume-screen 100/width, 15/height
45
46 assume-resources [
47 ]
48
49 env:&:environment <- new-programming-environment resources, screen, [divide-with-remainder 11, 3]
50 render-all screen, env, render
51
52 assume-console [
53 press F4
54 ]
55 run [
56 event-loop screen, console, env, resources
57 ]
58
59 screen-should-contain [
60 . run (F4) .
61 . ╎ .
62 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
63 . ╎0 edit copy to recipe delete .
64 . ╎divide-with-remainder 11, 3 .
65 . ╎3 .
66 . ╎2 .
67 . ╎─────────────────────────────────────────────────.
68 . ╎ .
69 ]
70 screen-should-contain-in-color 7/white, [
71 . .
72 . .
73 . .
74 . .
75 . divide-with-remainder 11, 3 .
76 . .
77 . .
78 . .
79 . .
80 ]
81 screen-should-contain-in-color 245/grey, [
82 . .
83 . ╎ .
84 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
85 . ╎ .
86 . ╎ .
87 . ╎3 .
88 . ╎2 .
89 . ╎─────────────────────────────────────────────────.
90 . ╎ .
91 ]
92
93 screen-should-contain-in-color 232/black, [
94 . .
95 . .
96 . .
97 . 0 edit copy to recipe delete .
98 ]
99
100 assume-console [
101 left-click 1, 80
102 type [add 2, 2]
103 press F4
104 ]
105 run [
106 event-loop screen, console, env, resources
107 ]
108
109 screen-should-contain [
110 . run (F4) .
111 . ╎ .
112 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
113 . ╎0 edit copy to recipe delete .
114 . ╎add 2, 2 .
115 . ╎4 .
116 . ╎─────────────────────────────────────────────────.
117 . ╎1 edit copy to recipe delete .
118 . ╎divide-with-remainder 11, 3 .
119 . ╎3 .
120 . ╎2 .
121 . ╎─────────────────────────────────────────────────.
122 . ╎ .
123 ]
124 ]
125
126 after <global-keypress> [
127
128 {
129 do-run?:bool <- equal k, 65532/F4
130 break-unless do-run?
131 screen <- update-status screen, [running... ], 245/grey
132 <begin-run-sandboxes-on-F4>
133 error?:bool <- run-sandboxes env, resources, screen
134
135 <end-run-sandboxes-on-F4>
136 screen <- render-sandbox-side screen, env, render
137 {
138 break-if error?
139 screen <- update-status screen, [ ], 245/grey
140 }
141 screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
142 loop +next-event
143 }
144 ]
145
146 def run-sandboxes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [
147 local-scope
148 load-inputs
149 errors-found?:bool <- update-recipes env, resources, screen
150 jump-if errors-found?, +return
151
152 <begin-run-sandboxes>
153 current-sandbox:&:editor <- get *env, current-sandbox:offset
154 {
155 sandbox-contents:text <- editor-contents current-sandbox
156 break-unless sandbox-contents
157
158
159 new-sandbox:&:sandbox <- new sandbox:type
160 *new-sandbox <- put *new-sandbox, data:offset, sandbox-contents
161
162 dest:&:sandbox <- get *env, sandbox:offset
163 *new-sandbox <- put *new-sandbox, next-sandbox:offset, dest
164 *env <- put *env, sandbox:offset, new-sandbox
165
166 sandbox-count:num <- get *env, number-of-sandboxes:offset
167 sandbox-count <- add sandbox-count, 1
168 *env <- put *env, number-of-sandboxes:offset, sandbox-count
169
170
171 save-sandboxes env, resources
172
173 init:&:duplex-list:char <- push 167/§, 0/tail
174 *current-sandbox <- put *current-sandbox, data:offset, init
175 *current-sandbox <- put *current-sandbox, top-of-screen:offset, init
176 }
177
178 curr:&:sandbox <- get *env, sandbox:offset
179 idx:num <- copy 0
180 {
181 break-unless curr
182 curr <- update-sandbox curr, env, idx
183 curr <- get *curr, next-sandbox:offset
184 idx <- add idx, 1
185 loop
186 }
187 <end-run-sandboxes>
188 +return
189 {
190 break-if resources
191 $system [./snapshot_lesson]
192 }
193 ]
194
195
196
197 def update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [
198 local-scope
199 load-inputs
200 recipes:&:editor <- get *env, recipes:offset
201 in:text <- editor-contents recipes
202 resources <- dump resources, [lesson/recipes.mu], in
203 reload in
204 errors-found? <- copy 0/false
205 ]
206
207
208 def update-sandbox sandbox:&:sandbox, env:&:environment, idx:num -> sandbox:&:sandbox, env:&:environment [
209 local-scope
210 load-inputs
211 data:text <- get *sandbox, data:offset
212 response:text, _, fake-screen:&:screen <- run-sandboxed data
213 *sandbox <- put *sandbox, response:offset, response
214 *sandbox <- put *sandbox, screen:offset, fake-screen
215 ]
216
217 def update-status screen:&:screen, msg:text, color:num -> screen:&:screen [
218 local-scope
219 load-inputs
220 screen <- move-cursor screen, 0, 2
221 screen <- print screen, msg, color, 238/grey/background
222 ]
223
224 def save-sandboxes env:&:environment, resources:&:resources -> resources:&:resources [
225 local-scope
226 load-inputs
227 trace 11, [app], [save sandboxes]
228 current-sandbox:&:editor <- get *env, current-sandbox:offset
229
230 $system [rm lesson/[0-9]* >/dev/null 2>/dev/null]
231 curr:&:sandbox <- get *env, sandbox:offset
232 idx:num <- copy 0
233 {
234 break-unless curr
235 resources <- save-sandbox resources, curr, idx
236 idx <- add idx, 1
237 curr <- get *curr, next-sandbox:offset
238 loop
239 }
240 ]
241
242 def save-sandbox resources:&:resources, sandbox:&:sandbox, sandbox-index:num -> resources:&:resources [
243 local-scope
244 load-inputs
245 data:text <- get *sandbox, data:offset
246 filename:text <- append [lesson/], sandbox-index
247 resources <- dump resources, filename, data
248 <end-save-sandbox>
249 ]
250
251 def! render-sandbox-side screen:&:screen, env:&:environment, render-editor:render-recipe -> screen:&:screen, env:&:environment [
252 local-scope
253 load-inputs
254 trace 11, [app], [render sandbox side]
255 old-top-idx:num <- save-top-idx screen
256 current-sandbox:&:editor <- get *env, current-sandbox:offset
257 row:num, column:num <- copy 1, 0
258 left:num <- get *current-sandbox, left:offset
259 right:num <- get *current-sandbox, right:offset
260
261 render-from:num <- get *env, render-from:offset
262 {
263 render-current-sandbox?:bool <- equal render-from, -1
264 break-unless render-current-sandbox?
265 row, column, screen, current-sandbox <- call render-editor, screen, current-sandbox
266 clear-screen-from screen, row, column, left, right
267 row <- add row, 1
268 }
269
270 draw-horizontal screen, row, left, right
271 sandbox:&:sandbox <- get *env, sandbox:offset
272 row, screen <- render-sandboxes screen, sandbox, left, right, row, render-from
273 clear-rest-of-screen screen, row, left, right
274
275 assert-no-scroll screen, old-top-idx
276 ]
277
278 def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, row:num, render-from:num, idx:num -> row:num, screen:&:screen, sandbox:&:sandbox [
279 local-scope
280 load-inputs
281 return-unless sandbox
282 screen-height:num <- screen-height screen
283 hidden?:bool <- lesser-than idx, render-from
284 {
285 break-if hidden?
286
287 row <- add row, 1
288 at-bottom?:bool <- greater-or-equal row, screen-height
289 return-if at-bottom?
290 screen <- move-cursor screen, row, left
291 screen <- render-sandbox-menu screen, idx, left, right
292
293 *sandbox <- put *sandbox, starting-row-on-screen:offset, row
294
295 row <- add row, 1
296 screen <- move-cursor screen, row, left
297 sandbox-data:text <- get *sandbox, data:offset
298 row, screen <- render-code screen, sandbox-data, left, right, row
299 *sandbox <- put *sandbox, code-ending-row-on-screen:offset, row
300
301 sandbox-response:text <- get *sandbox, response:offset
302 <render-sandbox-results>
303 {
304 sandbox-screen:&:screen <- get *sandbox, screen:offset
305 empty-screen?:bool <- fake-screen-is-empty? sandbox-screen
306 break-if empty-screen?
307 row, screen <- render-screen screen, sandbox-screen, left, right, row
308 }
309 {
310 break-unless empty-screen?
311 <render-sandbox-response>
312 row, screen <- render-text screen, sandbox-response, left, right, 245/grey, row
313 }
314 +render-sandbox-end
315 at-bottom?:bool <- greater-or-equal row, screen-height
316 return-if at-bottom?
317
318 draw-horizontal screen, row, left, right
319 }
320
321 {
322 break-unless hidden?
323 *sandbox <- put *sandbox, starting-row-on-screen:offset, 0
324 *sandbox <- put *sandbox, code-ending-row-on-screen:offset, 0
325 <end-render-sandbox-reset-hidden>
326 }
327
328 next-sandbox:&:sandbox <- get *sandbox, next-sandbox:offset
329 next-idx:num <- add idx, 1
330 row, screen <- render-sandboxes screen, next-sandbox, left, right, row, render-from, next-idx
331 ]
332
333 def render-sandbox-menu screen:&:screen, sandbox-index:num, left:num, right:num -> screen:&:screen [
334 local-scope
335 load-inputs
336 move-cursor-to-column screen, left
337 edit-button-left:num, edit-button-right:num, copy-button-left:num, copy-button-right:num, recipe-button-left:num, recipe-button-right:num, delete-button-left:num <- sandbox-menu-columns left, right
338 print screen, sandbox-index, 232/dark-grey, 245/grey
339 start-buttons:num <- subtract edit-button-left, 1
340 clear-line-until screen, start-buttons, 245/grey
341 print screen, [edit], 232/black, 25/background-blue
342 clear-line-until screen, edit-button-right, 25/background-blue
343 print screen, [copy], 232/black, 58/background-green
344 clear-line-until screen, copy-button-right, 58/background-green
345 print screen, [to recipe], 232/black, 94/background-orange
346 clear-line-until screen, recipe-button-right, 94/background-orange
347 print screen, [delete], 232/black, 52/background-red
348 clear-line-until screen, right, 52/background-red
349 ]
350
351 scenario skip-rendering-sandbox-menu-past-bottom-row [
352 trace-until 100/app
353 assume-screen 100/width, 6/height
354
355 assume-resources [
356 [lesson/0] <- [|add 2, 2|]
357 [lesson/1] <- [|add 1, 1|]
358 ]
359
360 env:&:environment <- new-programming-environment resources, screen, []
361 env <- restore-sandboxes env, resources
362 run [
363 render-all screen, env, render
364 ]
365 screen-should-contain [
366 . run (F4) .
367 . ╎ .
368 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
369 . ╎0 edit copy to recipe delete .
370 . ╎add 2, 2 .
371 . ╎─────────────────────────────────────────────────.
372 ]
373 ]
374
375
376
377
378 def sandbox-menu-columns left:num, right:num -> edit-button-left:num, edit-button-right:num, copy-button-left:num, copy-button-right:num, recipe-button-left:num, recipe-button-right:num, delete-button-left:num [
379 local-scope
380 load-inputs
381 start-buttons:num <- add left, 4/space-for-sandbox-index
382 buttons-space:num <- subtract right, start-buttons
383 button-width:num <- divide-with-remainder buttons-space, 4
384 buttons-wide-enough?:bool <- greater-or-equal button-width, 10
385 assert buttons-wide-enough?, [sandbox must be at least 40 or so characters wide]
386 edit-button-left:num <- copy start-buttons
387 copy-button-left:num <- add start-buttons, button-width
388 edit-button-right:num <- subtract copy-button-left, 1
389 recipe-button-left:num <- add copy-button-left, button-width
390 copy-button-right:num <- subtract recipe-button-left, 1
391 delete-button-left:num <- subtract right, button-width, -2
392 recipe-button-right:num <- subtract delete-button-left, 1
393 ]
394
395
396
397
398 def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num -> row:num, screen:&:screen [
399 local-scope
400 load-inputs
401 return-unless s
402 column:num <- copy left
403 screen <- move-cursor screen, row, column
404 screen-height:num <- screen-height screen
405 i:num <- copy 0
406 len:num <- length *s
407 {
408 +next-character
409 done?:bool <- greater-or-equal i, len
410 break-if done?
411 done? <- greater-or-equal row, screen-height
412 break-if done?
413 c:char <- index *s, i
414 {
415
416 newline?:bool <- equal c, 10/newline
417 break-unless newline?
418
419 {
420 done?:bool <- greater-than column, right
421 break-if done?
422 space:char <- copy 32/space
423 print screen, space
424 column <- add column, 1
425 loop
426 }
427 row <- add row, 1
428 column <- copy left
429 screen <- move-cursor screen, row, column
430 i <- add i, 1
431 loop +next-character
432 }
433 {
434
435 at-right?:bool <- equal column, right
436 break-unless at-right?
437
438 wrap-icon:char <- copy 8617/loop-back-to-left
439 print screen, wrap-icon, 245/grey
440 column <- copy left
441 row <- add row, 1
442 screen <- move-cursor screen, row, column
443
444 loop +next-character
445 }
446 i <- add i, 1
447 print screen, c, color
448 column <- add column, 1
449 loop
450 }
451 was-at-left?:bool <- equal column, left
452 clear-line-until screen, right
453 {
454 break-if was-at-left?
455 row <- add row, 1
456 }
457 move-cursor screen, row, left
458 ]
459
460 scenario render-text-wraps-barely-long-lines [
461 local-scope
462 assume-screen 5/width, 5/height
463 run [
464 render-text screen, [abcde], 0/left, 4/right, 7/white, 1/row
465 ]
466 screen-should-contain [
467 . .
468 .abcd↩.
469 .e .
470 . .
471 ]
472 ]
473
474
475 def restore-sandboxes env:&:environment, resources:&:resources -> env:&:environment [
476 local-scope
477 load-inputs
478
479 idx:num <- copy 0
480 curr:&:sandbox <- copy 0
481 prev:&:sandbox <- copy 0
482 {
483 filename:text <- append [lesson/], idx
484 contents:text <- slurp resources, filename
485 break-unless contents
486
487
488 curr <- new sandbox:type
489 *curr <- put *curr, data:offset, contents
490 <end-restore-sandbox>
491 {
492 break-if idx
493 *env <- put *env, sandbox:offset, curr
494 }
495 {
496 break-unless idx
497 *prev <- put *prev, next-sandbox:offset, curr
498 }
499 idx <- add idx, 1
500 prev <- copy curr
501 loop
502 }
503
504 *env <- put *env, number-of-sandboxes:offset, idx
505 ]
506
507
508
509 def render-screen screen:&:screen, sandbox-screen:&:screen, left:num, right:num, row:num -> row:num, screen:&:screen [
510 local-scope
511 load-inputs
512 return-unless sandbox-screen
513
514 row <- render-text screen, [screen:], left, right, 245/grey, row
515 screen <- move-cursor screen, row, left
516
517 column:num <- copy left
518 s-width:num <- screen-width sandbox-screen
519 s-height:num <- screen-height sandbox-screen
520 buf:&:@:screen-cell <- get *sandbox-screen, data:offset
521 stop-printing:num <- add left, s-width, 3
522 max-column:num <- min stop-printing, right
523 i:num <- copy 0
524 len:num <- length *buf
525 screen-height:num <- screen-height screen
526 {
527 done?:bool <- greater-or-equal i, len
528 break-if done?
529 done? <- greater-or-equal row, screen-height
530 break-if done?
531 column <- copy left
532 screen <- move-cursor screen, row, column
533
534 space:char <- copy 32/space
535 print screen, space, 245/grey
536 print screen, space, 245/grey
537 full-stop:char <- copy 46/period
538 print screen, full-stop, 245/grey
539 column <- add left, 3
540 {
541
542 row-done?:bool <- greater-or-equal column, max-column
543 break-if row-done?
544 curr:screen-cell <- index *buf, i
545 c:char <- get curr, contents:offset
546 color:num <- get curr, color:offset
547 {
548
549 white?:bool <- equal color, 7/white
550 break-unless white?
551 color <- copy 245/grey
552 }
553 print screen, c, color
554 column <- add column, 1
555 i <- add i, 1
556 loop
557 }
558
559 print screen, full-stop, 245/grey
560 column <- add column, 1
561 {
562
563 line-done?:bool <- greater-than column, right
564 break-if line-done?
565 print screen, space
566 column <- add column, 1
567 loop
568 }
569 row <- add row, 1
570 loop
571 }
572 ]
573
574 scenario run-updates-results [
575 local-scope
576 trace-until 100/app
577 assume-screen 100/width, 12/height
578
579 assume-resources [
580 [lesson/recipes.mu] <- [
581 ||
582 |recipe foo [|
583 | local-scope|
584 | z:num <- add 2, 2|
585 | reply z|
586 |]|
587 ]
588 ]
589
590 env:&:environment <- new-programming-environment resources, screen, [foo]
591 render-all screen, env, render
592 $clear-trace
593
594 assume-console [
595 press F4
596 ]
597 event-loop screen, console, env, resources
598 screen-should-contain [
599 . run (F4) .
600 . ╎ .
601 .recipe foo [ ╎─────────────────────────────────────────────────.
602 . local-scope ╎0 edit copy to recipe delete .
603 . z:num <- add 2, 2 ╎foo .
604 . reply z ╎4 .
605 .] ╎─────────────────────────────────────────────────.
606 . ╎ .
607 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
608 . ╎ .
609 ]
610
611 trace-should-contain [
612 app: save sandboxes
613 ]
614
615 trace-should-not-contain [
616 app: render recipes
617 ]
618
619 $clear-trace
620 assume-console [
621 left-click 4, 28
622 press backspace
623 type [3]
624 press F4
625 ]
626 run [
627 event-loop screen, console, env, resources
628 ]
629
630 screen-should-contain [
631 . run (F4) .
632 . ╎ .
633 .recipe foo [ ╎─────────────────────────────────────────────────.
634 . local-scope ╎0 edit copy to recipe delete .
635 . z:num <- add 2, 3 ╎foo .
636 . reply z ╎5 .
637 .] ╎─────────────────────────────────────────────────.
638 . ╎ .
639 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
640 . ╎ .
641 ]
642
643 trace-should-not-contain [
644 app: save sandboxes
645 ]
646 ]
647
648 scenario run-instruction-manages-screen-per-sandbox [
649 local-scope
650 trace-until 100/app
651 assume-screen 100/width, 20/height
652
653 assume-resources [
654 ]
655
656 env:&:environment <- new-programming-environment resources, screen, [print screen, 4]
657 render-all screen, env, render
658
659 assume-console [
660 press F4
661 ]
662 run [
663 event-loop screen, console, env, resources
664 ]
665
666 screen-should-contain [
667 . run (F4) .
668 . ╎ .
669 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
670 . ╎0 edit copy to recipe delete .
671 . ╎print screen, 4 .
672 . ╎screen: .
673 . ╎ .4 . .
674 . ╎ . . .
675 . ╎ . . .
676 . ╎ . . .
677 . ╎ . . .
678 . ╎─────────────────────────────────────────────────.
679 . ╎ .
680 ]
681 ]
682
683 def editor-contents editor:&:editor -> result:text [
684 local-scope
685 load-inputs
686 buf:&:buffer:char <- new-buffer 80
687 curr:&:duplex-list:char <- get *editor, data:offset
688
689 assert curr, [editor without data is illegal; must have at least a sentinel]
690 curr <- next curr
691 return-unless curr, 0
692 {
693 break-unless curr
694 c:char <- get *curr, value:offset
695 buf <- append buf, c
696 curr <- next curr
697 loop
698 }
699 result <- buffer-to-array buf
700 ]
701
702 scenario editor-provides-edited-contents [
703 local-scope
704 assume-screen 10/width, 5/height
705 e:&:editor <- new-editor [abc], 0/left, 10/right
706 assume-console [
707 left-click 1, 2
708 type [def]
709 ]
710 run [
711 editor-event-loop screen, console, e
712 s:text <- editor-contents e
713 1:@:char/raw <- copy *s
714 ]
715 memory-should-contain [
716 1:array:character <- [abdefc]
717 ]
718 ]
719
720
721
722 scenario scrolling-down-past-bottom-of-recipe-editor [
723 local-scope
724 trace-until 100/app
725 assume-screen 100/width, 10/height
726 assume-resources [
727 ]
728 env:&:environment <- new-programming-environment resources, screen, []
729 render-all screen, env, render
730 assume-console [
731 press enter
732 press down-arrow
733 ]
734 event-loop screen, console, env, resources
735
736 screen-should-contain [
737 . run (F4) .
738 . ╎ .
739 . ╎─────────────────────────────────────────────────.
740 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
741 . ╎ .
742 ]
743 ]
744
745 scenario cursor-down-in-recipe-editor [
746 local-scope
747 trace-until 100/app
748 assume-screen 100/width, 10/height
749 assume-resources [
750 ]
751 env:&:environment <- new-programming-environment resources, screen, []
752 render-all screen, env, render
753 assume-console [
754 press enter
755 press up-arrow
756 press down-arrow
757 ]
758 event-loop screen, console, env, resources
759 cursor:char <- copy 9251/␣
760 print screen, cursor
761
762 screen-should-contain [
763 . run (F4) .
764 . ╎ .
765 .␣ ╎─────────────────────────────────────────────────.
766 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
767 . ╎ .
768 ]
769 ]
770
771 scenario scrolling-down-past-bottom-of-recipe-editor-2 [
772 local-scope
773 trace-until 100/app
774 assume-screen 100/width, 10/height
775 assume-resources [
776 ]
777 env:&:environment <- new-programming-environment resources, screen, []
778 render-all screen, env, render
779 assume-console [
780
781 press enter
782
783 press up-arrow
784
785 press page-down
786 ]
787 event-loop screen, console, env, resources
788
789 screen-should-contain [
790 . run (F4) .
791 . ╎ .
792 . ╎─────────────────────────────────────────────────.
793 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
794 . ╎ .
795 ]
796 ]
797
798 scenario scrolling-down-past-bottom-of-recipe-editor-3 [
799 local-scope
800 trace-until 100/app
801 assume-screen 100/width, 10/height
802 assume-resources [
803 ]
804 env:&:environment <- new-programming-environment resources, screen, [ab
805 cd]
806 render-all screen, env, render
807 assume-console [
808
809 press enter
810
811 press ctrl-n
812
813 press down-arrow
814 ]
815 event-loop screen, console, env, resources
816 cursor:char <- copy 9251/␣
817 print screen, cursor
818
819 screen-should-contain [
820 . run (F4) .
821 . ╎ab .
822 . ╎␣d .
823 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
824 . ╎ .
825 ]
826 ]
827
828
829
830 scenario scrolling-down-past-bottom-of-sandbox-editor [
831 local-scope
832 trace-until 100/app
833 assume-screen 100/width, 10/height
834
835 assume-resources [
836 ]
837 env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
838 render-all screen, env, render
839 assume-console [
840
841 press F4
842 ]
843 event-loop screen, console, env, resources
844 screen-should-contain [
845 . run (F4) .
846 . ╎ .
847 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
848 . ╎0 edit copy to recipe delete .
849 . ╎add 2, 2 .
850 ]
851
852 assume-console [
853 press ctrl-n
854 press page-down
855 ]
856 run [
857 event-loop screen, console, env, resources
858 cursor:char <- copy 9251/␣
859 print screen, cursor
860 ]
861
862
863 screen-should-contain [
864 . run (F4) .
865 . ╎─────────────────────────────────────────────────.
866 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy to recipe delete .
867 . ╎add 2, 2 .
868 . ╎4 .
869 ]
870
871 assume-console [
872 press page-up
873 ]
874 run [
875 event-loop screen, console, env, resources
876 cursor:char <- copy 9251/␣
877 print screen, cursor
878 ]
879
880 screen-should-contain [
881 . run (F4) .
882 . ╎␣ .
883 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
884 . ╎0 edit copy to recipe delete .
885 . ╎add 2, 2 .
886 ]
887 ]
888
889
890 after <global-keypress> [
891 {
892 break-unless sandbox-in-focus?
893 page-down?:bool <- equal k, 65518/page-down
894 break-unless page-down?
895 sandbox:&:sandbox <- get *env, sandbox:offset
896 break-unless sandbox
897
898 {
899 render-from:num <- get *env, render-from:offset
900 number-of-sandboxes:num <- get *env, number-of-sandboxes:offset
901 max:num <- subtract number-of-sandboxes, 1
902 at-end?:bool <- greater-or-equal render-from, max
903 loop-if at-end?, +next-event
904 render-from <- add render-from, 1
905 *env <- put *env, render-from:offset, render-from
906 }
907 screen <- render-sandbox-side screen, env, render
908 screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
909 loop +next-event
910 }
911 ]
912
913
914 after <update-cursor-special-cases> [
915 {
916 break-unless sandbox-in-focus?
917 render-from:num <- get *env, render-from:offset
918 scrolling?:bool <- greater-or-equal render-from, 0
919 break-unless scrolling?
920 cursor-column:num <- get *current-sandbox, left:offset
921 screen <- move-cursor screen, 2/row, cursor-column
922 return
923 }
924 ]
925
926
927 after <global-keypress> [
928 {
929 break-unless sandbox-in-focus?
930 page-up?:bool <- equal k, 65519/page-up
931 break-unless page-up?
932 render-from:num <- get *env, render-from:offset
933 at-beginning?:bool <- equal render-from, -1
934 break-if at-beginning?
935 render-from <- subtract render-from, 1
936 *env <- put *env, render-from:offset, render-from
937 screen <- render-sandbox-side screen, env, render
938 screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
939 loop +next-event
940 }
941 ]
942
943
944
945 def previous-sandbox env:&:environment, in:&:sandbox -> out:&:sandbox [
946 local-scope
947 load-inputs
948 curr:&:sandbox <- get *env, sandbox:offset
949 return-unless curr, 0/nil
950 next:&:sandbox <- get *curr, next-sandbox:offset
951 {
952 return-unless next, 0/nil
953 found?:bool <- equal next, in
954 break-if found?
955 curr <- copy next
956 next <- get *curr, next-sandbox:offset
957 loop
958 }
959 return curr
960 ]
961
962 scenario scrolling-through-multiple-sandboxes [
963 local-scope
964 trace-until 100/app
965 assume-screen 100/width, 10/height
966
967 assume-resources [
968 ]
969 env:&:environment <- new-programming-environment resources, screen, []
970 render-all screen, env, render
971
972 assume-console [
973 press ctrl-n
974 type [add 2, 2]
975 press F4
976 type [add 1, 1]
977 press F4
978 ]
979 event-loop screen, console, env, resources
980 cursor:char <- copy 9251/␣
981 print screen, cursor
982 screen-should-contain [
983 . run (F4) .
984 . ╎␣ .
985 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
986 . ╎0 edit copy to recipe delete .
987 . ╎add 1, 1 .
988 . ╎2 .
989 . ╎─────────────────────────────────────────────────.
990 . ╎1 edit copy to recipe delete .
991 . ╎add 2, 2 .
992 . ╎4 .
993 ]
994
995 assume-console [
996 press page-down
997 ]
998 run [
999 event-loop screen, console, env, resources
1000 cursor:char <- copy 9251/␣
1001 print screen, cursor
1002 ]
1003
1004
1005 screen-should-contain [
1006 . run (F4) .
1007 . ╎─────────────────────────────────────────────────.
1008 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy to recipe delete .
1009 . ╎add 1, 1 .
1010 . ╎2 .
1011 . ╎─────────────────────────────────────────────────.
1012 . ╎1 edit copy to recipe delete .
1013 . ╎add 2, 2 .
1014 . ╎4 .
1015 ]
1016
1017 assume-console [
1018 press page-down
1019 ]
1020 run [
1021 event-loop screen, console, env, resources
1022 ]
1023
1024 screen-should-contain [
1025 . run (F4) .
1026 . ╎─────────────────────────────────────────────────.
1027 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy to recipe delete .
1028 . ╎add 2, 2 .
1029 . ╎4 .
1030 . ╎─────────────────────────────────────────────────.
1031 . ╎ .
1032 ]
1033
1034 assume-console [
1035 press page-down
1036 ]
1037 run [
1038 event-loop screen, console, env, resources
1039 ]
1040
1041 screen-should-contain [
1042 . run (F4) .
1043 . ╎─────────────────────────────────────────────────.
1044 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy to recipe delete .
1045 . ╎add 2, 2 .
1046 . ╎4 .
1047 . ╎─────────────────────────────────────────────────.
1048 . ╎ .
1049 ]
1050
1051 assume-console [
1052 press page-up
1053 ]
1054 run [
1055 event-loop screen, console, env, resources
1056 ]
1057
1058 screen-should-contain [
1059 . run (F4) .
1060 . ╎─────────────────────────────────────────────────.
1061 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1062 . ╎add 1, 1 .
1063 . ╎2 .
1064 . ╎─────────────────────────────────────────────────.
1065 . ╎1 edit copy to recipe delete .
1066 . ╎add 2, 2 .
1067 . ╎4 .
1068 ]
1069
1070 assume-console [
1071 press page-up
1072 ]
1073 run [
1074 event-loop screen, console, env, resources
1075 cursor:char <- copy 9251/␣
1076 print screen, cursor
1077 ]
1078
1079 screen-should-contain [
1080 . run (F4) .
1081 . ╎␣ .
1082 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1083 . ╎0 edit copy to recipe delete .
1084 . ╎add 1, 1 .
1085 . ╎2 .
1086 . ╎─────────────────────────────────────────────────.
1087 . ╎1 edit copy to recipe delete .
1088 . ╎add 2, 2 .
1089 . ╎4 .
1090 ]
1091
1092 assume-console [
1093 press page-up
1094 ]
1095 run [
1096 event-loop screen, console, env, resources
1097 cursor:char <- copy 9251/␣
1098 print screen, cursor
1099 ]
1100
1101 screen-should-contain [
1102 . run (F4) .
1103 . ╎␣ .
1104 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1105 . ╎0 edit copy to recipe delete .
1106 . ╎add 1, 1 .
1107 . ╎2 .
1108 . ╎─────────────────────────────────────────────────.
1109 . ╎1 edit copy to recipe delete .
1110 . ╎add 2, 2 .
1111 . ╎4 .
1112 ]
1113 ]
1114
1115 scenario scrolling-manages-sandbox-index-correctly [
1116 local-scope
1117 trace-until 100/app
1118 assume-screen 100/width, 10/height
1119
1120 assume-resources [
1121 ]
1122 env:&:environment <- new-programming-environment resources, screen, []
1123 render-all screen, env, render
1124
1125 assume-console [
1126 press ctrl-n
1127 type [add 1, 1]
1128 press F4
1129 ]
1130 event-loop screen, console, env, resources
1131 screen-should-contain [
1132 . run (F4) .
1133 . ╎ .
1134 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1135 . ╎0 edit copy to recipe delete .
1136 . ╎add 1, 1 .
1137 . ╎2 .
1138 . ╎─────────────────────────────────────────────────.
1139 . ╎ .
1140 ]
1141
1142 assume-console [
1143 press page-down
1144 ]
1145 run [
1146 event-loop screen, console, env, resources
1147 ]
1148
1149
1150 screen-should-contain [
1151 . run (F4) .
1152 . ╎─────────────────────────────────────────────────.
1153 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1154 . ╎add 1, 1 .
1155 . ╎2 .
1156 . ╎─────────────────────────────────────────────────.
1157 . ╎ .
1158 ]
1159
1160 assume-console [
1161 press page-up
1162 ]
1163 run [
1164 event-loop screen, console, env, resources
1165 ]
1166
1167 screen-should-contain [
1168 . run (F4) .
1169 . ╎ .
1170 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1171 . ╎0 edit copy to recipe delete .
1172 . ╎add 1, 1 .
1173 . ╎2 .
1174 . ╎─────────────────────────────────────────────────.
1175 . ╎ .
1176 ]
1177
1178 assume-console [
1179 press page-down
1180 ]
1181 run [
1182 event-loop screen, console, env, resources
1183 ]
1184
1185
1186 screen-should-contain [
1187 . run (F4) .
1188 . ╎─────────────────────────────────────────────────.
1189 .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1190 . ╎add 1, 1 .
1191 . ╎2 .
1192 . ╎─────────────────────────────────────────────────.
1193 . ╎ .
1194 ]
1195 ]