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