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