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:render-recipe -> 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 render-text-wraps-barely-long-lines [
429 local-scope
430 assume-screen 5/width, 5/height
431 run [
432 ¦ render-text screen, [abcde], 0/left, 4/right, 7/white, 1/row
433 ]
434 screen-should-contain [
435 ¦ . .
436 ¦ .abcd↩.
437 ¦ .e .
438 ¦ . .
439 ]
440 ]
441
442
443 def restore-sandboxes env:&:environment, resources:&:resources -> env:&:environment [
444 local-scope
445 load-ingredients
446
447 idx:num <- copy 0
448 curr:&:sandbox <- copy 0
449 prev:&:sandbox <- copy 0
450 {
451 ¦ filename:text <- append [lesson/], idx
452 ¦ contents:text <- slurp resources, filename
453 ¦ break-unless contents
454 ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦
455 ¦
456 ¦ curr <- new sandbox:type
457 ¦ *curr <- put *curr, data:offset, contents
458 ¦ <end-restore-sandbox>
459 ¦ {
460 ¦ ¦ break-if idx
461 ¦ ¦ *env <- put *env, sandbox:offset, curr
462 ¦ }
463 ¦ {
464 ¦ ¦ break-unless idx
465 ¦ ¦ *prev <- put *prev, next-sandbox:offset, curr
466 ¦ }
467 ¦ idx <- add idx, 1
468 ¦ prev <- copy curr
469 ¦ loop
470 }
471
472 *env <- put *env, number-of-sandboxes:offset, idx
473 ]
474
475
476
477 def render-screen screen:&:screen, sandbox-screen:&:screen, left:num, right:num, row:num -> row:num, screen:&:screen [
478 local-scope
479 load-ingredients
480 return-unless sandbox-screen
481
482 row <- render-text screen, [screen:], left, right, 245/grey, row
483 screen <- move-cursor screen, row, left
484
485 column:num <- copy left
486 s-width:num <- screen-width sandbox-screen
487 s-height:num <- screen-height sandbox-screen
488 buf:&:@:screen-cell <- get *sandbox-screen, data:offset
489 stop-printing:num <- add left, s-width, 3
490 max-column:num <- min stop-printing, right
491 i:num <- copy 0
492 len:num <- length *buf
493 screen-height:num <- screen-height screen
494 {
495 ¦ done?:bool <- greater-or-equal i, len
496 ¦ break-if done?
497 ¦ done? <- greater-or-equal row, screen-height
498 ¦ break-if done?
499 ¦ column <- copy left
500 ¦ screen <- move-cursor screen, row, column
501 ¦
502 ¦ space:char <- copy 32/space
503 ¦ print screen, space, 245/grey
504 ¦ print screen, space, 245/grey
505 ¦ full-stop:char <- copy 46/period
506 ¦ print screen, full-stop, 245/grey
507 ¦ column <- add left, 3
508 ¦ {
509 ¦ ¦
510 ¦ ¦ row-done?:bool <- greater-or-equal column, max-column
511 ¦ ¦ break-if row-done?
512 ¦ ¦ curr:screen-cell <- index *buf, i
513 ¦ ¦ c:char <- get curr, contents:offset
514 ¦ ¦ color:num <- get curr, color:offset
515 ¦ ¦ {
516 ¦ ¦ ¦
517 ¦ ¦ ¦ white?:bool <- equal color, 7/white
518 ¦ ¦ ¦ break-unless white?
519 ¦ ¦ ¦ color <- copy 245/grey
520 ¦ ¦ }
521 ¦ ¦ print screen, c, color
522 ¦ ¦ column <- add column, 1
523 ¦ ¦ i <- add i, 1
524 ¦ ¦ loop
525 ¦ }
526 ¦
527 ¦ print screen, full-stop, 245/grey
528 ¦ column <- add column, 1
529 ¦ {
530 ¦ ¦
531 ¦ ¦ line-done?:bool <- greater-than column, right
532 ¦ ¦ break-if line-done?
533 ¦ ¦ print screen, space
534 ¦ ¦ column <- add column, 1
535 ¦ ¦ loop
536 ¦ }
537 ¦ row <- add row, 1
538 ¦ loop
539 }
540 ]
541
542 scenario run-updates-results [
543 local-scope
544 trace-until 100/app
545 assume-screen 100/width, 12/height
546
547 assume-resources [
548 ¦ [lesson/recipes.mu] <- [
549 ¦ ¦ ||
550 ¦ ¦ |recipe foo [|
551 ¦ ¦ | local-scope|
552 ¦ ¦ | z:num <- add 2, 2|
553 ¦ ¦ | reply z|
554 ¦ ¦ |]|
555 ¦ ]
556 ]
557
558 env:&:environment <- new-programming-environment resources, screen, [foo]
559 render-all screen, env, render
560 $clear-trace
561
562 assume-console [
563 ¦ press F4
564 ]
565 event-loop screen, console, env, resources
566 screen-should-contain [
567 ¦ . run (F4) .
568 ¦ . ╎ .
569 ¦ .recipe foo [ ╎─────────────────────────────────────────────────.
570 ¦ . local-scope ╎0 edit copy to recipe delete .
571 ¦ . z:num <- add 2, 2 ╎foo .
572 ¦ . reply z ╎4 .
573 ¦ .] ╎─────────────────────────────────────────────────.
574 ¦ . ╎ .
575 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
576 ¦ . ╎ .
577 ]
578
579 trace-should-not-contain [
580 ¦ app: render recipes
581 ]
582
583 assume-console [
584 ¦ left-click 4, 28
585 ¦ press backspace
586 ¦ type [3]
587 ¦ press F4
588 ]
589 run [
590 ¦ event-loop screen, console, env, resources
591 ]
592
593 screen-should-contain [
594 ¦ . run (F4) .
595 ¦ . ╎ .
596 ¦ .recipe foo [ ╎─────────────────────────────────────────────────.
597 ¦ . local-scope ╎0 edit copy to recipe delete .
598 ¦ . z:num <- add 2, 3 ╎foo .
599 ¦ . reply z ╎5 .
600 ¦ .] ╎─────────────────────────────────────────────────.
601 ¦ . ╎ .
602 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
603 ¦ . ╎ .
604 ]
605 ]
606
607 scenario run-instruction-manages-screen-per-sandbox [
608 local-scope
609 trace-until 100/app
610 assume-screen 100/width, 20/height
611
612 assume-resources [
613 ]
614
615 env:&:environment <- new-programming-environment resources, screen, [print screen, 4]
616 render-all screen, env, render
617
618 assume-console [
619 ¦ press F4
620 ]
621 run [
622 ¦ event-loop screen, console, env, resources
623 ]
624
625 screen-should-contain [
626 ¦ . run (F4) .
627 ¦ . ╎ .
628 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
629 ¦ . ╎0 edit copy to recipe delete .
630 ¦ . ╎print screen, 4 .
631 ¦ . ╎screen: .
632 ¦ . ╎ .4 . .
633 ¦ . ╎ . . .
634 ¦ . ╎ . . .
635 ¦ . ╎ . . .
636 ¦ . ╎ . . .
637 ¦ . ╎─────────────────────────────────────────────────.
638 ¦ . ╎ .
639 ]
640 ]
641
642 def editor-contents editor:&:editor -> result:text [
643 local-scope
644 load-ingredients
645 buf:&:buffer:char <- new-buffer 80
646 curr:&:duplex-list:char <- get *editor, data:offset
647
648 assert curr, [editor without data is illegal; must have at least a sentinel]
649 curr <- next curr
650 return-unless curr, 0
651 {
652 ¦ break-unless curr
653 ¦ c:char <- get *curr, value:offset
654 ¦ buf <- append buf, c
655 ¦ curr <- next curr
656 ¦ loop
657 }
658 result <- buffer-to-array buf
659 ]
660
661 scenario editor-provides-edited-contents [
662 local-scope
663 assume-screen 10/width, 5/height
664 e:&:editor <- new-editor [abc], 0/left, 10/right
665 assume-console [
666 ¦ left-click 1, 2
667 ¦ type [def]
668 ]
669 run [
670 ¦ editor-event-loop screen, console, e
671 ¦ s:text <- editor-contents e
672 ¦ 1:@:char/raw <- copy *s
673 ]
674 memory-should-contain [
675 ¦ 1:array:character <- [abdefc]
676 ]
677 ]
678
679
680
681 scenario scrolling-down-past-bottom-of-recipe-editor [
682 local-scope
683 trace-until 100/app
684 assume-screen 100/width, 10/height
685 assume-resources [
686 ]
687 env:&:environment <- new-programming-environment resources, screen, []
688 render-all screen, env, render
689 assume-console [
690 ¦ press enter
691 ¦ press down-arrow
692 ]
693 event-loop screen, console, env, resources
694
695 screen-should-contain [
696 ¦ . run (F4) .
697 ¦ . ╎ .
698 ¦ . ╎─────────────────────────────────────────────────.
699 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
700 ¦ . ╎ .
701 ]
702 ]
703
704 scenario cursor-down-in-recipe-editor [
705 local-scope
706 trace-until 100/app
707 assume-screen 100/width, 10/height
708 assume-resources [
709 ]
710 env:&:environment <- new-programming-environment resources, screen, []
711 render-all screen, env, render
712 assume-console [
713 ¦ press enter
714 ¦ press up-arrow
715 ¦ press down-arrow
716 ]
717 event-loop screen, console, env, resources
718 cursor:char <- copy 9251/␣
719 print screen, cursor
720
721 screen-should-contain [
722 ¦ . run (F4) .
723 ¦ . ╎ .
724 ¦ .␣ ╎─────────────────────────────────────────────────.
725 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
726 ¦ . ╎ .
727 ]
728 ]
729
730
731
732
733 container environment [
734 recipe-bottom:num
735 ]
736
737 after <render-recipe-components-end> [
738 *env <- put *env, recipe-bottom:offset, row
739 ]
740
741 after <global-keypress> [
742 {
743 ¦ break-if sandbox-in-focus?
744 ¦ down-arrow?:bool <- equal k, 65516/down-arrow
745 ¦ break-unless down-arrow?
746 ¦ recipe-editor:&:editor <- get *env, recipes:offset
747 ¦ recipe-cursor-row:num <- get *recipe-editor, cursor-row:offset
748 ¦ recipe-editor-bottom:num <- get *recipe-editor, bottom:offset
749 ¦ at-bottom-of-editor?:bool <- greater-or-equal recipe-cursor-row, recipe-editor-bottom
750 ¦ break-unless at-bottom-of-editor?
751 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen
752 ¦ break-if more-to-scroll?
753 ¦ loop +next-event
754 }
755 {
756 ¦ break-if sandbox-in-focus?
757 ¦ page-down?:bool <- equal k, 65518/page-down
758 ¦ break-unless page-down?
759 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen
760 ¦ break-if more-to-scroll?
761 ¦ loop +next-event
762 }
763 ]
764
765 after <global-type> [
766 {
767 ¦ break-if sandbox-in-focus?
768 ¦ page-down?:bool <- equal k, 6/ctrl-f
769 ¦ break-unless page-down?
770 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen
771 ¦ break-if more-to-scroll?
772 ¦ loop +next-event
773 }
774 ]
775
776 def more-to-scroll? env:&:environment, screen:&:screen -> result:bool [
777 local-scope
778 load-ingredients
779 recipe-bottom:num <- get *env, recipe-bottom:offset
780 height:num <- screen-height screen
781 result <- greater-or-equal recipe-bottom, height
782 ]
783
784 scenario scrolling-down-past-bottom-of-recipe-editor-2 [
785 local-scope
786 trace-until 100/app
787 assume-screen 100/width, 10/height
788 assume-resources [
789 ]
790 env:&:environment <- new-programming-environment resources, screen, []
791 render-all screen, env, render
792 assume-console [
793 ¦
794 ¦ press enter
795 ¦
796 ¦ press up-arrow
797 ¦
798 ¦ press page-down
799 ]
800 event-loop screen, console, env, resources
801
802 screen-should-contain [
803 ¦ . run (F4) .
804 ¦ . ╎ .
805 ¦ . ╎─────────────────────────────────────────────────.
806 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ .
807 ¦ . ╎ .
808 ]
809 ]
810
811 scenario scrolling-down-past-bottom-of-recipe-editor-3 [
812 local-scope
813 trace-until 100/app
814 assume-screen 100/width, 10/height
815 assume-resources [
816 ]
817 env:&:environment <- new-programming-environment resources, screen, [ab
818 cd]
819 render-all screen, env, render
820 assume-console [
821 ¦
822 ¦ press enter
823 ¦
824 ¦ press ctrl-n
825 ¦
826 ¦ press down-arrow
827 ]
828 event-loop screen, console, env, resources
829 cursor:char <- copy 9251/␣
830 print screen, cursor
831
832 screen-should-contain [
833 ¦ . run (F4) .
834 ¦ . ╎ab .
835 ¦ . ╎␣d .
836 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
837 ¦ . ╎ .
838 ]
839 ]
840
841
842
843 scenario scrolling-down-past-bottom-of-sandbox-editor [
844 local-scope
845 trace-until 100/app
846 assume-screen 100/width, 10/height
847
848 assume-resources [
849 ]
850 env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
851 render-all screen, env, render
852 assume-console [
853 ¦
854 ¦ press F4
855 ]
856 event-loop screen, console, env, resources
857 screen-should-contain [
858 ¦ . run (F4) .
859 ¦ . ╎ .
860 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
861 ¦ . ╎0 edit copy to recipe delete .
862 ¦ . ╎add 2, 2 .
863 ]
864
865 assume-console [
866 ¦ press ctrl-n
867 ¦ press page-down
868 ]
869 run [
870 ¦ event-loop screen, console, env, resources
871 ¦ cursor:char <- copy 9251/␣
872 ¦ print screen, cursor
873 ]
874
875
876 screen-should-contain [
877 ¦ . run (F4) .
878 ¦ . ╎─────────────────────────────────────────────────.
879 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy to recipe delete .
880 ¦ . ╎add 2, 2 .
881 ¦ . ╎4 .
882 ]
883
884 assume-console [
885 ¦ press page-up
886 ]
887 run [
888 ¦ event-loop screen, console, env, resources
889 ¦ cursor:char <- copy 9251/␣
890 ¦ print screen, cursor
891 ]
892
893 screen-should-contain [
894 ¦ . run (F4) .
895 ¦ . ╎␣ .
896 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
897 ¦ . ╎0 edit copy to recipe delete .
898 ¦ . ╎add 2, 2 .
899 ]
900 ]
901
902
903 after <global-keypress> [
904 {
905 ¦ break-unless sandbox-in-focus?
906 ¦ page-down?:bool <- equal k, 65518/page-down
907 ¦ break-unless page-down?
908 ¦ sandbox:&:sandbox <- get *env, sandbox:offset
909 ¦ break-unless sandbox
910 ¦
911 ¦ {
912 ¦ ¦ render-from:num <- get *env, render-from:offset
913 ¦ ¦ number-of-sandboxes:num <- get *env, number-of-sandboxes:offset
914 ¦ ¦ max:num <- subtract number-of-sandboxes, 1
915 ¦ ¦ at-end?:bool <- greater-or-equal render-from, max
916 ¦ ¦ loop-if at-end?, +next-event
917 ¦ ¦ render-from <- add render-from, 1
918 ¦ ¦ *env <- put *env, render-from:offset, render-from
919 ¦ }
920 ¦ screen <- render-sandbox-side screen, env, render
921 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
922 ¦ loop +next-event
923 }
924 ]
925
926
927 after <update-cursor-special-cases> [
928 {
929 ¦ break-unless sandbox-in-focus?
930 ¦ render-from:num <- get *env, render-from:offset
931 ¦ scrolling?:bool <- greater-or-equal render-from, 0
932 ¦ break-unless scrolling?
933 ¦ cursor-column:num <- get *current-sandbox, left:offset
934 ¦ screen <- move-cursor screen, 2/row, cursor-column
935 ¦ return
936 }
937 ]
938
939
940 after <global-keypress> [
941 {
942 ¦ break-unless sandbox-in-focus?
943 ¦ page-up?:bool <- equal k, 65519/page-up
944 ¦ break-unless page-up?
945 ¦ render-from:num <- get *env, render-from:offset
946 ¦ at-beginning?:bool <- equal render-from, -1
947 ¦ break-if at-beginning?
948 ¦ render-from <- subtract render-from, 1
949 ¦ *env <- put *env, render-from:offset, render-from
950 ¦ screen <- render-sandbox-side screen, env, render
951 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
952 ¦ loop +next-event
953 }
954 ]
955
956
957
958 def previous-sandbox env:&:environment, in:&:sandbox -> out:&:sandbox [
959 local-scope
960 load-ingredients
961 curr:&:sandbox <- get *env, sandbox:offset
962 return-unless curr, 0/nil
963 next:&:sandbox <- get *curr, next-sandbox:offset
964 {
965 ¦ return-unless next, 0/nil
966 ¦ found?:bool <- equal next, in
967 ¦ break-if found?
968 ¦ curr <- copy next
969 ¦ next <- get *curr, next-sandbox:offset
970 ¦ loop
971 }
972 return curr
973 ]
974
975 scenario scrolling-down-past-bottom-on-recipe-side [
976 local-scope
977 trace-until 100/app
978 assume-screen 100/width, 10/height
979
980 assume-resources [
981 ¦ [lesson/recipes.mu] <- [
982 ¦ ¦ ||
983 ¦ ]
984 ]
985
986 env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
987 render-all screen, env, render
988 assume-console [
989 ¦ press F4
990 ]
991 event-loop screen, console, env, resources
992
993 assume-console [
994 ¦ press page-down
995 ]
996 run [
997 ¦ event-loop screen, console, env, resources
998 ¦ cursor:char <- copy 9251/␣
999 ¦ print screen, cursor
1000 ]
1001
1002 screen-should-contain [
1003 ¦ . run (F4) .
1004 ¦ .␣ ╎ .
1005 ¦ . ╎─────────────────────────────────────────────────.
1006 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1007 ¦ . ╎add 2, 2 .
1008 ]
1009 ]
1010
1011 scenario scrolling-through-multiple-sandboxes [
1012 local-scope
1013 trace-until 100/app
1014 assume-screen 100/width, 10/height
1015
1016 assume-resources [
1017 ]
1018 env:&:environment <- new-programming-environment resources, screen, []
1019 render-all screen, env, render
1020
1021 assume-console [
1022 ¦ press ctrl-n
1023 ¦ type [add 2, 2]
1024 ¦ press F4
1025 ¦ type [add 1, 1]
1026 ¦ press F4
1027 ]
1028 event-loop screen, console, env, resources
1029 cursor:char <- copy 9251/␣
1030 print screen, cursor
1031 screen-should-contain [
1032 ¦ . run (F4) .
1033 ¦ . ╎␣ .
1034 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1035 ¦ . ╎0 edit copy to recipe delete .
1036 ¦ . ╎add 1, 1 .
1037 ¦ . ╎2 .
1038 ¦ . ╎─────────────────────────────────────────────────.
1039 ¦ . ╎1 edit copy to recipe delete .
1040 ¦ . ╎add 2, 2 .
1041 ¦ . ╎4 .
1042 ]
1043
1044 assume-console [
1045 ¦ press page-down
1046 ]
1047 run [
1048 ¦ event-loop screen, console, env, resources
1049 ¦ cursor:char <- copy 9251/␣
1050 ¦ print screen, cursor
1051 ]
1052
1053
1054 screen-should-contain [
1055 ¦ . run (F4) .
1056 ¦ . ╎─────────────────────────────────────────────────.
1057 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy to recipe delete .
1058 ¦ . ╎add 1, 1 .
1059 ¦ . ╎2 .
1060 ¦ . ╎─────────────────────────────────────────────────.
1061 ¦ . ╎1 edit copy to recipe delete .
1062 ¦ . ╎add 2, 2 .
1063 ¦ . ╎4 .
1064 ]
1065
1066 assume-console [
1067 ¦ press page-down
1068 ]
1069 run [
1070 ¦ event-loop screen, console, env, resources
1071 ]
1072
1073 screen-should-contain [
1074 ¦ . run (F4) .
1075 ¦ . ╎─────────────────────────────────────────────────.
1076 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy to recipe delete .
1077 ¦ . ╎add 2, 2 .
1078 ¦ . ╎4 .
1079 ¦ . ╎─────────────────────────────────────────────────.
1080 ¦ . ╎ .
1081 ]
1082
1083 assume-console [
1084 ¦ press page-down
1085 ]
1086 run [
1087 ¦ event-loop screen, console, env, resources
1088 ]
1089
1090 screen-should-contain [
1091 ¦ . run (F4) .
1092 ¦ . ╎─────────────────────────────────────────────────.
1093 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy to recipe delete .
1094 ¦ . ╎add 2, 2 .
1095 ¦ . ╎4 .
1096 ¦ . ╎─────────────────────────────────────────────────.
1097 ¦ . ╎ .
1098 ]
1099
1100 assume-console [
1101 ¦ press page-up
1102 ]
1103 run [
1104 ¦ event-loop screen, console, env, resources
1105 ]
1106
1107 screen-should-contain [
1108 ¦ . run (F4) .
1109 ¦ . ╎─────────────────────────────────────────────────.
1110 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1111 ¦ . ╎add 1, 1 .
1112 ¦ . ╎2 .
1113 ¦ . ╎─────────────────────────────────────────────────.
1114 ¦ . ╎1 edit copy to recipe delete .
1115 ¦ . ╎add 2, 2 .
1116 ¦ . ╎4 .
1117 ]
1118
1119 assume-console [
1120 ¦ press page-up
1121 ]
1122 run [
1123 ¦ event-loop screen, console, env, resources
1124 ¦ cursor:char <- copy 9251/␣
1125 ¦ print screen, cursor
1126 ]
1127
1128 screen-should-contain [
1129 ¦ . run (F4) .
1130 ¦ . ╎␣ .
1131 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1132 ¦ . ╎0 edit copy to recipe delete .
1133 ¦ . ╎add 1, 1 .
1134 ¦ . ╎2 .
1135 ¦ . ╎─────────────────────────────────────────────────.
1136 ¦ . ╎1 edit copy to recipe delete .
1137 ¦ . ╎add 2, 2 .
1138 ¦ . ╎4 .
1139 ]
1140
1141 assume-console [
1142 ¦ press page-up
1143 ]
1144 run [
1145 ¦ event-loop screen, console, env, resources
1146 ¦ cursor:char <- copy 9251/␣
1147 ¦ print screen, cursor
1148 ]
1149
1150 screen-should-contain [
1151 ¦ . run (F4) .
1152 ¦ . ╎␣ .
1153 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1154 ¦ . ╎0 edit copy to recipe delete .
1155 ¦ . ╎add 1, 1 .
1156 ¦ . ╎2 .
1157 ¦ . ╎─────────────────────────────────────────────────.
1158 ¦ . ╎1 edit copy to recipe delete .
1159 ¦ . ╎add 2, 2 .
1160 ¦ . ╎4 .
1161 ]
1162 ]
1163
1164 scenario scrolling-manages-sandbox-index-correctly [
1165 local-scope
1166 trace-until 100/app
1167 assume-screen 100/width, 10/height
1168
1169 assume-resources [
1170 ]
1171 env:&:environment <- new-programming-environment resources, screen, []
1172 render-all screen, env, render
1173
1174 assume-console [
1175 ¦ press ctrl-n
1176 ¦ type [add 1, 1]
1177 ¦ press F4
1178 ]
1179 event-loop screen, console, env, resources
1180 screen-should-contain [
1181 ¦ . run (F4) .
1182 ¦ . ╎ .
1183 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1184 ¦ . ╎0 edit copy to recipe delete .
1185 ¦ . ╎add 1, 1 .
1186 ¦ . ╎2 .
1187 ¦ . ╎─────────────────────────────────────────────────.
1188 ¦ . ╎ .
1189 ]
1190
1191 assume-console [
1192 ¦ press page-down
1193 ]
1194 run [
1195 ¦ event-loop screen, console, env, resources
1196 ]
1197
1198
1199 screen-should-contain [
1200 ¦ . run (F4) .
1201 ¦ . ╎─────────────────────────────────────────────────.
1202 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1203 ¦ . ╎add 1, 1 .
1204 ¦ . ╎2 .
1205 ¦ . ╎─────────────────────────────────────────────────.
1206 ¦ . ╎ .
1207 ]
1208
1209 assume-console [
1210 ¦ press page-up
1211 ]
1212 run [
1213 ¦ event-loop screen, console, env, resources
1214 ]
1215
1216 screen-should-contain [
1217 ¦ . run (F4) .
1218 ¦ . ╎ .
1219 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
1220 ¦ . ╎0 edit copy to recipe delete .
1221 ¦ . ╎add 1, 1 .
1222 ¦ . ╎2 .
1223 ¦ . ╎─────────────────────────────────────────────────.
1224 ¦ . ╎ .
1225 ]
1226
1227 assume-console [
1228 ¦ press page-down
1229 ]
1230 run [
1231 ¦ event-loop screen, console, env, resources
1232 ]
1233
1234
1235 screen-should-contain [
1236 ¦ . run (F4) .
1237 ¦ . ╎─────────────────────────────────────────────────.
1238 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy to recipe delete .
1239 ¦ . ╎add 1, 1 .
1240 ¦ . ╎2 .
1241 ¦ . ╎─────────────────────────────────────────────────.
1242 ¦ . ╎ .
1243 ]
1244 ]