From 987b630476eff43467905299d936c388f28d3fc6 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 13 Apr 2017 22:26:25 -0700 Subject: 3820 --- html/edit/004-programming-environment.mu.html | 962 +++++++++++++------------- 1 file changed, 476 insertions(+), 486 deletions(-) (limited to 'html/edit/004-programming-environment.mu.html') diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html index 68de2b01..acfea6bf 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -70,7 +70,7 @@ if ('onhashchange' in window) { 7 local-scope 8 open-console 9 env:&:environment <- new-programming-environment 0/filesystem, 0/screen - 10 render-all 0/screen, env, render + 10 render-all 0/screen, env, render 11 event-loop 0/screen, 0/console, env, 0/filesystem 12 # never gets here 13 ] @@ -145,500 +145,490 @@ if ('onhashchange' in window) { 82 ¦ ¦ _ <- move-cursor-in-editor screen, recipes, t 83 ¦ ¦ sandbox-in-focus?:bool <- move-cursor-in-editor screen, current-sandbox, t 84 ¦ ¦ *env <- put *env, sandbox-in-focus?:offset, sandbox-in-focus? - 85 ¦ ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env + 85 ¦ ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env 86 ¦ ¦ loop +next-event 87 ¦ } 88 ¦ # 'resize' event - redraw editor 89 ¦ # todo: test this after supporting resize in assume-console 90 ¦ { - 91 ¦ ¦ r:resize-event, is-resize?:bool <- maybe-convert e:event, resize:variant + 91 ¦ ¦ r:resize-event, is-resize?:bool <- maybe-convert e:event, resize:variant 92 ¦ ¦ break-unless is-resize? - 93 ¦ ¦ # if more events, we're still resizing; wait until we stop - 94 ¦ ¦ more-events?:bool <- has-more-events? console - 95 ¦ ¦ { - 96 ¦ ¦ ¦ break-unless more-events? - 97 ¦ ¦ ¦ render-all-on-no-more-events? <- copy 1/true # no rendering now, full rendering on some future event - 98 ¦ ¦ } - 99 ¦ ¦ { -100 ¦ ¦ ¦ break-if more-events? -101 ¦ ¦ ¦ env, screen <- resize screen, env -102 ¦ ¦ ¦ screen <- render-all screen, env, render-without-moving-cursor -103 ¦ ¦ ¦ render-all-on-no-more-events? <- copy 0/false # full render done -104 ¦ ¦ } -105 ¦ ¦ loop +next-event -106 ¦ } -107 ¦ # if it's not global and not a touch event, send to appropriate editor -108 ¦ { -109 ¦ ¦ hide-screen screen -110 ¦ ¦ sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset -111 ¦ ¦ { -112 ¦ ¦ ¦ break-if sandbox-in-focus? -113 ¦ ¦ ¦ render?:bool <- handle-keyboard-event screen, recipes, e:event -114 ¦ ¦ ¦ # refresh screen only if no more events -115 ¦ ¦ ¦ # if there are more events to process, wait for them to clear up, then make sure you render-all afterward. -116 ¦ ¦ ¦ more-events?:bool <- has-more-events? console -117 ¦ ¦ ¦ { -118 ¦ ¦ ¦ ¦ break-unless more-events? -119 ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 1/true # no rendering now, full rendering on some future event -120 ¦ ¦ ¦ ¦ jump +finish-event -121 ¦ ¦ ¦ } -122 ¦ ¦ ¦ { -123 ¦ ¦ ¦ ¦ break-if more-events? -124 ¦ ¦ ¦ ¦ { -125 ¦ ¦ ¦ ¦ ¦ break-unless render-all-on-no-more-events? -126 ¦ ¦ ¦ ¦ ¦ # no more events, and we have to force render -127 ¦ ¦ ¦ ¦ ¦ screen <- render-all screen, env, render -128 ¦ ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 0/false -129 ¦ ¦ ¦ ¦ ¦ jump +finish-event -130 ¦ ¦ ¦ ¦ } -131 ¦ ¦ ¦ ¦ # no more events, no force render -132 ¦ ¦ ¦ ¦ { -133 ¦ ¦ ¦ ¦ ¦ break-unless render? -134 ¦ ¦ ¦ ¦ ¦ screen <- render-recipes screen, env, render -135 ¦ ¦ ¦ ¦ ¦ jump +finish-event -136 ¦ ¦ ¦ ¦ } -137 ¦ ¦ ¦ } -138 ¦ ¦ } -139 ¦ ¦ { -140 ¦ ¦ ¦ break-unless sandbox-in-focus? -141 ¦ ¦ ¦ render?:bool <- handle-keyboard-event screen, current-sandbox, e:event -142 ¦ ¦ ¦ # refresh screen only if no more events -143 ¦ ¦ ¦ # if there are more events to process, wait for them to clear up, then make sure you render-all afterward. -144 ¦ ¦ ¦ more-events?:bool <- has-more-events? console -145 ¦ ¦ ¦ { -146 ¦ ¦ ¦ ¦ break-unless more-events? -147 ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 1/true # no rendering now, full rendering on some future event -148 ¦ ¦ ¦ ¦ jump +finish-event -149 ¦ ¦ ¦ } -150 ¦ ¦ ¦ { -151 ¦ ¦ ¦ ¦ break-if more-events? -152 ¦ ¦ ¦ ¦ { -153 ¦ ¦ ¦ ¦ ¦ break-unless render-all-on-no-more-events? -154 ¦ ¦ ¦ ¦ ¦ # no more events, and we have to force render -155 ¦ ¦ ¦ ¦ ¦ screen <- render-all screen, env, render -156 ¦ ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 0/false -157 ¦ ¦ ¦ ¦ ¦ jump +finish-event -158 ¦ ¦ ¦ ¦ } -159 ¦ ¦ ¦ ¦ # no more events, no force render -160 ¦ ¦ ¦ ¦ { -161 ¦ ¦ ¦ ¦ ¦ break-unless render? -162 ¦ ¦ ¦ ¦ ¦ screen <- render-sandbox-side screen, env, render -163 ¦ ¦ ¦ ¦ ¦ jump +finish-event -164 ¦ ¦ ¦ ¦ } -165 ¦ ¦ ¦ } -166 ¦ ¦ } -167 ¦ ¦ +finish-event -168 ¦ ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env -169 ¦ ¦ show-screen screen -170 ¦ } -171 ¦ loop -172 } -173 ] -174 -175 def resize screen:&:screen, env:&:environment -> env:&:environment, screen:&:screen [ -176 local-scope -177 load-ingredients -178 clear-screen screen # update screen dimensions -179 width:num <- screen-width screen -180 divider:num, _ <- divide-with-remainder width, 2 -181 # update recipe editor -182 recipes:&:editor <- get *env, recipes:offset -183 right:num <- subtract divider, 1 -184 *recipes <- put *recipes, right:offset, right -185 # reset cursor (later we'll try to preserve its position) -186 *recipes <- put *recipes, cursor-row:offset, 1 -187 *recipes <- put *recipes, cursor-column:offset, 0 -188 # update sandbox editor -189 current-sandbox:&:editor <- get *env, current-sandbox:offset -190 left:num <- add divider, 1 -191 *current-sandbox <- put *current-sandbox, left:offset, left -192 right:num <- subtract width, 1 -193 *current-sandbox <- put *current-sandbox, right:offset, right -194 # reset cursor (later we'll try to preserve its position) -195 *current-sandbox <- put *current-sandbox, cursor-row:offset, 1 -196 *current-sandbox <- put *current-sandbox, cursor-column:offset, left -197 ] -198 -199 # Variant of 'render' that updates cursor-row and cursor-column based on -200 # before-cursor (rather than the other way around). If before-cursor moves -201 # off-screen, it resets cursor-row and cursor-column. -202 def render-without-moving-cursor screen:&:screen, editor:&:editor -> last-row:num, last-column:num, screen:&:screen, editor:&:editor [ -203 local-scope -204 load-ingredients -205 return-unless editor, 1/top, 0/left -206 left:num <- get *editor, left:offset -207 screen-height:num <- screen-height screen -208 right:num <- get *editor, right:offset -209 curr:&:duplex-list:char <- get *editor, top-of-screen:offset -210 prev:&:duplex-list:char <- copy curr # just in case curr becomes null and we can't compute prev -211 curr <- next curr -212 color:num <- copy 7/white -213 row:num <- copy 1/top -214 column:num <- copy left -215 # save before-cursor -216 old-before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -217 # initialze cursor-row/cursor-column/before-cursor to the top of the screen -218 # by default -219 *editor <- put *editor, cursor-row:offset, row -220 *editor <- put *editor, cursor-column:offset, column -221 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -222 *editor <- put *editor, before-cursor:offset, top-of-screen -223 screen <- move-cursor screen, row, column -224 { -225 ¦ +next-character -226 ¦ break-unless curr -227 ¦ off-screen?:bool <- greater-or-equal row, screen-height -228 ¦ break-if off-screen? -229 ¦ # if we find old-before-cursor still on the new resized screen, update -230 ¦ # editor.cursor-row and editor.cursor-column based on -231 ¦ # old-before-cursor -232 ¦ { -233 ¦ ¦ at-cursor?:bool <- equal old-before-cursor, prev -234 ¦ ¦ break-unless at-cursor? -235 ¦ ¦ *editor <- put *editor, cursor-row:offset, row -236 ¦ ¦ *editor <- put *editor, cursor-column:offset, column -237 ¦ ¦ *editor <- put *editor, before-cursor:offset, old-before-cursor -238 ¦ } -239 ¦ c:char <- get *curr, value:offset -240 ¦ <character-c-received> -241 ¦ { -242 ¦ ¦ # newline? move to left rather than 0 -243 ¦ ¦ newline?:bool <- equal c, 10/newline -244 ¦ ¦ break-unless newline? -245 ¦ ¦ # clear rest of line in this window -246 ¦ ¦ clear-line-until screen, right -247 ¦ ¦ # skip to next line -248 ¦ ¦ row <- add row, 1 -249 ¦ ¦ column <- copy left -250 ¦ ¦ screen <- move-cursor screen, row, column -251 ¦ ¦ curr <- next curr -252 ¦ ¦ prev <- next prev -253 ¦ ¦ loop +next-character -254 ¦ } -255 ¦ { -256 ¦ ¦ # at right? wrap. even if there's only one more letter left; we need -257 ¦ ¦ # room for clicking on the cursor after it. -258 ¦ ¦ at-right?:bool <- equal column, right -259 ¦ ¦ break-unless at-right? -260 ¦ ¦ # print wrap icon -261 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left -262 ¦ ¦ print screen, wrap-icon, 245/grey -263 ¦ ¦ column <- copy left -264 ¦ ¦ row <- add row, 1 -265 ¦ ¦ screen <- move-cursor screen, row, column -266 ¦ ¦ # don't increment curr -267 ¦ ¦ loop +next-character -268 ¦ } -269 ¦ print screen, c, color -270 ¦ curr <- next curr -271 ¦ prev <- next prev -272 ¦ column <- add column, 1 -273 ¦ loop -274 } -275 # save first character off-screen -276 *editor <- put *editor, bottom-of-screen:offset, curr -277 *editor <- put *editor, bottom:offset, row -278 return row, column -279 ] -280 -281 scenario point-at-multiple-editors [ -282 local-scope -283 trace-until 100/app # trace too long -284 assume-screen 30/width, 5/height -285 # initialize both halves of screen -286 assume-resources [ -287 ¦ [lesson/recipes.mu] <- [ -288 ¦ ¦ |abc| -289 ¦ ] -290 ] -291 env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox editor -292 # focus on both sides -293 assume-console [ -294 ¦ left-click 1, 1 -295 ¦ left-click 1, 17 -296 ] -297 # check cursor column in each -298 run [ -299 ¦ event-loop screen, console, env, resources -300 ¦ recipes:&:editor <- get *env, recipes:offset -301 ¦ 5:num/raw <- get *recipes, cursor-column:offset -302 ¦ sandbox:&:editor <- get *env, current-sandbox:offset -303 ¦ 7:num/raw <- get *sandbox, cursor-column:offset -304 ] -305 memory-should-contain [ -306 ¦ 5 <- 1 -307 ¦ 7 <- 17 -308 ] -309 ] -310 -311 scenario edit-multiple-editors [ -312 local-scope -313 trace-until 100/app # trace too long -314 assume-screen 30/width, 5/height -315 # initialize both halves of screen -316 assume-resources [ -317 ¦ [lesson/recipes.mu] <- [ -318 ¦ ¦ |abc| -319 ¦ ] -320 ] -321 env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox -322 render-all screen, env, render -323 # type one letter in each of them -324 assume-console [ -325 ¦ left-click 1, 1 -326 ¦ type [0] -327 ¦ left-click 1, 17 -328 ¦ type [1] -329 ] -330 run [ -331 ¦ event-loop screen, console, env, resources -332 ¦ recipes:&:editor <- get *env, recipes:offset -333 ¦ 5:num/raw <- get *recipes, cursor-column:offset -334 ¦ sandbox:&:editor <- get *env, current-sandbox:offset -335 ¦ 7:num/raw <- get *sandbox, cursor-column:offset -336 ] -337 screen-should-contain [ -338 ¦ . run (F4) . # this line has a different background, but we don't test that yet -339 ¦ .a0bc ╎d1ef . -340 ¦ . ╎──────────────. -341 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . -342 ¦ . ╎ . -343 ] -344 memory-should-contain [ -345 ¦ 5 <- 2 # cursor column of recipe editor -346 ¦ 7 <- 18 # cursor column of sandbox editor -347 ] -348 # show the cursor at the right window -349 run [ -350 ¦ cursor:char <- copy 9251/␣ -351 ¦ print screen, cursor -352 ] -353 screen-should-contain [ -354 ¦ . run (F4) . -355 ¦ .a0bc ╎d1␣f . -356 ¦ . ╎──────────────. -357 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . -358 ¦ . ╎ . -359 ] -360 ] -361 -362 scenario editor-in-focus-keeps-cursor [ -363 local-scope -364 trace-until 100/app # trace too long -365 assume-screen 30/width, 5/height -366 assume-resources [ -367 ¦ [lesson/recipes.mu] <- [ -368 ¦ ¦ |abc| -369 ¦ ] -370 ] -371 env:&:environment <- new-programming-environment resources, screen, [def] -372 render-all screen, env, render -373 # initialize programming environment and highlight cursor -374 assume-console [] -375 run [ -376 ¦ event-loop screen, console, env, resources -377 ¦ cursor:char <- copy 9251/␣ -378 ¦ print screen, cursor -379 ] -380 # is cursor at the right place? -381 screen-should-contain [ -382 ¦ . run (F4) . -383 ¦ .␣bc ╎def . -384 ¦ . ╎──────────────. -385 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . -386 ¦ . ╎ . -387 ] -388 # now try typing a letter -389 assume-console [ -390 ¦ type [z] -391 ] -392 run [ -393 ¦ event-loop screen, console, env, resources -394 ¦ cursor:char <- copy 9251/␣ -395 ¦ print screen, cursor -396 ] -397 # cursor should still be right -398 screen-should-contain [ -399 ¦ . run (F4) . -400 ¦ .z␣bc ╎def . -401 ¦ . ╎──────────────. -402 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . -403 ¦ . ╎ . -404 ] -405 ] -406 -407 scenario backspace-in-sandbox-editor-joins-lines [ -408 local-scope -409 trace-until 100/app # trace too long -410 assume-screen 30/width, 5/height -411 assume-resources [ -412 ] -413 # initialize sandbox side with two lines -414 test-sandbox-editor-contents:text <- new [abc -415 def] -416 env:&:environment <- new-programming-environment resources, screen, test-sandbox-editor-contents -417 render-all screen, env, render -418 screen-should-contain [ -419 ¦ . run (F4) . -420 ¦ . ╎abc . -421 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎def . -422 ¦ . ╎──────────────. -423 ¦ . ╎ . + 93 ¦ ¦ env, screen <- resize screen, env + 94 ¦ ¦ screen <- render-all screen, env, render-without-moving-cursor + 95 ¦ ¦ loop +next-event + 96 ¦ } + 97 ¦ # if it's not global and not a touch event, send to appropriate editor + 98 ¦ { + 99 ¦ ¦ hide-screen screen +100 ¦ ¦ sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset +101 ¦ ¦ { +102 ¦ ¦ ¦ break-if sandbox-in-focus? +103 ¦ ¦ ¦ render?:bool <- handle-keyboard-event screen, recipes, e:event +104 ¦ ¦ ¦ # refresh screen only if no more events +105 ¦ ¦ ¦ # if there are more events to process, wait for them to clear up, then make sure you render-all afterward. +106 ¦ ¦ ¦ more-events?:bool <- has-more-events? console +107 ¦ ¦ ¦ { +108 ¦ ¦ ¦ ¦ break-unless more-events? +109 ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 1/true # no rendering now, full rendering on some future event +110 ¦ ¦ ¦ ¦ jump +finish-event +111 ¦ ¦ ¦ } +112 ¦ ¦ ¦ { +113 ¦ ¦ ¦ ¦ break-if more-events? +114 ¦ ¦ ¦ ¦ { +115 ¦ ¦ ¦ ¦ ¦ break-unless render-all-on-no-more-events? +116 ¦ ¦ ¦ ¦ ¦ # no more events, and we have to force render +117 ¦ ¦ ¦ ¦ ¦ screen <- render-all screen, env, render +118 ¦ ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 0/false +119 ¦ ¦ ¦ ¦ ¦ jump +finish-event +120 ¦ ¦ ¦ ¦ } +121 ¦ ¦ ¦ ¦ # no more events, no force render +122 ¦ ¦ ¦ ¦ { +123 ¦ ¦ ¦ ¦ ¦ break-unless render? +124 ¦ ¦ ¦ ¦ ¦ screen <- render-recipes screen, env, render +125 ¦ ¦ ¦ ¦ ¦ jump +finish-event +126 ¦ ¦ ¦ ¦ } +127 ¦ ¦ ¦ } +128 ¦ ¦ } +129 ¦ ¦ { +130 ¦ ¦ ¦ break-unless sandbox-in-focus? +131 ¦ ¦ ¦ render?:bool <- handle-keyboard-event screen, current-sandbox, e:event +132 ¦ ¦ ¦ # refresh screen only if no more events +133 ¦ ¦ ¦ # if there are more events to process, wait for them to clear up, then make sure you render-all afterward. +134 ¦ ¦ ¦ more-events?:bool <- has-more-events? console +135 ¦ ¦ ¦ { +136 ¦ ¦ ¦ ¦ break-unless more-events? +137 ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 1/true # no rendering now, full rendering on some future event +138 ¦ ¦ ¦ ¦ jump +finish-event +139 ¦ ¦ ¦ } +140 ¦ ¦ ¦ { +141 ¦ ¦ ¦ ¦ break-if more-events? +142 ¦ ¦ ¦ ¦ { +143 ¦ ¦ ¦ ¦ ¦ break-unless render-all-on-no-more-events? +144 ¦ ¦ ¦ ¦ ¦ # no more events, and we have to force render +145 ¦ ¦ ¦ ¦ ¦ screen <- render-all screen, env, render +146 ¦ ¦ ¦ ¦ ¦ render-all-on-no-more-events? <- copy 0/false +147 ¦ ¦ ¦ ¦ ¦ jump +finish-event +148 ¦ ¦ ¦ ¦ } +149 ¦ ¦ ¦ ¦ # no more events, no force render +150 ¦ ¦ ¦ ¦ { +151 ¦ ¦ ¦ ¦ ¦ break-unless render? +152 ¦ ¦ ¦ ¦ ¦ screen <- render-sandbox-side screen, env, render +153 ¦ ¦ ¦ ¦ ¦ jump +finish-event +154 ¦ ¦ ¦ ¦ } +155 ¦ ¦ ¦ } +156 ¦ ¦ } +157 ¦ ¦ +finish-event +158 ¦ ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env +159 ¦ ¦ show-screen screen +160 ¦ } +161 ¦ loop +162 } +163 ] +164 +165 def resize screen:&:screen, env:&:environment -> env:&:environment, screen:&:screen [ +166 local-scope +167 load-ingredients +168 clear-screen screen # update screen dimensions +169 width:num <- screen-width screen +170 divider:num, _ <- divide-with-remainder width, 2 +171 # update recipe editor +172 recipes:&:editor <- get *env, recipes:offset +173 right:num <- subtract divider, 1 +174 *recipes <- put *recipes, right:offset, right +175 # reset cursor (later we'll try to preserve its position) +176 *recipes <- put *recipes, cursor-row:offset, 1 +177 *recipes <- put *recipes, cursor-column:offset, 0 +178 # update sandbox editor +179 current-sandbox:&:editor <- get *env, current-sandbox:offset +180 left:num <- add divider, 1 +181 *current-sandbox <- put *current-sandbox, left:offset, left +182 right:num <- subtract width, 1 +183 *current-sandbox <- put *current-sandbox, right:offset, right +184 # reset cursor (later we'll try to preserve its position) +185 *current-sandbox <- put *current-sandbox, cursor-row:offset, 1 +186 *current-sandbox <- put *current-sandbox, cursor-column:offset, left +187 ] +188 +189 # Variant of 'render' that updates cursor-row and cursor-column based on +190 # before-cursor (rather than the other way around). If before-cursor moves +191 # off-screen, it resets cursor-row and cursor-column. +192 def render-without-moving-cursor screen:&:screen, editor:&:editor -> last-row:num, last-column:num, screen:&:screen, editor:&:editor [ +193 local-scope +194 load-ingredients +195 return-unless editor, 1/top, 0/left +196 left:num <- get *editor, left:offset +197 screen-height:num <- screen-height screen +198 right:num <- get *editor, right:offset +199 curr:&:duplex-list:char <- get *editor, top-of-screen:offset +200 prev:&:duplex-list:char <- copy curr # just in case curr becomes null and we can't compute prev +201 curr <- next curr +202 color:num <- copy 7/white +203 row:num <- copy 1/top +204 column:num <- copy left +205 # save before-cursor +206 old-before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +207 # initialze cursor-row/cursor-column/before-cursor to the top of the screen +208 # by default +209 *editor <- put *editor, cursor-row:offset, row +210 *editor <- put *editor, cursor-column:offset, column +211 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +212 *editor <- put *editor, before-cursor:offset, top-of-screen +213 screen <- move-cursor screen, row, column +214 { +215 ¦ +next-character +216 ¦ break-unless curr +217 ¦ off-screen?:bool <- greater-or-equal row, screen-height +218 ¦ break-if off-screen? +219 ¦ # if we find old-before-cursor still on the new resized screen, update +220 ¦ # editor.cursor-row and editor.cursor-column based on +221 ¦ # old-before-cursor +222 ¦ { +223 ¦ ¦ at-cursor?:bool <- equal old-before-cursor, prev +224 ¦ ¦ break-unless at-cursor? +225 ¦ ¦ *editor <- put *editor, cursor-row:offset, row +226 ¦ ¦ *editor <- put *editor, cursor-column:offset, column +227 ¦ ¦ *editor <- put *editor, before-cursor:offset, old-before-cursor +228 ¦ } +229 ¦ c:char <- get *curr, value:offset +230 ¦ <character-c-received> +231 ¦ { +232 ¦ ¦ # newline? move to left rather than 0 +233 ¦ ¦ newline?:bool <- equal c, 10/newline +234 ¦ ¦ break-unless newline? +235 ¦ ¦ # clear rest of line in this window +236 ¦ ¦ clear-line-until screen, right +237 ¦ ¦ # skip to next line +238 ¦ ¦ row <- add row, 1 +239 ¦ ¦ column <- copy left +240 ¦ ¦ screen <- move-cursor screen, row, column +241 ¦ ¦ curr <- next curr +242 ¦ ¦ prev <- next prev +243 ¦ ¦ loop +next-character +244 ¦ } +245 ¦ { +246 ¦ ¦ # at right? wrap. even if there's only one more letter left; we need +247 ¦ ¦ # room for clicking on the cursor after it. +248 ¦ ¦ at-right?:bool <- equal column, right +249 ¦ ¦ break-unless at-right? +250 ¦ ¦ # print wrap icon +251 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left +252 ¦ ¦ print screen, wrap-icon, 245/grey +253 ¦ ¦ column <- copy left +254 ¦ ¦ row <- add row, 1 +255 ¦ ¦ screen <- move-cursor screen, row, column +256 ¦ ¦ # don't increment curr +257 ¦ ¦ loop +next-character +258 ¦ } +259 ¦ print screen, c, color +260 ¦ curr <- next curr +261 ¦ prev <- next prev +262 ¦ column <- add column, 1 +263 ¦ loop +264 } +265 # save first character off-screen +266 *editor <- put *editor, bottom-of-screen:offset, curr +267 *editor <- put *editor, bottom:offset, row +268 return row, column +269 ] +270 +271 scenario point-at-multiple-editors [ +272 local-scope +273 trace-until 100/app # trace too long +274 assume-screen 30/width, 5/height +275 # initialize both halves of screen +276 assume-resources [ +277 ¦ [lesson/recipes.mu] <- [ +278 ¦ ¦ |abc| +279 ¦ ] +280 ] +281 env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox editor +282 # focus on both sides +283 assume-console [ +284 ¦ left-click 1, 1 +285 ¦ left-click 1, 17 +286 ] +287 # check cursor column in each +288 run [ +289 ¦ event-loop screen, console, env, resources +290 ¦ recipes:&:editor <- get *env, recipes:offset +291 ¦ 5:num/raw <- get *recipes, cursor-column:offset +292 ¦ sandbox:&:editor <- get *env, current-sandbox:offset +293 ¦ 7:num/raw <- get *sandbox, cursor-column:offset +294 ] +295 memory-should-contain [ +296 ¦ 5 <- 1 +297 ¦ 7 <- 17 +298 ] +299 ] +300 +301 scenario edit-multiple-editors [ +302 local-scope +303 trace-until 100/app # trace too long +304 assume-screen 30/width, 5/height +305 # initialize both halves of screen +306 assume-resources [ +307 ¦ [lesson/recipes.mu] <- [ +308 ¦ ¦ |abc| +309 ¦ ] +310 ] +311 env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox +312 render-all screen, env, render +313 # type one letter in each of them +314 assume-console [ +315 ¦ left-click 1, 1 +316 ¦ type [0] +317 ¦ left-click 1, 17 +318 ¦ type [1] +319 ] +320 run [ +321 ¦ event-loop screen, console, env, resources +322 ¦ recipes:&:editor <- get *env, recipes:offset +323 ¦ 5:num/raw <- get *recipes, cursor-column:offset +324 ¦ sandbox:&:editor <- get *env, current-sandbox:offset +325 ¦ 7:num/raw <- get *sandbox, cursor-column:offset +326 ] +327 screen-should-contain [ +328 ¦ . run (F4) . # this line has a different background, but we don't test that yet +329 ¦ .a0bc ╎d1ef . +330 ¦ . ╎──────────────. +331 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . +332 ¦ . ╎ . +333 ] +334 memory-should-contain [ +335 ¦ 5 <- 2 # cursor column of recipe editor +336 ¦ 7 <- 18 # cursor column of sandbox editor +337 ] +338 # show the cursor at the right window +339 run [ +340 ¦ cursor:char <- copy 9251/␣ +341 ¦ print screen, cursor +342 ] +343 screen-should-contain [ +344 ¦ . run (F4) . +345 ¦ .a0bc ╎d1␣f . +346 ¦ . ╎──────────────. +347 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . +348 ¦ . ╎ . +349 ] +350 ] +351 +352 scenario editor-in-focus-keeps-cursor [ +353 local-scope +354 trace-until 100/app # trace too long +355 assume-screen 30/width, 5/height +356 assume-resources [ +357 ¦ [lesson/recipes.mu] <- [ +358 ¦ ¦ |abc| +359 ¦ ] +360 ] +361 env:&:environment <- new-programming-environment resources, screen, [def] +362 render-all screen, env, render +363 # initialize programming environment and highlight cursor +364 assume-console [] +365 run [ +366 ¦ event-loop screen, console, env, resources +367 ¦ cursor:char <- copy 9251/␣ +368 ¦ print screen, cursor +369 ] +370 # is cursor at the right place? +371 screen-should-contain [ +372 ¦ . run (F4) . +373 ¦ .␣bc ╎def . +374 ¦ . ╎──────────────. +375 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . +376 ¦ . ╎ . +377 ] +378 # now try typing a letter +379 assume-console [ +380 ¦ type [z] +381 ] +382 run [ +383 ¦ event-loop screen, console, env, resources +384 ¦ cursor:char <- copy 9251/␣ +385 ¦ print screen, cursor +386 ] +387 # cursor should still be right +388 screen-should-contain [ +389 ¦ . run (F4) . +390 ¦ .z␣bc ╎def . +391 ¦ . ╎──────────────. +392 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . +393 ¦ . ╎ . +394 ] +395 ] +396 +397 scenario backspace-in-sandbox-editor-joins-lines [ +398 local-scope +399 trace-until 100/app # trace too long +400 assume-screen 30/width, 5/height +401 assume-resources [ +402 ] +403 # initialize sandbox side with two lines +404 test-sandbox-editor-contents:text <- new [abc +405 def] +406 env:&:environment <- new-programming-environment resources, screen, test-sandbox-editor-contents +407 render-all screen, env, render +408 screen-should-contain [ +409 ¦ . run (F4) . +410 ¦ . ╎abc . +411 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎def . +412 ¦ . ╎──────────────. +413 ¦ . ╎ . +414 ] +415 # position cursor at start of second line and hit backspace +416 assume-console [ +417 ¦ left-click 2, 16 +418 ¦ press backspace +419 ] +420 run [ +421 ¦ event-loop screen, console, env, resources +422 ¦ cursor:char <- copy 9251/␣ +423 ¦ print screen, cursor 424 ] -425 # position cursor at start of second line and hit backspace -426 assume-console [ -427 ¦ left-click 2, 16 -428 ¦ press backspace -429 ] -430 run [ -431 ¦ event-loop screen, console, env, resources -432 ¦ cursor:char <- copy 9251/␣ -433 ¦ print screen, cursor -434 ] -435 # cursor moves to end of old line -436 screen-should-contain [ -437 ¦ . run (F4) . -438 ¦ . ╎abc␣ef . -439 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. -440 ¦ . ╎ . -441 ] -442 ] -443 -444 def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ -445 local-scope -446 load-ingredients -447 trace 10, [app], [render all] -448 hide-screen screen -449 # top menu -450 trace 11, [app], [render top menu] -451 width:num <- screen-width screen -452 draw-horizontal screen, 0, 0/left, width, 32/space, 0/black, 238/grey -453 button-start:num <- subtract width, 20 -454 button-on-screen?:bool <- greater-or-equal button-start, 0 -455 assert button-on-screen?, [screen too narrow for menu] -456 screen <- move-cursor screen, 0/row, button-start -457 print screen, [ run (F4) ], 255/white, 161/reddish -458 # dotted line down the middle -459 trace 11, [app], [render divider] -460 divider:num, _ <- divide-with-remainder width, 2 -461 height:num <- screen-height screen -462 draw-vertical screen, divider, 1/top, height, 9482/vertical-dotted -463 # -464 screen <- render-recipes screen, env, render-editor -465 screen <- render-sandbox-side screen, env, render-editor -466 <render-components-end> -467 # -468 recipes:&:editor <- get *env, recipes:offset -469 current-sandbox:&:editor <- get *env, current-sandbox:offset -470 sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset -471 screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env -472 # -473 show-screen screen -474 ] -475 -476 def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ -477 local-scope -478 load-ingredients -479 trace 11, [app], [render recipes] -480 recipes:&:editor <- get *env, recipes:offset -481 # render recipes -482 left:num <- get *recipes, left:offset -483 right:num <- get *recipes, right:offset -484 row:num, column:num, screen <- call render-editor, screen, recipes -485 clear-line-until screen, right -486 row <- add row, 1 -487 <render-recipe-components-end> -488 # draw dotted line after recipes -489 draw-horizontal screen, row, left, right, 9480/horizontal-dotted -490 row <- add row, 1 -491 clear-screen-from screen, row, left, left, right -492 ] -493 -494 # replaced in a later layer -495 def render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ -496 local-scope -497 load-ingredients -498 current-sandbox:&:editor <- get *env, current-sandbox:offset -499 left:num <- get *current-sandbox, left:offset -500 right:num <- get *current-sandbox, right:offset -501 row:num, column:num, screen, current-sandbox <- call render-editor, screen, current-sandbox -502 clear-line-until screen, right -503 row <- add row, 1 -504 # draw solid line after code (you'll see why in later layers) -505 draw-horizontal screen, row, left, right -506 row <- add row, 1 -507 clear-screen-from screen, row, left, left, right -508 ] -509 -510 def update-cursor screen:&:screen, recipes:&:editor, current-sandbox:&:editor, sandbox-in-focus?:bool, env:&:environment -> screen:&:screen [ -511 local-scope -512 load-ingredients -513 <update-cursor-special-cases> -514 { -515 ¦ break-if sandbox-in-focus? -516 ¦ cursor-row:num <- get *recipes, cursor-row:offset -517 ¦ cursor-column:num <- get *recipes, cursor-column:offset -518 } -519 { -520 ¦ break-unless sandbox-in-focus? -521 ¦ cursor-row:num <- get *current-sandbox, cursor-row:offset -522 ¦ cursor-column:num <- get *current-sandbox, cursor-column:offset -523 } -524 screen <- move-cursor screen, cursor-row, cursor-column -525 ] -526 -527 # ctrl-l - redraw screen (just in case it printed junk somehow) +425 # cursor moves to end of old line +426 screen-should-contain [ +427 ¦ . run (F4) . +428 ¦ . ╎abc␣ef . +429 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. +430 ¦ . ╎ . +431 ] +432 ] +433 +434 def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ +435 local-scope +436 load-ingredients +437 trace 10, [app], [render all] +438 hide-screen screen +439 # top menu +440 trace 11, [app], [render top menu] +441 width:num <- screen-width screen +442 draw-horizontal screen, 0, 0/left, width, 32/space, 0/black, 238/grey +443 button-start:num <- subtract width, 20 +444 button-on-screen?:bool <- greater-or-equal button-start, 0 +445 assert button-on-screen?, [screen too narrow for menu] +446 screen <- move-cursor screen, 0/row, button-start +447 print screen, [ run (F4) ], 255/white, 161/reddish +448 # dotted line down the middle +449 trace 11, [app], [render divider] +450 divider:num, _ <- divide-with-remainder width, 2 +451 height:num <- screen-height screen +452 draw-vertical screen, divider, 1/top, height, 9482/vertical-dotted +453 # +454 screen <- render-recipes screen, env, render-editor +455 screen <- render-sandbox-side screen, env, render-editor +456 <render-components-end> +457 # +458 recipes:&:editor <- get *env, recipes:offset +459 current-sandbox:&:editor <- get *env, current-sandbox:offset +460 sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset +461 screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env +462 # +463 show-screen screen +464 ] +465 +466 def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ +467 local-scope +468 load-ingredients +469 trace 11, [app], [render recipes] +470 recipes:&:editor <- get *env, recipes:offset +471 # render recipes +472 left:num <- get *recipes, left:offset +473 right:num <- get *recipes, right:offset +474 row:num, column:num, screen <- call render-editor, screen, recipes +475 clear-line-until screen, right +476 row <- add row, 1 +477 <render-recipe-components-end> +478 # draw dotted line after recipes +479 draw-horizontal screen, row, left, right, 9480/horizontal-dotted +480 row <- add row, 1 +481 clear-screen-from screen, row, left, left, right +482 ] +483 +484 # replaced in a later layer +485 def render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ +486 local-scope +487 load-ingredients +488 current-sandbox:&:editor <- get *env, current-sandbox:offset +489 left:num <- get *current-sandbox, left:offset +490 right:num <- get *current-sandbox, right:offset +491 row:num, column:num, screen, current-sandbox <- call render-editor, screen, current-sandbox +492 clear-line-until screen, right +493 row <- add row, 1 +494 # draw solid line after code (you'll see why in later layers) +495 draw-horizontal screen, row, left, right +496 row <- add row, 1 +497 clear-screen-from screen, row, left, left, right +498 ] +499 +500 def update-cursor screen:&:screen, recipes:&:editor, current-sandbox:&:editor, sandbox-in-focus?:bool, env:&:environment -> screen:&:screen [ +501 local-scope +502 load-ingredients +503 <update-cursor-special-cases> +504 { +505 ¦ break-if sandbox-in-focus? +506 ¦ cursor-row:num <- get *recipes, cursor-row:offset +507 ¦ cursor-column:num <- get *recipes, cursor-column:offset +508 } +509 { +510 ¦ break-unless sandbox-in-focus? +511 ¦ cursor-row:num <- get *current-sandbox, cursor-row:offset +512 ¦ cursor-column:num <- get *current-sandbox, cursor-column:offset +513 } +514 screen <- move-cursor screen, cursor-row, cursor-column +515 ] +516 +517 # ctrl-l - redraw screen (just in case it printed junk somehow) +518 +519 after <global-type> [ +520 { +521 ¦ redraw-screen?:bool <- equal c, 12/ctrl-l +522 ¦ break-unless redraw-screen? +523 ¦ screen <- render-all screen, env:&:environment, render +524 ¦ sync-screen screen +525 ¦ loop +next-event +526 } +527 ] 528 -529 after <global-type> [ -530 { -531 ¦ redraw-screen?:bool <- equal c, 12/ctrl-l -532 ¦ break-unless redraw-screen? -533 ¦ screen <- render-all screen, env:&:environment, render -534 ¦ sync-screen screen -535 ¦ loop +next-event -536 } -537 ] -538 -539 # ctrl-n - switch focus -540 # todo: test this -541 -542 after <global-type> [ -543 { -544 ¦ switch-side?:bool <- equal c, 14/ctrl-n -545 ¦ break-unless switch-side? -546 ¦ sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset -547 ¦ sandbox-in-focus? <- not sandbox-in-focus? -548 ¦ *env <- put *env, sandbox-in-focus?:offset, sandbox-in-focus? -549 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env -550 ¦ loop +next-event -551 } -552 ] -553 -554 ## helpers -555 -556 def draw-vertical screen:&:screen, col:num, y:num, bottom:num -> screen:&:screen [ -557 local-scope -558 load-ingredients -559 style:char, style-found?:bool <- next-ingredient +529 # ctrl-n - switch focus +530 # todo: test this +531 +532 after <global-type> [ +533 { +534 ¦ switch-side?:bool <- equal c, 14/ctrl-n +535 ¦ break-unless switch-side? +536 ¦ sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset +537 ¦ sandbox-in-focus? <- not sandbox-in-focus? +538 ¦ *env <- put *env, sandbox-in-focus?:offset, sandbox-in-focus? +539 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env +540 ¦ loop +next-event +541 } +542 ] +543 +544 ## helpers +545 +546 def draw-vertical screen:&:screen, col:num, y:num, bottom:num -> screen:&:screen [ +547 local-scope +548 load-ingredients +549 style:char, style-found?:bool <- next-ingredient +550 { +551 ¦ break-if style-found? +552 ¦ style <- copy 9474/vertical +553 } +554 color:num, color-found?:bool <- next-ingredient +555 { +556 ¦ # default color to white +557 ¦ break-if color-found? +558 ¦ color <- copy 245/grey +559 } 560 { -561 ¦ break-if style-found? -562 ¦ style <- copy 9474/vertical -563 } -564 color:num, color-found?:bool <- next-ingredient -565 { -566 ¦ # default color to white -567 ¦ break-if color-found? -568 ¦ color <- copy 245/grey -569 } -570 { -571 ¦ continue?:bool <- lesser-than y, bottom -572 ¦ break-unless continue? -573 ¦ screen <- move-cursor screen, y, col -574 ¦ print screen, style, color -575 ¦ y <- add y, 1 -576 ¦ loop -577 } -578 ] +561 ¦ continue?:bool <- lesser-than y, bottom +562 ¦ break-unless continue? +563 ¦ screen <- move-cursor screen, y, col +564 ¦ print screen, style, color +565 ¦ y <- add y, 1 +566 ¦ loop +567 } +568 ] -- cgit 1.4.1-2-gfad0