about summary refs log tree commit diff stats
path: root/html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-09-07 10:37:27 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-09-07 10:37:27 -0700
commitf5465e1220d73e237c51897b7d1211ec53b0dc04 (patch)
tree939ee8e57241b8515aede8106c6420e330ace75a /html
parent5ccf2653fb7d31b013f77df4e92e964e45c54f8a (diff)
downloadmu-f5465e1220d73e237c51897b7d1211ec53b0dc04.tar.gz
2177
Diffstat (limited to 'html')
-rw-r--r--html/051scenario_test.mu.html49
-rw-r--r--html/060string.mu.html1652
-rw-r--r--html/061channel.mu.html448
-rw-r--r--html/062array.mu.html61
-rw-r--r--html/063list.mu.html83
-rw-r--r--html/065duplex_list.mu.html828
-rw-r--r--html/066stream.mu.html72
-rw-r--r--html/071print.mu.html954
-rw-r--r--html/073scenario_screen_test.mu.html27
-rw-r--r--html/074console.mu.html153
-rw-r--r--html/076scenario_console_test.mu.html33
-rw-r--r--html/callcc.mu.html20
-rw-r--r--html/channel.mu.html62
-rw-r--r--html/chessboard.mu.html850
-rw-r--r--html/console.mu.html21
-rw-r--r--html/counters.mu.html47
-rw-r--r--html/display.mu.html15
-rw-r--r--html/edit.mu.html6555
-rw-r--r--html/edit/001-editor.mu.html539
-rw-r--r--html/edit/002-typing.mu.html1092
-rw-r--r--html/edit/003-shortcuts.mu.html3107
-rw-r--r--html/edit/004-programming-environment.mu.html826
-rw-r--r--html/edit/005-sandbox.mu.html555
-rw-r--r--html/edit/006-sandbox-edit.mu.html212
-rw-r--r--html/edit/007-sandbox-delete.mu.html149
-rw-r--r--html/edit/008-sandbox-test.mu.html211
-rw-r--r--html/edit/009-sandbox-trace.mu.html248
-rw-r--r--html/edit/010-warnings.mu.html428
-rw-r--r--html/edit/011-editor-undo.mu.html2095
-rw-r--r--html/factorial.mu.html45
-rw-r--r--html/fork.mu.html27
-rw-r--r--html/global.mu.html13
-rw-r--r--html/screen.mu.html43
-rw-r--r--html/tangle.mu.html46
-rw-r--r--html/x.mu.html13
35 files changed, 12270 insertions, 9309 deletions
diff --git a/html/051scenario_test.mu.html b/html/051scenario_test.mu.html
index f7807a4d..d38539dd 100644
--- a/html/051scenario_test.mu.html
+++ b/html/051scenario_test.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -29,69 +30,69 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># tests for 'scenario' in previous layer</span>
 
-scenario first_scenario_in_mu [
+<span class="muScenario">scenario</span> first_scenario_in_mu [
   run [
-    1:number<span class="Special"> &lt;- </span>add 2, 2
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>, <span class="Constant">2</span>
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>4
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
   ]
 ]
 
-scenario scenario_with_comment_in_mu [
+<span class="muScenario">scenario</span> scenario_with_comment_in_mu [
   run [
     <span class="Comment"># comment</span>
-    1:number<span class="Special"> &lt;- </span>add 2, 2
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>, <span class="Constant">2</span>
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>4
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
   ]
 ]
 
-scenario scenario_with_multiple_comments_in_mu [
+<span class="muScenario">scenario</span> scenario_with_multiple_comments_in_mu [
   run [
     <span class="Comment"># comment1</span>
     <span class="Comment"># comment2</span>
-    1:number<span class="Special"> &lt;- </span>add 2, 2
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>, <span class="Constant">2</span>
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>4
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
   ]
 ]
 
-scenario check_string_in_memory [
+<span class="muScenario">scenario</span> check_string_in_memory [
   run [
-    1:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 3
-    2:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 97  <span class="Comment"># 'a'</span>
-    3:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 98  <span class="Comment"># 'b'</span>
-    4:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 99  <span class="Comment"># 'c'</span>
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>
+    <span class="Constant">2</span>:character<span class="Special"> &lt;- </span>copy <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>copy <span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    <span class="Constant">4</span>:character<span class="Special"> &lt;- </span>copy <span class="Constant">99</span>  <span class="Comment"># 'c'</span>
   ]
   memory-should-contain [
-    1:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">1</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario check_trace [
+<span class="muScenario">scenario</span> check_trace [
   run [
-    1:number<span class="Special"> &lt;- </span>add 2, 2
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>, <span class="Constant">2</span>
   ]
   trace-should-contain [
-    mem: storing 4 <span class="Identifier">in</span> location 1
+    mem: storing <span class="Constant">4</span> in location <span class="Constant">1</span>
   ]
 ]
 
-scenario check_trace_negative [
+<span class="muScenario">scenario</span> check_trace_negative [
   run [
-    1:number<span class="Special"> &lt;- </span>add 2, 2
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">2</span>, <span class="Constant">2</span>
   ]
   trace-should-not-contain [
-    mem: storing 5 <span class="Identifier">in</span> location 1
+    mem: storing <span class="Constant">5</span> in location <span class="Constant">1</span>
   ]
 ]
 
-scenario check_trace_instruction [
+<span class="muScenario">scenario</span> check_trace_instruction [
   run [
-    trace 1, [foo], [aaa]
+    trace <span class="Constant">1</span>, <span class="Constant">[foo]</span>, <span class="Constant">[aaa]</span>
   ]
   trace-should-contain [
     foo: aaa
diff --git a/html/060string.mu.html b/html/060string.mu.html
index ff86a100..a5cf9f7a 100644
--- a/html/060string.mu.html
+++ b/html/060string.mu.html
@@ -13,10 +13,14 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,70 +34,70 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># Some useful helpers for dealing with strings.</span>
 
-recipe string-equal [
-  <span class="Underlined">local</span>-scope
-  a:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  a-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *a
-  b:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  b-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *b
+<span class="muRecipe">recipe</span> string-equal [
+  <span class="Constant">local-scope</span>
+  a:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  a-len:number<span class="Special"> &lt;- </span>length *a
+  b:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  b-len:number<span class="Special"> &lt;- </span>length *b
   <span class="Comment"># compare lengths</span>
-  {
-    trace 99, [string-equal], [comparing lengths]
-    <span class="Identifier">length</span>-equal?:boolean<span class="Special"> &lt;- </span>equal a-len, b-len
-    break-if <span class="Identifier">length</span>-equal?
-    reply 0
-  }
+  <span class="Delimiter">{</span>
+    trace <span class="Constant">99</span>, <span class="Constant">[string-equal]</span>, <span class="Constant">[comparing lengths]</span>
+    length-equal?:boolean<span class="Special"> &lt;- </span>equal a-len, b-len
+    <span class="muControl">break-if</span> length-equal?
+    <span class="muControl">reply</span> <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># compare each corresponding character</span>
-  trace 99, [string-equal], [comparing characters]
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  trace <span class="Constant">99</span>, <span class="Constant">[string-equal]</span>, <span class="Constant">[comparing characters]</span>
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, a-len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     a2:character<span class="Special"> &lt;- </span>index *a, i
     b2:character<span class="Special"> &lt;- </span>index *b, i
-    {
-      chars-<span class="Identifier">match</span>?:boolean<span class="Special"> &lt;- </span>equal a2, b2
-      break-if chars-<span class="Identifier">match</span>?
-      reply 0
-    }
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop
-  }
-  reply 1
-]
-
-scenario string-equal-reflexive [
+    <span class="Delimiter">{</span>
+      chars-match?:boolean<span class="Special"> &lt;- </span>equal a2, b2
+      <span class="muControl">break-if</span> chars-match?
+      <span class="muControl">reply</span> <span class="Constant">0</span>
+    <span class="Delimiter">}</span>
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">1</span>
+]
+
+<span class="muScenario">scenario</span> string-equal-reflexive [
   run [
-    default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    3:boolean/<span class="Special">raw &lt;- </span>string-equal x, x
+    <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>string-equal x, x
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># x == x for all x</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># x == x for all x</span>
   ]
 ]
 
-scenario string-equal-identical [
+<span class="muScenario">scenario</span> string-equal-identical [
   run [
-    default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    3:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
+    <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    y:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># abc == abc</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># abc == abc</span>
   ]
 ]
 
-scenario string-equal-distinct-lengths [
+<span class="muScenario">scenario</span> string-equal-distinct-lengths [
   run [
-    default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    3:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
+    <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    y:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># abc != abcd</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># abc != abcd</span>
   ]
   trace-should-contain [
     string-equal: comparing lengths
@@ -103,1250 +107,1250 @@ scenario string-equal-distinct-lengths [
   ]
 ]
 
-scenario string-equal-with-empty [
+<span class="muScenario">scenario</span> string-equal-with-empty [
   run [
-    default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    3:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
+    <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    y:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># &quot;&quot; != abcd</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># &quot;&quot; != abcd</span>
   ]
 ]
 
-scenario string-equal-common-lengths-but-distinct [
+<span class="muScenario">scenario</span> string-equal-common-lengths-but-distinct [
   run [
-    default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abd]
-    3:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
+    <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    y:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abd]</span>
+    <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>string-equal x, y
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># abc != abd</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># abc != abd</span>
   ]
 ]
 
 <span class="Comment"># A new type to help incrementally construct strings.</span>
-container buffer [
-  <span class="Identifier">length</span>:number
-  data:address:<span class="Identifier">array</span>:character
-]
-
-recipe <span class="Identifier">new</span>-buffer [
-  <span class="Underlined">local</span>-scope
-  result:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span> buffer:<span class="Identifier">type</span>
-  len:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Identifier">length</span>:offset
-  *len:address:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  s:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get-address *result, data:offset
-  capacity:number, found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">assert</span> found?, [<span class="Identifier">new</span>-buffer must get a capacity argument]
-  *s<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, capacity
-  reply result
-]
-
-recipe grow-buffer [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:buffer<span class="Special"> &lt;- </span>next-ingredient
+<span class="muData">container</span> buffer [
+  length:number
+  data:address:array:character
+]
+
+<span class="muRecipe">recipe</span> new-buffer [
+  <span class="Constant">local-scope</span>
+  result:address:buffer<span class="Special"> &lt;- </span>new <span class="Constant">buffer:type</span>
+  len:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">length:offset</span>
+  *len:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  s:address:address:array:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  capacity:number, found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  assert found?, <span class="Constant">[new-buffer must get a capacity argument]</span>
+  *s<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, capacity
+  <span class="muControl">reply</span> result
+]
+
+<span class="muRecipe">recipe</span> grow-buffer [
+  <span class="Constant">local-scope</span>
+  in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># double buffer size</span>
-  x:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, data:offset
-  oldlen:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> **x
-  newlen:number<span class="Special"> &lt;- </span>multiply oldlen, 2
-  olddata:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *x
-  *x<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, newlen
+  x:address:address:array:character<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">data:offset</span>
+  oldlen:number<span class="Special"> &lt;- </span>length **x
+  newlen:number<span class="Special"> &lt;- </span>multiply oldlen, <span class="Constant">2</span>
+  olddata:address:array:character<span class="Special"> &lt;- </span>copy *x
+  *x<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, newlen
   <span class="Comment"># copy old contents</span>
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, oldlen
-    break-if done?
+    <span class="muControl">break-if</span> done?
     src:character<span class="Special"> &lt;- </span>index *olddata, i
     dest:address:character<span class="Special"> &lt;- </span>index-address **x, i
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> src
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop
-  }
-  reply <span class="Identifier">in</span>
-]
-
-recipe buffer-full? [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:buffer<span class="Special"> &lt;- </span>next-ingredient
-  len:number<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, data:offset
-  capacity:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
+    *dest<span class="Special"> &lt;- </span>copy src
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> in
+]
+
+<span class="muRecipe">recipe</span> buffer-full? [
+  <span class="Constant">local-scope</span>
+  in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  len:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">length:offset</span>
+  s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
+  capacity:number<span class="Special"> &lt;- </span>length *s
   result:boolean<span class="Special"> &lt;- </span>greater-or-equal len, capacity
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># in &lt;- buffer-append in:address:buffer, c:character</span>
-recipe buffer-<span class="Identifier">append</span> [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:buffer<span class="Special"> &lt;- </span>next-ingredient
-  c:character<span class="Special"> &lt;- </span>next-ingredient
-  len:address:number<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset
-  {
+<span class="muRecipe">recipe</span> buffer-append [
+  <span class="Constant">local-scope</span>
+  in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  len:address:number<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">length:offset</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># backspace? just drop last character if it exists and return</span>
-    backspace?:boolean<span class="Special"> &lt;- </span>equal c, 8/backspace
-    break-unless backspace?
-    empty?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *len, 0
-    reply-if empty?, <span class="Identifier">in</span>/same-as-ingredient:0
-    *len<span class="Special"> &lt;- </span>subtract *len, 1
-    reply <span class="Identifier">in</span>/same-as-ingredient:0
-  }
-  {
+    backspace?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/backspace</span>
+    <span class="muControl">break-unless</span> backspace?
+    empty?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *len, <span class="Constant">0</span>
+    <span class="muControl">reply-if</span> empty?, in/same-as-ingredient:<span class="Constant">0</span>
+    *len<span class="Special"> &lt;- </span>subtract *len, <span class="Constant">1</span>
+    <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># grow buffer if necessary</span>
-    full?:boolean<span class="Special"> &lt;- </span>buffer-full? <span class="Identifier">in</span>
-    break-unless full?
-    <span class="Identifier">in</span><span class="Special"> &lt;- </span>grow-buffer <span class="Identifier">in</span>
-  }
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, data:offset
+    full?:boolean<span class="Special"> &lt;- </span>buffer-full? in
+    <span class="muControl">break-unless</span> full?
+    in<span class="Special"> &lt;- </span>grow-buffer in
+  <span class="Delimiter">}</span>
+  s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
   dest:address:character<span class="Special"> &lt;- </span>index-address *s, *len
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> c
-  *len<span class="Special"> &lt;- </span>add *len, 1
-  reply <span class="Identifier">in</span>/same-as-ingredient:0
+  *dest<span class="Special"> &lt;- </span>copy c
+  *len<span class="Special"> &lt;- </span>add *len, <span class="Constant">1</span>
+  <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario buffer-<span class="Identifier">append</span>-works [
+<span class="muScenario">scenario</span> buffer-append-works [
   run [
-    <span class="Underlined">local</span>-scope
-    x:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span>-buffer 3
-    s1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *x:address:buffer, data:offset
-    x:address:buffer<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 97  <span class="Comment"># 'a'</span>
-    x:address:buffer<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 98  <span class="Comment"># 'b'</span>
-    x:address:buffer<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 99  <span class="Comment"># 'c'</span>
-    s2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *x:address:buffer, data:offset
-    1:boolean/<span class="Special">raw &lt;- </span>equal s1:address:<span class="Identifier">array</span>:character, s2:address:<span class="Identifier">array</span>:character
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *s2:address:<span class="Identifier">array</span>:character
-    +buffer-filled
-    x:address:buffer<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x:address:buffer, 100  <span class="Comment"># 'd'</span>
-    s3:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *x:address:buffer, data:offset
-    10:boolean/<span class="Special">raw &lt;- </span>equal s1:address:<span class="Identifier">array</span>:character, s3:address:<span class="Identifier">array</span>:character
-    11:number/<span class="Special">raw &lt;- </span>get *x:address:buffer, <span class="Identifier">length</span>:offset
-    12:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *s3:address:<span class="Identifier">array</span>:character
+    <span class="Constant">local-scope</span>
+    x:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">3</span>
+    s1:address:array:character<span class="Special"> &lt;- </span>get *x:address:buffer, <span class="Constant">data:offset</span>
+    x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">99</span>  <span class="Comment"># 'c'</span>
+    s2:address:array:character<span class="Special"> &lt;- </span>get *x:address:buffer, <span class="Constant">data:offset</span>
+    <span class="Constant">1</span>:boolean/<span class="Special">raw &lt;- </span>equal s1:address:array:character, s2:address:array:character
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *s2:address:array:character
+<span class="Constant">    +buffer-filled</span>
+    x:address:buffer<span class="Special"> &lt;- </span>buffer-append x:address:buffer, <span class="Constant">100</span>  <span class="Comment"># 'd'</span>
+    s3:address:array:character<span class="Special"> &lt;- </span>get *x:address:buffer, <span class="Constant">data:offset</span>
+    <span class="Constant">10</span>:boolean/<span class="Special">raw &lt;- </span>equal s1:address:array:character, s3:address:array:character
+    <span class="Constant">11</span>:number/<span class="Special">raw &lt;- </span>get *x:address:buffer, <span class="Constant">length:offset</span>
+    <span class="Constant">12</span>:array:character/<span class="Special">raw &lt;- </span>copy *s3:address:array:character
   ]
   memory-should-contain [
     <span class="Comment"># before +buffer-filled</span>
-    1<span class="Special"> &lt;- </span>1   <span class="Comment"># no change in data pointer</span>
-    2<span class="Special"> &lt;- </span>3   <span class="Comment"># size of data</span>
-    3<span class="Special"> &lt;- </span>97  <span class="Comment"># data</span>
-    4<span class="Special"> &lt;- </span>98
-    5<span class="Special"> &lt;- </span>99
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">1</span>   <span class="Comment"># no change in data pointer</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">3</span>   <span class="Comment"># size of data</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># data</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">98</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">99</span>
     <span class="Comment"># in the end</span>
-    10<span class="Special"> &lt;- </span>0   <span class="Comment"># data pointer has grown</span>
-    11<span class="Special"> &lt;- </span>4   <span class="Comment"># final length</span>
-    12<span class="Special"> &lt;- </span>6   <span class="Comment"># but data's capacity has doubled</span>
-    13<span class="Special"> &lt;- </span>97  <span class="Comment"># data</span>
-    14<span class="Special"> &lt;- </span>98
-    15<span class="Special"> &lt;- </span>99
-    16<span class="Special"> &lt;- </span>100
-    17<span class="Special"> &lt;- </span>0
-    18<span class="Special"> &lt;- </span>0
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span>   <span class="Comment"># data pointer has grown</span>
+    <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">4</span>   <span class="Comment"># final length</span>
+    <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">6</span>   <span class="Comment"># but data's capacity has doubled</span>
+    <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># data</span>
+    <span class="Constant">14</span><span class="Special"> &lt;- </span><span class="Constant">98</span>
+    <span class="Constant">15</span><span class="Special"> &lt;- </span><span class="Constant">99</span>
+    <span class="Constant">16</span><span class="Special"> &lt;- </span><span class="Constant">100</span>
+    <span class="Constant">17</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">18</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario buffer-<span class="Identifier">append</span>-handles-backspace [
+<span class="muScenario">scenario</span> buffer-append-handles-backspace [
   run [
-    <span class="Underlined">local</span>-scope
-    x:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span>-buffer 3
-    x<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x, 97  <span class="Comment"># 'a'</span>
-    x<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x, 98  <span class="Comment"># 'b'</span>
-    x<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> x, 8/backspace
-    s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>buffer-to-<span class="Identifier">array</span> x
-    1:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *s
+    <span class="Constant">local-scope</span>
+    x:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">3</span>
+    x<span class="Special"> &lt;- </span>buffer-append x, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    x<span class="Special"> &lt;- </span>buffer-append x, <span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    x<span class="Special"> &lt;- </span>buffer-append x, <span class="Constant">8/backspace</span>
+    s:address:array:character<span class="Special"> &lt;- </span>buffer-to-array x
+    <span class="Constant">1</span>:array:character/<span class="Special">raw &lt;- </span>copy *s
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>1   <span class="Comment"># length</span>
-    2<span class="Special"> &lt;- </span>97  <span class="Comment"># contents</span>
-    3<span class="Special"> &lt;- </span>0
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">1</span>   <span class="Comment"># length</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># contents</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
 <span class="Comment"># result:address:array:character &lt;- integer-to-decimal-string n:number</span>
-recipe integer-to-decimal-string [
-  <span class="Underlined">local</span>-scope
-  n:number<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> integer-to-decimal-string [
+  <span class="Constant">local-scope</span>
+  n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># is it zero?</span>
-  {
-    break-if n
-    result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [0]
-    reply result
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> n
+    result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[0]</span>
+    <span class="muControl">reply</span> result
+  <span class="Delimiter">}</span>
   <span class="Comment"># save sign</span>
-  negate-result:boolean<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
-    negative?:boolean<span class="Special"> &lt;- </span>lesser-than n, 0
-    break-unless negative?
-    negate-result<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1
-    n<span class="Special"> &lt;- </span>multiply n, -1
-  }
+  negate-result:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    negative?:boolean<span class="Special"> &lt;- </span>lesser-than n, <span class="Constant">0</span>
+    <span class="muControl">break-unless</span> negative?
+    negate-result<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
+    n<span class="Special"> &lt;- </span>multiply n, <span class="Constant">-1</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># add digits from right to left into intermediate buffer</span>
-  tmp:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span>-buffer 30
-  digit-base:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 48  <span class="Comment"># '0'</span>
-  {
-    done?:boolean<span class="Special"> &lt;- </span>equal n, 0
-    break-if done?
-    n, digit:number<span class="Special"> &lt;- </span><span class="Identifier">divide</span>-with-remainder n, 10
+  tmp:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">30</span>
+  digit-base:number<span class="Special"> &lt;- </span>copy <span class="Constant">48</span>  <span class="Comment"># '0'</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>equal n, <span class="Constant">0</span>
+    <span class="muControl">break-if</span> done?
+    n, digit:number<span class="Special"> &lt;- </span>divide-with-remainder n, <span class="Constant">10</span>
     c:character<span class="Special"> &lt;- </span>add digit-base, digit
-    tmp:address:buffer<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> tmp, c
-    loop
-  }
+    tmp:address:buffer<span class="Special"> &lt;- </span>buffer-append tmp, c
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># add sign</span>
-  {
-    break-unless negate-result:boolean
-    tmp<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> tmp, 45  <span class="Comment"># '-'</span>
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> negate-result:boolean
+    tmp<span class="Special"> &lt;- </span>buffer-append tmp, <span class="Constant">45</span>  <span class="Comment"># '-'</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># reverse buffer into string result</span>
-  len:number<span class="Special"> &lt;- </span>get *tmp, <span class="Identifier">length</span>:offset
-  buf:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *tmp, data:offset
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, len
-  i:number<span class="Special"> &lt;- </span>subtract len, 1  <span class="Comment"># source index, decreasing</span>
-  j:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># destination index, increasing</span>
-  {
+  len:number<span class="Special"> &lt;- </span>get *tmp, <span class="Constant">length:offset</span>
+  buf:address:array:character<span class="Special"> &lt;- </span>get *tmp, <span class="Constant">data:offset</span>
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, len
+  i:number<span class="Special"> &lt;- </span>subtract len, <span class="Constant">1</span>  <span class="Comment"># source index, decreasing</span>
+  j:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># destination index, increasing</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while i &gt;= 0</span>
-    done?:boolean<span class="Special"> &lt;- </span>lesser-than i, 0
-    break-if done?
+    done?:boolean<span class="Special"> &lt;- </span>lesser-than i, <span class="Constant">0</span>
+    <span class="muControl">break-if</span> done?
     <span class="Comment"># result[j] = tmp[i]</span>
     src:character<span class="Special"> &lt;- </span>index *buf, i
     dest:address:character<span class="Special"> &lt;- </span>index-address *result, j
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> src
-    i<span class="Special"> &lt;- </span>subtract i, 1
-    j<span class="Special"> &lt;- </span>add j, 1
-    loop
-  }
-  reply result
-]
-
-recipe buffer-to-<span class="Identifier">array</span> [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:buffer<span class="Special"> &lt;- </span>next-ingredient
-  {
+    *dest<span class="Special"> &lt;- </span>copy src
+    i<span class="Special"> &lt;- </span>subtract i, <span class="Constant">1</span>
+    j<span class="Special"> &lt;- </span>add j, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muRecipe">recipe</span> buffer-to-array [
+  <span class="Constant">local-scope</span>
+  in:address:buffer<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># propagate null buffer</span>
-    break-if <span class="Identifier">in</span>
-    reply 0
-  }
-  len:number<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, <span class="Identifier">length</span>:offset
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, data:offset
+    <span class="muControl">break-if</span> in
+    <span class="muControl">reply</span> <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  len:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">length:offset</span>
+  s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
   <span class="Comment"># we can't just return s because it is usually the wrong length</span>
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, len
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, len
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     src:character<span class="Special"> &lt;- </span>index *s, i
     dest:address:character<span class="Special"> &lt;- </span>index-address *result, i
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> src
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop
-  }
-  reply result
+    *dest<span class="Special"> &lt;- </span>copy src
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario integer-to-decimal-digit-zero [
+<span class="muScenario">scenario</span> integer-to-decimal-digit-zero [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string 0
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string <span class="Constant">0</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[0]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[0]</span>
   ]
 ]
 
-scenario integer-to-decimal-digit-positive [
+<span class="muScenario">scenario</span> integer-to-decimal-digit-positive [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string 234
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string <span class="Constant">234</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[234]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[234]</span>
   ]
 ]
 
-scenario integer-to-decimal-digit-negative [
+<span class="muScenario">scenario</span> integer-to-decimal-digit-negative [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string -1
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>integer-to-decimal-string <span class="Constant">-1</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>2
-    3<span class="Special"> &lt;- </span>45  <span class="Comment"># '-'</span>
-    4<span class="Special"> &lt;- </span>49  <span class="Comment"># '1'</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">45</span>  <span class="Comment"># '-'</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">49</span>  <span class="Comment"># '1'</span>
   ]
 ]
 
 <span class="Comment"># result:address:array:character &lt;- string-append a:address:array:character, b:address:array:character</span>
-recipe string-<span class="Identifier">append</span> [
-  <span class="Underlined">local</span>-scope
+<span class="muRecipe">recipe</span> string-append [
+  <span class="Constant">local-scope</span>
   <span class="Comment"># result = new character[a.length + b.length]</span>
-  a:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  a-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *a
-  b:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  b-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *b
+  a:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  a-len:number<span class="Special"> &lt;- </span>length *a
+  b:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  b-len:number<span class="Special"> &lt;- </span>length *b
   result-len:number<span class="Special"> &lt;- </span>add a-len, b-len
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, result-len
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, result-len
   <span class="Comment"># copy a into result</span>
-  result-idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  result-idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while i &lt; a.length</span>
     a-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, a-len
-    break-if a-done?
+    <span class="muControl">break-if</span> a-done?
     <span class="Comment"># result[result-idx] = a[i]</span>
     out:address:character<span class="Special"> &lt;- </span>index-address *result, result-idx
-    <span class="Identifier">in</span>:character<span class="Special"> &lt;- </span>index *a, i
-    *out<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-    i<span class="Special"> &lt;- </span>add i, 1
-    result-idx<span class="Special"> &lt;- </span>add result-idx, 1
-    loop
-  }
+    in:character<span class="Special"> &lt;- </span>index *a, i
+    *out<span class="Special"> &lt;- </span>copy in
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># copy b into result</span>
-  i<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  i<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while i &lt; b.length</span>
     b-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, b-len
-    break-if b-done?
+    <span class="muControl">break-if</span> b-done?
     <span class="Comment"># result[result-idx] = a[i]</span>
     out:address:character<span class="Special"> &lt;- </span>index-address *result, result-idx
-    <span class="Identifier">in</span>:character<span class="Special"> &lt;- </span>index *b, i
-    *out<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-    i<span class="Special"> &lt;- </span>add i, 1
-    result-idx<span class="Special"> &lt;- </span>add result-idx, 1
-    loop
-  }
-  reply result
+    in:character<span class="Special"> &lt;- </span>index *b, i
+    *out<span class="Special"> &lt;- </span>copy in
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario string-<span class="Identifier">append</span>-1 [
+<span class="muScenario">scenario</span> string-append-1 [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [hello,]
-    2:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [ world!]
-    3:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-<span class="Identifier">append</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
-    4:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[hello,]</span>
+    <span class="Constant">2</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[ world!]</span>
+    <span class="Constant">3</span>:address:array:character/<span class="Special">raw &lt;- </span>string-append <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span>
+    <span class="Constant">4</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    4:string<span class="Special"> &lt;- </span>[hello, world!]
+    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[hello, world!]</span>
   ]
 ]
 
-scenario replace-character-<span class="Identifier">in</span>-string [
+<span class="muScenario">scenario</span> replace-character-in-string [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 98/b, 122/z
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>string-replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">98/b</span>, <span class="Constant">122/z</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[azc]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[azc]</span>
   ]
 ]
 
-recipe string-replace [
-  <span class="Underlined">local</span>-scope
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  oldc:character<span class="Special"> &lt;- </span>next-ingredient
-  newc:character<span class="Special"> &lt;- </span>next-ingredient
-  from:number<span class="Special"> &lt;- </span>next-ingredient
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
+<span class="muRecipe">recipe</span> string-replace [
+  <span class="Constant">local-scope</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  oldc:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  newc:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  from:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  len:number<span class="Special"> &lt;- </span>length *s
   i:number<span class="Special"> &lt;- </span>find-next s, oldc, from
   done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-  reply-if done?, s/same-as-ingredient:0
+  <span class="muControl">reply-if</span> done?, s/same-as-ingredient:<span class="Constant">0</span>
   dest:address:character<span class="Special"> &lt;- </span>index-address *s, i
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> newc
-  i<span class="Special"> &lt;- </span>add i, 1
+  *dest<span class="Special"> &lt;- </span>copy newc
+  i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
   s<span class="Special"> &lt;- </span>string-replace s, oldc, newc, i
-  reply s/same-as-ingredient:0
+  <span class="muControl">reply</span> s/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario replace-character-at-start [
+<span class="muScenario">scenario</span> replace-character-at-start [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 97/a, 122/z
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>string-replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[zbc]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[zbc]</span>
   ]
 ]
 
-scenario replace-character-at-end [
+<span class="muScenario">scenario</span> replace-character-at-end [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 99/c, 122/z
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>string-replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">99/c</span>, <span class="Constant">122/z</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[abz]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abz]</span>
   ]
 ]
 
-scenario replace-character-missing [
+<span class="muScenario">scenario</span> replace-character-missing [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 100/d, 122/z
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>string-replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">100/d</span>, <span class="Constant">122/z</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario replace-all-characters [
+<span class="muScenario">scenario</span> replace-all-characters [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [banana]
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span>string-replace 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 97/a, 122/z
-    2:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[banana]</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>string-replace <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">97/a</span>, <span class="Constant">122/z</span>
+    <span class="Constant">2</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    2:string<span class="Special"> &lt;- </span>[bznznz]
+    <span class="Constant">2</span>:string<span class="Special"> &lt;- </span><span class="Constant">[bznznz]</span>
   ]
 ]
 
 <span class="Comment"># replace underscores in first with remaining args</span>
 <span class="Comment"># result:address:array:character &lt;- interpolate template:address:array:character, ...</span>
-recipe <span class="Identifier">interpolate</span> [
-  <span class="Underlined">local</span>-scope
-  template:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> interpolate [
+  <span class="Constant">local-scope</span>
+  template:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># compute result-len, space to allocate for result</span>
-  tem-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *template
-  result-len:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> tem-len
-  {
+  tem-len:number<span class="Special"> &lt;- </span>length *template
+  result-len:number<span class="Special"> &lt;- </span>copy tem-len
+  <span class="Delimiter">{</span>
     <span class="Comment"># while arg received</span>
-    a:address:<span class="Identifier">array</span>:character, <span class="Identifier">arg</span>-received?:boolean<span class="Special"> &lt;- </span>next-ingredient
-    break-unless <span class="Identifier">arg</span>-received?
+    a:address:array:character, arg-received?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+    <span class="muControl">break-unless</span> arg-received?
     <span class="Comment"># result-len = result-len + arg.length - 1 (for the 'underscore' being replaced)</span>
-    a-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *a
+    a-len:number<span class="Special"> &lt;- </span>length *a
     result-len<span class="Special"> &lt;- </span>add result-len, a-len
-    result-len<span class="Special"> &lt;- </span>subtract result-len, 1
-    loop
-  }
+    result-len<span class="Special"> &lt;- </span>subtract result-len, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   rewind-ingredients
-  _<span class="Special"> &lt;- </span>next-ingredient  <span class="Comment"># skip template</span>
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, result-len
+  _<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>  <span class="Comment"># skip template</span>
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, result-len
   <span class="Comment"># repeatedly copy sections of template and 'holes' into result</span>
-  result-idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  result-idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while arg received</span>
-    a:address:<span class="Identifier">array</span>:character, <span class="Identifier">arg</span>-received?:boolean<span class="Special"> &lt;- </span>next-ingredient
-    break-unless <span class="Identifier">arg</span>-received?
+    a:address:array:character, arg-received?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+    <span class="muControl">break-unless</span> arg-received?
     <span class="Comment"># copy template into result until '_'</span>
-    {
+    <span class="Delimiter">{</span>
       <span class="Comment"># while i &lt; template.length</span>
       tem-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, tem-len
-      break-if tem-done?, +done:label
+      <span class="muControl">break-if</span> tem-done?, <span class="Constant">+done:label</span>
       <span class="Comment"># while template[i] != '_'</span>
-      <span class="Identifier">in</span>:character<span class="Special"> &lt;- </span>index *template, i
-      underscore?:boolean<span class="Special"> &lt;- </span>equal <span class="Identifier">in</span>, 95/_
-      break-if underscore?
+      in:character<span class="Special"> &lt;- </span>index *template, i
+      underscore?:boolean<span class="Special"> &lt;- </span>equal in, <span class="Constant">95/_</span>
+      <span class="muControl">break-if</span> underscore?
       <span class="Comment"># result[result-idx] = template[i]</span>
       out:address:character<span class="Special"> &lt;- </span>index-address *result, result-idx
-      *out<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-      i<span class="Special"> &lt;- </span>add i, 1
-      result-idx<span class="Special"> &lt;- </span>add result-idx, 1
-      loop
-    }
+      *out<span class="Special"> &lt;- </span>copy in
+      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+      result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># copy 'a' into result</span>
-    j:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    {
+    j:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Delimiter">{</span>
       <span class="Comment"># while j &lt; a.length</span>
-      <span class="Identifier">arg</span>-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal j, a-len
-      break-if <span class="Identifier">arg</span>-done?
+      arg-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal j, a-len
+      <span class="muControl">break-if</span> arg-done?
       <span class="Comment"># result[result-idx] = a[j]</span>
-      <span class="Identifier">in</span>:character<span class="Special"> &lt;- </span>index *a, j
+      in:character<span class="Special"> &lt;- </span>index *a, j
       out:address:character<span class="Special"> &lt;- </span>index-address *result, result-idx
-      *out<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-      j<span class="Special"> &lt;- </span>add j, 1
-      result-idx<span class="Special"> &lt;- </span>add result-idx, 1
-      loop
-    }
+      *out<span class="Special"> &lt;- </span>copy in
+      j<span class="Special"> &lt;- </span>add j, <span class="Constant">1</span>
+      result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># skip '_' in template</span>
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop  <span class="Comment"># interpolate next arg</span>
-  }
-  +done
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>  <span class="Comment"># interpolate next arg</span>
+  <span class="Delimiter">}</span>
+<span class="Constant">  +done</span>
   <span class="Comment"># done with holes; copy rest of template directly into result</span>
-  {
+  <span class="Delimiter">{</span>
     <span class="Comment"># while i &lt; template.length</span>
     tem-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, tem-len
-    break-if tem-done?
+    <span class="muControl">break-if</span> tem-done?
     <span class="Comment"># result[result-idx] = template[i]</span>
-    <span class="Identifier">in</span>:character<span class="Special"> &lt;- </span>index *template, i
+    in:character<span class="Special"> &lt;- </span>index *template, i
     out:address:character<span class="Special"> &lt;- </span>index-address *result, result-idx:number
-    *out<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-    i<span class="Special"> &lt;- </span>add i, 1
-    result-idx<span class="Special"> &lt;- </span>add result-idx, 1
-    loop
-  }
-  reply result
+    *out<span class="Special"> &lt;- </span>copy in
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario <span class="Identifier">interpolate</span>-works [
+<span class="muScenario">scenario</span> interpolate-works [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc _]
-    2:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [def]
-    3:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
-    4:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc _]</span>
+    <span class="Constant">2</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[def]</span>
+    <span class="Constant">3</span>:address:array:character/<span class="Special">raw &lt;- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span>
+    <span class="Constant">4</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    4:string<span class="Special"> &lt;- </span>[abc def]
+    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc def]</span>
   ]
 ]
 
-scenario <span class="Identifier">interpolate</span>-at-start [
+<span class="muScenario">scenario</span> interpolate-at-start [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [_, hello!]
-    2:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    3:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
-    4:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[_, hello!]</span>
+    <span class="Constant">2</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:address:array:character/<span class="Special">raw &lt;- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span>
+    <span class="Constant">4</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    4:string<span class="Special"> &lt;- </span>[abc, hello!]
-    16<span class="Special"> &lt;- </span>0  <span class="Comment"># out of bounds</span>
+    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc, hello!]</span>
+    <span class="Constant">16</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># out of bounds</span>
   ]
 ]
 
-scenario <span class="Identifier">interpolate</span>-at-end [
+<span class="muScenario">scenario</span> interpolate-at-end [
   run [
-    1:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [hello, _]
-    2:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">new</span> [abc]
-    3:address:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">interpolate</span> 1:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>, 2:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
-    4:<span class="Identifier">array</span>:character/<span class="Special">raw &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character/<span class="Special">raw</span>
+    <span class="Constant">1</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[hello, _]</span>
+    <span class="Constant">2</span>:address:array:character/<span class="Special">raw &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:address:array:character/<span class="Special">raw &lt;- </span>interpolate <span class="Constant">1</span>:address:array:character/<span class="Special">raw</span>, <span class="Constant">2</span>:address:array:character/<span class="Special">raw</span>
+    <span class="Constant">4</span>:array:character/<span class="Special">raw &lt;- </span>copy *<span class="Constant">3</span>:address:array:character/<span class="Special">raw</span>
   ]
   memory-should-contain [
-    4:string<span class="Special"> &lt;- </span>[hello, abc]
+    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[hello, abc]</span>
   ]
 ]
 
 <span class="Comment"># result:boolean &lt;- space? c:character</span>
-recipe space? [
-  <span class="Underlined">local</span>-scope
-  c:character<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> space? [
+  <span class="Constant">local-scope</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># most common case first</span>
-  result:boolean<span class="Special"> &lt;- </span>equal c, 32/space
-  jump-if result +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 10/newline
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 9/tab
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 13/carriage-<span class="Identifier">return</span>
-  jump-if result, +reply:label
+  result:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span>
+  <span class="muControl">jump-if</span> result <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">9/tab</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">13/carriage-return</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
   <span class="Comment"># remaining uncommon cases in sorted order</span>
   <span class="Comment"># <a href="http://unicode.org">http://unicode.org</a> code-points in unicode-set Z and Pattern_White_Space</span>
-  result<span class="Special"> &lt;- </span>equal c, 11/ctrl-k
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 12/ctrl-l
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 133/ctrl-0085
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 160/no-break-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 5760/ogham-space-mark
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8192/en-quad
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8193/em-quad
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8194/en-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8195/em-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8196/three-per-em-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8197/four-per-em-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8198/six-per-em-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8199/figure-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8200/punctuation-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8201/thin-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8202/hair-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8206/left-to-right
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8207/right-to-left
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8232/line-separator
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8233/paragraph-separator
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8239/narrow-no-break-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 8287/medium-mathematical-space
-  jump-if result, +reply:label
-  result<span class="Special"> &lt;- </span>equal c, 12288/ideographic-space
-  jump-if result, +reply:label
-  +reply
-  reply result
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">11/ctrl-k</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12/ctrl-l</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">133/ctrl-0085</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">160/no-break-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">5760/ogham-space-mark</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8192/en-quad</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8193/em-quad</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8194/en-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8195/em-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8196/three-per-em-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8197/four-per-em-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8198/six-per-em-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8199/figure-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8200/punctuation-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8201/thin-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8202/hair-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8206/left-to-right</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8207/right-to-left</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8232/line-separator</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8233/paragraph-separator</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8239/narrow-no-break-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8287/medium-mathematical-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+  result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12288/ideographic-space</span>
+  <span class="muControl">jump-if</span> result, <span class="Constant">+reply:label</span>
+<span class="Constant">  +reply</span>
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:address:array:character &lt;- trim s:address:array:character</span>
-recipe trim [
-  <span class="Underlined">local</span>-scope
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
+<span class="muRecipe">recipe</span> trim [
+  <span class="Constant">local-scope</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  len:number<span class="Special"> &lt;- </span>length *s
   <span class="Comment"># left trim: compute start</span>
-  start:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
-    {
+  start:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    <span class="Delimiter">{</span>
       at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal start, len
-      break-unless at-end?
-      result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, 0
-      reply result
-    }
+      <span class="muControl">break-unless</span> at-end?
+      result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">0</span>
+      <span class="muControl">reply</span> result
+    <span class="Delimiter">}</span>
     curr:character<span class="Special"> &lt;- </span>index *s, start
     whitespace?:boolean<span class="Special"> &lt;- </span>space? curr
-    break-unless whitespace?
-    start<span class="Special"> &lt;- </span>add start, 1
-    loop
-  }
+    <span class="muControl">break-unless</span> whitespace?
+    start<span class="Special"> &lt;- </span>add start, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># right trim: compute end</span>
-  end:number<span class="Special"> &lt;- </span>subtract len, 1
-  {
+  end:number<span class="Special"> &lt;- </span>subtract len, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     not-at-start?:boolean<span class="Special"> &lt;- </span>greater-than end, start
-    <span class="Identifier">assert</span> not-at-start?, [end ran up against start]
+    assert not-at-start?, <span class="Constant">[end ran up against start]</span>
     curr:character<span class="Special"> &lt;- </span>index *s, end
     whitespace?:boolean<span class="Special"> &lt;- </span>space? curr
-    break-unless whitespace?
-    end<span class="Special"> &lt;- </span>subtract end, 1
-    loop
-  }
+    <span class="muControl">break-unless</span> whitespace?
+    end<span class="Special"> &lt;- </span>subtract end, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># result = new character[end+1 - start]</span>
-  <span class="Identifier">new</span>-len:number<span class="Special"> &lt;- </span>subtract end, start, -1
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, <span class="Identifier">new</span>-len
+  new-len:number<span class="Special"> &lt;- </span>subtract end, start, <span class="Constant">-1</span>
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, new-len
   <span class="Comment"># copy the untrimmed parts between start and end</span>
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> start
-  j:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  i:number<span class="Special"> &lt;- </span>copy start
+  j:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while i &lt;= end</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-than i, end
-    break-if done?
+    <span class="muControl">break-if</span> done?
     <span class="Comment"># result[j] = s[i]</span>
     src:character<span class="Special"> &lt;- </span>index *s, i
     dest:address:character<span class="Special"> &lt;- </span>index-address *result, j
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> src
-    i<span class="Special"> &lt;- </span>add i, 1
-    j<span class="Special"> &lt;- </span>add j, 1
-    loop
-  }
-  reply result
+    *dest<span class="Special"> &lt;- </span>copy src
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    j<span class="Special"> &lt;- </span>add j, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario trim-unmodified [
+<span class="muScenario">scenario</span> trim-unmodified [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>trim 1:address:<span class="Identifier">array</span>:character
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>trim <span class="Constant">1</span>:address:array:character
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario trim-left [
+<span class="muScenario">scenario</span> trim-left [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [  abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>trim 1:address:<span class="Identifier">array</span>:character
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[  abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>trim <span class="Constant">1</span>:address:array:character
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario trim-right [
+<span class="muScenario">scenario</span> trim-right [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc  ]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>trim 1:address:<span class="Identifier">array</span>:character
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc  ]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>trim <span class="Constant">1</span>:address:array:character
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario trim-left-right [
+<span class="muScenario">scenario</span> trim-left-right [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [  abc   ]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>trim 1:address:<span class="Identifier">array</span>:character
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[  abc   ]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>trim <span class="Constant">1</span>:address:array:character
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario trim-newline-tab [
+<span class="muScenario">scenario</span> trim-newline-tab [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [  abc
-]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>trim 1:address:<span class="Identifier">array</span>:character
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[  abc</span>
+<span class="Constant">]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>trim <span class="Constant">1</span>:address:array:character
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
 <span class="Comment"># next-index:number &lt;- find-next text:address:array:character, pattern:character, idx:number</span>
-recipe find-next [
-  <span class="Underlined">local</span>-scope
-  text:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  pattern:character<span class="Special"> &lt;- </span>next-ingredient
-  idx:number<span class="Special"> &lt;- </span>next-ingredient
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *text
-  {
+<span class="muRecipe">recipe</span> find-next [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  pattern:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  len:number<span class="Special"> &lt;- </span>length *text
+  <span class="Delimiter">{</span>
     eof?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
-    break-if eof?
+    <span class="muControl">break-if</span> eof?
     curr:character<span class="Special"> &lt;- </span>index *text, idx
     found?:boolean<span class="Special"> &lt;- </span>equal curr, pattern
-    break-if found?
-    idx<span class="Special"> &lt;- </span>add idx, 1
-    loop
-  }
-  reply idx
+    <span class="muControl">break-if</span> found?
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> idx
 ]
 
-scenario string-find-next [
+<span class="muScenario">scenario</span> string-find-next [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a/b]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
   ]
 ]
 
-scenario string-find-next-empty [
+<span class="muScenario">scenario</span> string-find-next-empty [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario string-find-next-initial [
+<span class="muScenario">scenario</span> string-find-next-initial [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [/abc]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[/abc]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># prefix match</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># prefix match</span>
   ]
 ]
 
-scenario string-find-next-final [
+<span class="muScenario">scenario</span> string-find-next-final [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc/]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc/]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>3  <span class="Comment"># suffix match</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># suffix match</span>
   ]
 ]
 
-scenario string-find-next-missing [
+<span class="muScenario">scenario</span> string-find-next-missing [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>3  <span class="Comment"># no match</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># no match</span>
   ]
 ]
 
-scenario string-find-next-invalid-index [
+<span class="muScenario">scenario</span> string-find-next-invalid-index [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 4/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">4/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>4  <span class="Comment"># no change</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># no change</span>
   ]
 ]
 
-scenario string-find-next-first [
+<span class="muScenario">scenario</span> string-find-next-first [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [ab/c/]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 0/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab/c/]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>2  <span class="Comment"># first '/' of multiple</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># first '/' of multiple</span>
   ]
 ]
 
-scenario string-find-next-second [
+<span class="muScenario">scenario</span> string-find-next-second [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [ab/c/]
-    2:number<span class="Special"> &lt;- </span>find-next 1:address:<span class="Identifier">array</span>:character, 47/slash, 3/start-index
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab/c/]</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>find-next <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>, <span class="Constant">3/start-index</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>4  <span class="Comment"># second '/' of multiple</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># second '/' of multiple</span>
   ]
 ]
 
 <span class="Comment"># next-index:number &lt;- find-substring text:address:array:character, pattern:address:array:character, idx:number</span>
 <span class="Comment"># like find-next, but searches for multiple characters</span>
 <span class="Comment"># fairly dumb algorithm</span>
-recipe find-<span class="Identifier">substring</span> [
-  <span class="Underlined">local</span>-scope
-  text:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  pattern:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  idx:number<span class="Special"> &lt;- </span>next-ingredient
-  first:character<span class="Special"> &lt;- </span>index *pattern, 0
+<span class="muRecipe">recipe</span> find-substring [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  pattern:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  first:character<span class="Special"> &lt;- </span>index *pattern, <span class="Constant">0</span>
   <span class="Comment"># repeatedly check for match at current idx</span>
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *text
-  {
+  len:number<span class="Special"> &lt;- </span>length *text
+  <span class="Delimiter">{</span>
     <span class="Comment"># does some unnecessary work checking for substrings even when there isn't enough of text left</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
-    break-if done?
-    found?:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at text, pattern, idx
-    break-if found?
-    idx<span class="Special"> &lt;- </span>add idx, 1
+    <span class="muControl">break-if</span> done?
+    found?:boolean<span class="Special"> &lt;- </span>match-at text, pattern, idx
+    <span class="muControl">break-if</span> found?
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
     <span class="Comment"># optimization: skip past indices that definitely won't match</span>
     idx<span class="Special"> &lt;- </span>find-next text, first, idx
-    loop
-  }
-  reply idx
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> idx
 ]
 
-scenario find-<span class="Identifier">substring</span>-1 [
+<span class="muScenario">scenario</span> find-substring-1 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [bc]
-    3:number<span class="Special"> &lt;- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>find-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
   ]
 ]
 
-scenario find-<span class="Identifier">substring</span>-2 [
+<span class="muScenario">scenario</span> find-substring-2 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [bc]
-    3:number<span class="Special"> &lt;- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 1
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>find-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">1</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
   ]
 ]
 
-scenario find-<span class="Identifier">substring</span>-no-<span class="Identifier">match</span> [
+<span class="muScenario">scenario</span> find-substring-no-match [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [bd]
-    3:number<span class="Special"> &lt;- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[bd]</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>find-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>3  <span class="Comment"># not found</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># not found</span>
   ]
 ]
 
-scenario find-<span class="Identifier">substring</span>-suffix-<span class="Identifier">match</span> [
+<span class="muScenario">scenario</span> find-substring-suffix-match [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [cd]
-    3:number<span class="Special"> &lt;- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[cd]</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>find-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>2
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
   ]
 ]
 
-scenario find-<span class="Identifier">substring</span>-suffix-<span class="Identifier">match</span>-2 [
+<span class="muScenario">scenario</span> find-substring-suffix-match-2 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [cde]
-    3:number<span class="Special"> &lt;- </span>find-<span class="Identifier">substring</span> 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[cde]</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>find-substring <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>4  <span class="Comment"># not found</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># not found</span>
   ]
 ]
 
 <span class="Comment"># result:boolean &lt;- match-at text:address:array:character, pattern:address:array:character, idx:number</span>
 <span class="Comment"># checks if substring matches at index 'idx'</span>
-recipe <span class="Identifier">match</span>-at [
-  <span class="Underlined">local</span>-scope
-  text:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  pattern:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  idx:number<span class="Special"> &lt;- </span>next-ingredient
-  pattern-len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *pattern
+<span class="muRecipe">recipe</span> match-at [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  pattern:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  pattern-len:number<span class="Special"> &lt;- </span>length *pattern
   <span class="Comment"># check that there's space left for the pattern</span>
-  {
-    x:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *text
+  <span class="Delimiter">{</span>
+    x:number<span class="Special"> &lt;- </span>length *text
     x<span class="Special"> &lt;- </span>subtract x, pattern-len
     enough-room?:boolean<span class="Special"> &lt;- </span>lesser-or-equal idx, x
-    break-if enough-room?
-    reply 0/not-found
-  }
+    <span class="muControl">break-if</span> enough-room?
+    <span class="muControl">reply</span> <span class="Constant">0/not-found</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># check each character of pattern</span>
-  pattern-idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  pattern-idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal pattern-idx, pattern-len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     c:character<span class="Special"> &lt;- </span>index *text, idx
-    <span class="Identifier">exp</span>:character<span class="Special"> &lt;- </span>index *pattern, pattern-idx
-    {
-      <span class="Identifier">match</span>?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Identifier">exp</span>
-      break-if <span class="Identifier">match</span>?
-      reply 0/not-found
-    }
-    idx<span class="Special"> &lt;- </span>add idx, 1
-    pattern-idx<span class="Special"> &lt;- </span>add pattern-idx, 1
-    loop
-  }
-  reply 1/found
-]
-
-scenario <span class="Identifier">match</span>-at-checks-<span class="Identifier">substring</span>-at-index [
+    exp:character<span class="Special"> &lt;- </span>index *pattern, pattern-idx
+    <span class="Delimiter">{</span>
+      match?:boolean<span class="Special"> &lt;- </span>equal c, exp
+      <span class="muControl">break-if</span> match?
+      <span class="muControl">reply</span> <span class="Constant">0/not-found</span>
+    <span class="Delimiter">}</span>
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    pattern-idx<span class="Special"> &lt;- </span>add pattern-idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">1/found</span>
+]
+
+<span class="muScenario">scenario</span> match-at-checks-substring-at-index [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [ab]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># match found</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># match found</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-reflexive [
+<span class="muScenario">scenario</span> match-at-reflexive [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 1:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># match found</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># match found</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-outside-bounds [
+<span class="muScenario">scenario</span> match-at-outside-bounds [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 4
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">4</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># never matches</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># never matches</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-empty-pattern [
+<span class="muScenario">scenario</span> match-at-empty-pattern [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># always matches empty pattern given a valid index</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># always matches empty pattern given a valid index</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-empty-pattern-outside-bound [
+<span class="muScenario">scenario</span> match-at-empty-pattern-outside-bound [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 4
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">4</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># no match</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no match</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-empty-text [
+<span class="muScenario">scenario</span> match-at-empty-text [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># no match</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no match</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-empty-against-empty [
+<span class="muScenario">scenario</span> match-at-empty-against-empty [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 1:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># matches because pattern is also empty</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># matches because pattern is also empty</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-inside-bounds [
+<span class="muScenario">scenario</span> match-at-inside-bounds [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [bc]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 1
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">1</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># matches inner substring</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># matches inner substring</span>
   ]
 ]
 
-scenario <span class="Identifier">match</span>-at-inside-bounds-2 [
+<span class="muScenario">scenario</span> match-at-inside-bounds-2 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [bc]
-    3:boolean<span class="Special"> &lt;- </span><span class="Identifier">match</span>-at 1:address:<span class="Identifier">array</span>:character, 2:address:<span class="Identifier">array</span>:character, 0
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>match-at <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character, <span class="Constant">0</span>
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># no match</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no match</span>
   ]
 ]
 
 <span class="Comment"># result:address:array:address:array:character &lt;- split s:address:array:character, delim:character</span>
-recipe <span class="Identifier">split</span> [
-  <span class="Underlined">local</span>-scope
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  delim:character<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> split [
+  <span class="Constant">local-scope</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  delim:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># empty string? return empty array</span>
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
-  {
-    empty?:boolean<span class="Special"> &lt;- </span>equal len, 0
-    break-unless empty?
-    result:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 0
-    reply result
-  }
+  len:number<span class="Special"> &lt;- </span>length *s
+  <span class="Delimiter">{</span>
+    empty?:boolean<span class="Special"> &lt;- </span>equal len, <span class="Constant">0</span>
+    <span class="muControl">break-unless</span> empty?
+    result:address:array:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">0</span>
+    <span class="muControl">reply</span> result
+  <span class="Delimiter">}</span>
   <span class="Comment"># count #pieces we need room for</span>
-  count:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1  <span class="Comment"># n delimiters = n+1 pieces</span>
-  idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>  <span class="Comment"># n delimiters = n+1 pieces</span>
+  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     idx<span class="Special"> &lt;- </span>find-next s, delim, idx
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
-    break-if done?
-    idx<span class="Special"> &lt;- </span>add idx, 1
-    count<span class="Special"> &lt;- </span>add count, 1
-    loop
-  }
+    <span class="muControl">break-if</span> done?
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># allocate space</span>
-  result:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, count
+  result:address:array:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, count
   <span class="Comment"># repeatedly copy slices start..end until delimiter into result[curr-result]</span>
-  curr-result:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  start:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  curr-result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  start:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while next delim exists</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal start, len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     end:number<span class="Special"> &lt;- </span>find-next s, delim, start
     <span class="Comment"># copy start..end into result[curr-result]</span>
-    dest:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index-address *result, curr-result
-    *dest<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> s, start, end
+    dest:address:address:array:character<span class="Special"> &lt;- </span>index-address *result, curr-result
+    *dest<span class="Special"> &lt;- </span>string-copy s, start, end
     <span class="Comment"># slide over to next slice</span>
-    start<span class="Special"> &lt;- </span>add end, 1
-    curr-result<span class="Special"> &lt;- </span>add curr-result, 1
-    loop
-  }
-  reply result
+    start<span class="Special"> &lt;- </span>add end, <span class="Constant">1</span>
+    curr-result<span class="Special"> &lt;- </span>add curr-result, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario string-<span class="Identifier">split</span>-1 [
+<span class="muScenario">scenario</span> string-split-1 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a/b]
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash
-    3:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character
-    4:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0
-    5:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1
-    10:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character
-    20:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span>
+    <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> &lt;- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>length *<span class="Constant">2</span>:address:array:address:array:character
+    <span class="Constant">4</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span>
+    <span class="Constant">5</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span>
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:character
+    <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">5</span>:address:array:character
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>2  <span class="Comment"># length of result</span>
-    10:string<span class="Special"> &lt;- </span>[a]
-    20:string<span class="Special"> &lt;- </span>[b]
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># length of result</span>
+    <span class="Constant">10</span>:string<span class="Special"> &lt;- </span><span class="Constant">[a]</span>
+    <span class="Constant">20</span>:string<span class="Special"> &lt;- </span><span class="Constant">[b]</span>
   ]
 ]
 
-scenario string-<span class="Identifier">split</span>-2 [
+<span class="muScenario">scenario</span> string-split-2 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a/b/c]
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash
-    3:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character
-    4:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0
-    5:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1
-    6:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 2
-    10:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character
-    20:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>:character
-    30:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *6:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a/b/c]</span>
+    <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> &lt;- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>length *<span class="Constant">2</span>:address:array:address:array:character
+    <span class="Constant">4</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span>
+    <span class="Constant">5</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span>
+    <span class="Constant">6</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">2</span>
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:character
+    <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">5</span>:address:array:character
+    <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">6</span>:address:array:character
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>3  <span class="Comment"># length of result</span>
-    10:string<span class="Special"> &lt;- </span>[a]
-    20:string<span class="Special"> &lt;- </span>[b]
-    30:string<span class="Special"> &lt;- </span>[c]
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># length of result</span>
+    <span class="Constant">10</span>:string<span class="Special"> &lt;- </span><span class="Constant">[a]</span>
+    <span class="Constant">20</span>:string<span class="Special"> &lt;- </span><span class="Constant">[b]</span>
+    <span class="Constant">30</span>:string<span class="Special"> &lt;- </span><span class="Constant">[c]</span>
   ]
 ]
 
-scenario string-<span class="Identifier">split</span>-missing [
+<span class="muScenario">scenario</span> string-split-missing [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash
-    3:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character
-    4:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0
-    10:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> &lt;- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>length *<span class="Constant">2</span>:address:array:address:array:character
+    <span class="Constant">4</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span>
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:character
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># length of result</span>
-    10:string<span class="Special"> &lt;- </span>[abc]
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># length of result</span>
+    <span class="Constant">10</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
   ]
 ]
 
-scenario string-<span class="Identifier">split</span>-empty [
+<span class="muScenario">scenario</span> string-split-empty [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash
-    3:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> &lt;- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>length *<span class="Constant">2</span>:address:array:address:array:character
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># empty result</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty result</span>
   ]
 ]
 
-scenario string-<span class="Identifier">split</span>-empty-piece [
+<span class="muScenario">scenario</span> string-split-empty-piece [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a/b<span class="Comment">//c]</span>
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span> 1:address:<span class="Identifier">array</span>:character, 47/slash
-    3:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character
-    4:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 0
-    5:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 1
-    6:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 2
-    7:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character, 3
-    10:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:character
-    20:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *5:address:<span class="Identifier">array</span>:character
-    30:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *6:address:<span class="Identifier">array</span>:character
-    40:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *7:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a/b//c]</span>
+    <span class="Constant">2</span>:address:array:address:array:character<span class="Special"> &lt;- </span>split <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>length *<span class="Constant">2</span>:address:array:address:array:character
+    <span class="Constant">4</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">0</span>
+    <span class="Constant">5</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">1</span>
+    <span class="Constant">6</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">2</span>
+    <span class="Constant">7</span>:address:array:character<span class="Special"> &lt;- </span>index *<span class="Constant">2</span>:address:array:address:array:character, <span class="Constant">3</span>
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:character
+    <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">5</span>:address:array:character
+    <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">6</span>:address:array:character
+    <span class="Constant">40</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">7</span>:address:array:character
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>4  <span class="Comment"># length of result</span>
-    10:string<span class="Special"> &lt;- </span>[a]
-    20:string<span class="Special"> &lt;- </span>[b]
-    30:string<span class="Special"> &lt;- </span>[]
-    40:string<span class="Special"> &lt;- </span>[c]
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># length of result</span>
+    <span class="Constant">10</span>:string<span class="Special"> &lt;- </span><span class="Constant">[a]</span>
+    <span class="Constant">20</span>:string<span class="Special"> &lt;- </span><span class="Constant">[b]</span>
+    <span class="Constant">30</span>:string<span class="Special"> &lt;- </span><span class="Constant">[]</span>
+    <span class="Constant">40</span>:string<span class="Special"> &lt;- </span><span class="Constant">[c]</span>
   ]
 ]
 
 <span class="Comment"># x:address:array:character, y:address:array:character &lt;- split-first text:address:array:character, delim:character</span>
-recipe <span class="Identifier">split</span>-first [
-  <span class="Underlined">local</span>-scope
-  text:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  delim:character<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> split-first [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  delim:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># empty string? return empty strings</span>
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *text
-  {
-    empty?:boolean<span class="Special"> &lt;- </span>equal len, 0
-    break-unless empty?
-    x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> []
-    reply x, y
-  }
-  idx:number<span class="Special"> &lt;- </span>find-next text, delim, 0
-  x:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> text, 0, idx
-  idx<span class="Special"> &lt;- </span>add idx, 1
-  y:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> text, idx, len
-  reply x, y
-]
-
-scenario string-<span class="Identifier">split</span>-first [
+  len:number<span class="Special"> &lt;- </span>length *text
+  <span class="Delimiter">{</span>
+    empty?:boolean<span class="Special"> &lt;- </span>equal len, <span class="Constant">0</span>
+    <span class="muControl">break-unless</span> empty?
+    x:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    y:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="muControl">reply</span> x, y
+  <span class="Delimiter">}</span>
+  idx:number<span class="Special"> &lt;- </span>find-next text, delim, <span class="Constant">0</span>
+  x:address:array:character<span class="Special"> &lt;- </span>string-copy text, <span class="Constant">0</span>, idx
+  idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+  y:address:array:character<span class="Special"> &lt;- </span>string-copy text, idx, len
+  <span class="muControl">reply</span> x, y
+]
+
+<span class="muScenario">scenario</span> string-split-first [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [a/b]
-    2:address:<span class="Identifier">array</span>:character, 3:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">split</span>-first 1:address:<span class="Identifier">array</span>:character, 47/slash
-    10:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
-    20:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span>
+    <span class="Constant">2</span>:address:array:character, <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>split-first <span class="Constant">1</span>:address:array:character, <span class="Constant">47/slash</span>
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
+    <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:character
   ]
   memory-should-contain [
-    10:string<span class="Special"> &lt;- </span>[a]
-    20:string<span class="Special"> &lt;- </span>[b]
+    <span class="Constant">10</span>:string<span class="Special"> &lt;- </span><span class="Constant">[a]</span>
+    <span class="Constant">20</span>:string<span class="Special"> &lt;- </span><span class="Constant">[b]</span>
   ]
 ]
 
 <span class="Comment"># result:address:array:character &lt;- string-copy buf:address:array:character, start:number, end:number</span>
 <span class="Comment"># todo: make this generic</span>
-recipe string-<span class="Identifier">copy</span> [
-  <span class="Underlined">local</span>-scope
-  buf:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  start:number<span class="Special"> &lt;- </span>next-ingredient
-  end:number<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> string-copy [
+  <span class="Constant">local-scope</span>
+  buf:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  start:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  end:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if end is out of bounds, trim it</span>
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *buf
-  end:number<span class="Special"> &lt;- </span><span class="Identifier">min</span> len, end
+  len:number<span class="Special"> &lt;- </span>length *buf
+  end:number<span class="Special"> &lt;- </span>min len, end
   <span class="Comment"># allocate space for result</span>
   len<span class="Special"> &lt;- </span>subtract end, start
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, len
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, len
   <span class="Comment"># copy start..end into result[curr-result]</span>
-  src-idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> start
-  dest-idx:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  src-idx:number<span class="Special"> &lt;- </span>copy start
+  dest-idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal src-idx, end
-    break-if done?
+    <span class="muControl">break-if</span> done?
     src:character<span class="Special"> &lt;- </span>index *buf, src-idx
     dest:address:character<span class="Special"> &lt;- </span>index-address *result, dest-idx
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> src
-    src-idx<span class="Special"> &lt;- </span>add src-idx, 1
-    dest-idx<span class="Special"> &lt;- </span>add dest-idx, 1
-    loop
-  }
-  reply result
+    *dest<span class="Special"> &lt;- </span>copy src
+    src-idx<span class="Special"> &lt;- </span>add src-idx, <span class="Constant">1</span>
+    dest-idx<span class="Special"> &lt;- </span>add dest-idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario string-<span class="Identifier">copy</span>-copies-<span class="Identifier">substring</span> [
+<span class="muScenario">scenario</span> string-copy-copies-substring [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 1, 3
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>string-copy <span class="Constant">1</span>:address:array:character, <span class="Constant">1</span>, <span class="Constant">3</span>
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[bc]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[bc]</span>
   ]
 ]
 
-scenario string-<span class="Identifier">copy</span>-out-of-bounds [
+<span class="muScenario">scenario</span> string-copy-out-of-bounds [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 2, 4
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>string-copy <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>, <span class="Constant">4</span>
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[c]
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[c]</span>
   ]
 ]
 
-scenario string-<span class="Identifier">copy</span>-out-of-bounds-2 [
+<span class="muScenario">scenario</span> string-copy-out-of-bounds-2 [
   run [
-    1:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abc]
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> 1:address:<span class="Identifier">array</span>:character, 3, 3
-    3:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:character
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>string-copy <span class="Constant">1</span>:address:array:character, <span class="Constant">3</span>, <span class="Constant">3</span>
+    <span class="Constant">3</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:character
   ]
   memory-should-contain [
-    3:string<span class="Special"> &lt;- </span>[]
-  ]
-]
-
-recipe <span class="Identifier">min</span> [
-  <span class="Underlined">local</span>-scope
-  x:number<span class="Special"> &lt;- </span>next-ingredient
-  y:number<span class="Special"> &lt;- </span>next-ingredient
-  {
-    <span class="Identifier">return</span>-x?:boolean<span class="Special"> &lt;- </span>lesser-than x, y
-    break-if <span class="Identifier">return</span>-x?
-    reply y
-  }
-  reply x
-]
-
-recipe <span class="Identifier">max</span> [
-  <span class="Underlined">local</span>-scope
-  x:number<span class="Special"> &lt;- </span>next-ingredient
-  y:number<span class="Special"> &lt;- </span>next-ingredient
-  {
-    <span class="Identifier">return</span>-x?:boolean<span class="Special"> &lt;- </span>greater-than x, y
-    break-if <span class="Identifier">return</span>-x?
-    reply y
-  }
-  reply x
+    <span class="Constant">3</span>:string<span class="Special"> &lt;- </span><span class="Constant">[]</span>
+  ]
+]
+
+<span class="muRecipe">recipe</span> min [
+  <span class="Constant">local-scope</span>
+  x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    return-x?:boolean<span class="Special"> &lt;- </span>lesser-than x, y
+    <span class="muControl">break-if</span> return-x?
+    <span class="muControl">reply</span> y
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> x
+]
+
+<span class="muRecipe">recipe</span> max [
+  <span class="Constant">local-scope</span>
+  x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    return-x?:boolean<span class="Special"> &lt;- </span>greater-than x, y
+    <span class="muControl">break-if</span> return-x?
+    <span class="muControl">reply</span> y
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> x
 ]
 </pre>
 </body>
diff --git a/html/061channel.mu.html b/html/061channel.mu.html
index 0823083a..a52d34f3 100644
--- a/html/061channel.mu.html
+++ b/html/061channel.mu.html
@@ -13,11 +13,15 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.muData { color: #ffff00; }
 .SalientComment { color: #00ffff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,27 +34,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># Mu synchronizes using channels rather than locks, like Erlang and Go.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># The two ends of a channel will usually belong to different routines, but</span>
 <span class="Comment"># each end should only be used by a single one. Don't try to read from or</span>
 <span class="Comment"># write to it from multiple routines at once.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># The key property of channels is that writing to a full channel or reading</span>
 <span class="Comment"># from an empty one will put the current routine in 'waiting' state until the</span>
 <span class="Comment"># operation can be completed.</span>
 
-scenario channel [
+<span class="muScenario">scenario</span> channel [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:number, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:number, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>34
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">34</span>
   ]
 ]
 
-container channel [
+<span class="muData">container</span> channel [
   <span class="Comment"># To avoid locking, writer and reader will never write to the same location.</span>
   <span class="Comment"># So channels will include fields in pairs, one for the writer and one for the</span>
   <span class="Comment"># reader.</span>
@@ -59,344 +63,344 @@ container channel [
   <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span>
   <span class="Comment"># including) index first-empty. The reader always modifies it at first-full,</span>
   <span class="Comment"># while the writer always modifies it at first-empty.</span>
-  data:address:<span class="Identifier">array</span>:location
+  data:address:array:location
 ]
 
 <span class="Comment"># result:address:channel &lt;- new-channel capacity:number</span>
-recipe <span class="Identifier">new</span>-channel [
-  <span class="Underlined">local</span>-scope
+<span class="muRecipe">recipe</span> new-channel [
+  <span class="Constant">local-scope</span>
   <span class="Comment"># result = new channel</span>
-  result:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span> channel:<span class="Identifier">type</span>
+  result:address:channel<span class="Special"> &lt;- </span>new <span class="Constant">channel:type</span>
   <span class="Comment"># result.first-full = 0</span>
-  full:address:number<span class="Special"> &lt;- </span>get-address *result, first-full:offset
-  *full<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+  full:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">first-full:offset</span>
+  *full<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   <span class="Comment"># result.first-free = 0</span>
-  free:address:number<span class="Special"> &lt;- </span>get-address *result, first-free:offset
-  *free<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+  free:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">first-free:offset</span>
+  *free<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   <span class="Comment"># result.data = new location[ingredient+1]</span>
-  capacity:number<span class="Special"> &lt;- </span>next-ingredient
-  capacity<span class="Special"> &lt;- </span>add capacity, 1  <span class="Comment"># unused slot for 'full?' below</span>
-  dest:address:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get-address *result, data:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, capacity
-  reply result
+  capacity:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  capacity<span class="Special"> &lt;- </span>add capacity, <span class="Constant">1</span>  <span class="Comment"># unused slot for 'full?' below</span>
+  dest:address:address:array:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *dest<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, capacity
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># chan &lt;- write chan:address:channel, val:location</span>
-recipe <span class="Identifier">write</span> [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">val</span>:location<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> write [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  val:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># block if chan is full</span>
     full:boolean<span class="Special"> &lt;- </span>channel-full? chan
-    break-unless full
-    full-address:address:number<span class="Special"> &lt;- </span>get-address *chan, first-full:offset
+    <span class="muControl">break-unless</span> full
+    full-address:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-full:offset</span>
     wait-for-location *full-address
-  }
+  <span class="Delimiter">}</span>
   <span class="Comment"># store val</span>
-  circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
-  free:address:number<span class="Special"> &lt;- </span>get-address *chan, first-free:offset
+  circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span>
+  free:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-free:offset</span>
   dest:address:location<span class="Special"> &lt;- </span>index-address *circular-buffer, *free
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">val</span>
+  *dest<span class="Special"> &lt;- </span>copy val
   <span class="Comment"># mark its slot as filled</span>
-  *free<span class="Special"> &lt;- </span>add *free, 1
-  {
+  *free<span class="Special"> &lt;- </span>add *free, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># wrap free around to 0 if necessary</span>
-    len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *circular-buffer
+    len:number<span class="Special"> &lt;- </span>length *circular-buffer
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal *free, len
-    break-unless at-end?
-    *free<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
-  reply chan/same-as-ingredient:0
+    <span class="muControl">break-unless</span> at-end?
+    *free<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
 <span class="Comment"># result:location, chan &lt;- read chan:address:channel</span>
-recipe <span class="Identifier">read</span> [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> read [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># block if chan is empty</span>
     empty?:boolean<span class="Special"> &lt;- </span>channel-empty? chan
-    break-unless empty?
-    free-address:address:number<span class="Special"> &lt;- </span>get-address *chan, first-free:offset
+    <span class="muControl">break-unless</span> empty?
+    free-address:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-free:offset</span>
     wait-for-location *free-address
-  }
+  <span class="Delimiter">}</span>
   <span class="Comment"># read result</span>
-  full:address:number<span class="Special"> &lt;- </span>get-address *chan, first-full:offset
-  circular-buffer:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
+  full:address:number<span class="Special"> &lt;- </span>get-address *chan, <span class="Constant">first-full:offset</span>
+  circular-buffer:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span>
   result:location<span class="Special"> &lt;- </span>index *circular-buffer, *full
   <span class="Comment"># mark its slot as empty</span>
-  *full<span class="Special"> &lt;- </span>add *full, 1
-  {
+  *full<span class="Special"> &lt;- </span>add *full, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># wrap full around to 0 if necessary</span>
-    len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *circular-buffer
+    len:number<span class="Special"> &lt;- </span>length *circular-buffer
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal *full, len
-    break-unless at-end?
-    *full<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
-  reply result, chan/same-as-ingredient:0
+    <span class="muControl">break-unless</span> at-end?
+    *full<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result, chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe clear-channel [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> clear-channel [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     empty?:boolean<span class="Special"> &lt;- </span>channel-empty? chan
-    break-if empty?
-    _, chan<span class="Special"> &lt;- </span><span class="Identifier">read</span> chan
-  }
-  reply chan/same-as-ingredient:0
+    <span class="muControl">break-if</span> empty?
+    _, chan<span class="Special"> &lt;- </span>read chan
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> chan/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario channel-initialization [
+<span class="muScenario">scenario</span> channel-initialization [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-increments-free [
+<span class="muScenario">scenario</span> channel-write-increments-free [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">read</span>-increments-full [
+<span class="muScenario">scenario</span> channel-read-increments-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># first-full</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-full</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free</span>
   ]
 ]
 
-scenario channel-wrap [
+<span class="muScenario">scenario</span> channel-wrap [
   run [
     <span class="Comment"># channel with just 1 slot</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
     <span class="Comment"># write and read a value</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
     <span class="Comment"># first-free will now be 1</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
     <span class="Comment"># write second value, verify that first-free wraps</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    4:number<span class="Special"> &lt;- </span>get *1:address:channel, first-free:offset
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-free:offset</span>
     <span class="Comment"># read second value, verify that first-full wraps</span>
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    5:number<span class="Special"> &lt;- </span>get *1:address:channel, first-full:offset
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:channel, <span class="Constant">first-full:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># first-free after first write</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># first-full after first read</span>
-    4<span class="Special"> &lt;- </span>0  <span class="Comment"># first-free after second write, wrapped</span>
-    5<span class="Special"> &lt;- </span>0  <span class="Comment"># first-full after second read, wrapped</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-free after first write</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># first-full after first read</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-free after second write, wrapped</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first-full after second read, wrapped</span>
   ]
 ]
 
 <span class="SalientComment">## helpers</span>
 
 <span class="Comment"># An empty channel has first-empty and first-full both at the same value.</span>
-recipe channel-empty? [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> channel-empty? [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># return chan.first-full == chan.first-free</span>
-  full:number<span class="Special"> &lt;- </span>get *chan, first-full:offset
-  free:number<span class="Special"> &lt;- </span>get *chan, first-free:offset
+  full:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-full:offset</span>
+  free:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-free:offset</span>
   result:boolean<span class="Special"> &lt;- </span>equal full, free
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># A full channel has first-empty just before first-full, wasting one slot.</span>
 <span class="Comment"># (Other alternatives: <a href="https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)">https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)</a></span>
-recipe channel-full? [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> channel-full? [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># tmp = chan.first-free + 1</span>
-  tmp:number<span class="Special"> &lt;- </span>get *chan, first-free:offset
-  tmp<span class="Special"> &lt;- </span>add tmp, 1
-  {
+  tmp:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-free:offset</span>
+  tmp<span class="Special"> &lt;- </span>add tmp, <span class="Constant">1</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># if tmp == chan.capacity, tmp = 0</span>
     len:number<span class="Special"> &lt;- </span>channel-capacity chan
     at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal tmp, len
-    break-unless at-end?
-    tmp<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  }
+    <span class="muControl">break-unless</span> at-end?
+    tmp<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># return chan.first-full == tmp</span>
-  full:number<span class="Special"> &lt;- </span>get *chan, first-full:offset
+  full:number<span class="Special"> &lt;- </span>get *chan, <span class="Constant">first-full:offset</span>
   result:boolean<span class="Special"> &lt;- </span>equal full, tmp
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:number &lt;- channel-capacity chan:address:channel</span>
-recipe channel-capacity [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  q:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span>get *chan, data:offset
-  result:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *q
-  reply result
+<span class="muRecipe">recipe</span> channel-capacity [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  q:address:array:location<span class="Special"> &lt;- </span>get *chan, <span class="Constant">data:offset</span>
+  result:number<span class="Special"> &lt;- </span>length *q
+  <span class="muControl">reply</span> result
 ]
 
-scenario channel-<span class="Identifier">new</span>-empty-not-full [
+<span class="muScenario">scenario</span> channel-new-empty-not-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-not-empty [
+<span class="muScenario">scenario</span> channel-write-not-empty [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">write</span>-full [
+<span class="muScenario">scenario</span> channel-write-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># full?</span>
   ]
 ]
 
-scenario channel-<span class="Identifier">read</span>-not-full [
+<span class="muScenario">scenario</span> channel-read-not-full [
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 1/capacity
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 34
-    _, 1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> 1:address:channel
-    2:boolean<span class="Special"> &lt;- </span>channel-empty? 1:address:channel
-    3:boolean<span class="Special"> &lt;- </span>channel-full? 1:address:channel
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">1/capacity</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">34</span>
+    _, <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>read <span class="Constant">1</span>:address:channel
+    <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">1</span>:address:channel
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-full? <span class="Constant">1</span>:address:channel
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># empty?</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># full?</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># empty?</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># full?</span>
   ]
 ]
 
 <span class="Comment"># helper for channels of characters in particular</span>
 <span class="Comment"># out &lt;- buffer-lines in:address:channel, out:address:channel</span>
-recipe buffer-lines [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  out:address:channel<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> buffer-lines [
+  <span class="Constant">local-scope</span>
+  in:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  out:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># repeat forever</span>
-  {
-    line:address:buffer<span class="Special"> &lt;- </span><span class="Identifier">new</span>-buffer, 30
+  <span class="Delimiter">{</span>
+    line:address:buffer<span class="Special"> &lt;- </span>new-buffer, <span class="Constant">30</span>
     <span class="Comment"># read characters from 'in' until newline, copy into line</span>
-    {
-      +next-character
-      c:character, <span class="Identifier">in</span><span class="Special"> &lt;- </span><span class="Identifier">read</span> <span class="Identifier">in</span>
+    <span class="Delimiter">{</span>
+<span class="Constant">      +next-character</span>
+      c:character, in<span class="Special"> &lt;- </span>read in
       <span class="Comment"># drop a character on backspace</span>
-      {
+      <span class="Delimiter">{</span>
         <span class="Comment"># special-case: if it's a backspace</span>
-        backspace?:boolean<span class="Special"> &lt;- </span>equal c, 8
-        break-unless backspace?
+        backspace?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8</span>
+        <span class="muControl">break-unless</span> backspace?
         <span class="Comment"># drop previous character</span>
-        {
-          buffer-<span class="Identifier">length</span>:address:number<span class="Special"> &lt;- </span>get-address *line, <span class="Identifier">length</span>:offset
-          buffer-empty?:boolean<span class="Special"> &lt;- </span>equal *buffer-<span class="Identifier">length</span>, 0
-          break-if buffer-empty?
-          *buffer-<span class="Identifier">length</span><span class="Special"> &lt;- </span>subtract *buffer-<span class="Identifier">length</span>, 1
-        }
+        <span class="Delimiter">{</span>
+          buffer-length:address:number<span class="Special"> &lt;- </span>get-address *line, <span class="Constant">length:offset</span>
+          buffer-empty?:boolean<span class="Special"> &lt;- </span>equal *buffer-length, <span class="Constant">0</span>
+          <span class="muControl">break-if</span> buffer-empty?
+          *buffer-length<span class="Special"> &lt;- </span>subtract *buffer-length, <span class="Constant">1</span>
+        <span class="Delimiter">}</span>
         <span class="Comment"># and don't append this one</span>
-        loop +next-character:label
-      }
+        <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+      <span class="Delimiter">}</span>
       <span class="Comment"># append anything else</span>
-      line<span class="Special"> &lt;- </span>buffer-<span class="Identifier">append</span> line, c
-      line-done?:boolean<span class="Special"> &lt;- </span>equal c, 10/newline
-      break-if line-done?
+      line<span class="Special"> &lt;- </span>buffer-append line, c
+      line-done?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> line-done?
       <span class="Comment"># stop buffering on eof (currently only generated by fake console)</span>
-      eof?:boolean<span class="Special"> &lt;- </span>equal c, 0/eof
-      break-if eof?
-      loop
-    }
+      eof?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">0/eof</span>
+      <span class="muControl">break-if</span> eof?
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># copy line into 'out'</span>
-    i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    line-contents:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *line, data:offset
-    <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span>get *line, <span class="Identifier">length</span>:offset
-    {
-      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, <span class="Identifier">max</span>
-      break-if done?
+    i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    line-contents:address:array:character<span class="Special"> &lt;- </span>get *line, <span class="Constant">data:offset</span>
+    max:number<span class="Special"> &lt;- </span>get *line, <span class="Constant">length:offset</span>
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, max
+      <span class="muControl">break-if</span> done?
       c:character<span class="Special"> &lt;- </span>index *line-contents, i
-      out<span class="Special"> &lt;- </span><span class="Identifier">write</span> out, c
-      i<span class="Special"> &lt;- </span>add i, 1
-      loop
-    }
-    loop
-  }
-  reply out/same-as-ingredient:1
+      out<span class="Special"> &lt;- </span>write out, c
+      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> out/same-as-ingredient:<span class="Constant">1</span>
 ]
 
-scenario buffer-lines-blocks-until-newline [
+<span class="muScenario">scenario</span> buffer-lines-blocks-until-newline [
   run [
-    1:address:channel/stdin<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-    2:address:channel/buffered-stdin<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-    3:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 3:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after init]
+    <span class="Constant">1</span>:address:channel/stdin<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+    <span class="Constant">2</span>:address:channel/buffered-stdin<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">3</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> init]
     <span class="Comment"># buffer stdin into buffered-stdin, try to read from buffered-stdin</span>
-    4:number/buffer-routine<span class="Special"> &lt;- </span>start-running buffer-lines:recipe, 1:address:channel/stdin, 2:address:channel/buffered-stdin
-    wait-for-routine 4:number/buffer-routine
-    5:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 5:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up]
+    <span class="Constant">4</span>:number/buffer-routine<span class="Special"> &lt;- </span>start-running <span class="Constant">buffer-lines:recipe</span>, <span class="Constant">1</span>:address:channel/stdin, <span class="Constant">2</span>:address:channel/buffered-stdin
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">5</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">5</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> buffer-lines bring-up]
     <span class="Comment"># write 'a'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    6:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 6:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">6</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'a']
     <span class="Comment"># write 'b'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 98/b
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    7:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    <span class="Identifier">assert</span> 7:boolean, [
-F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">98/b</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">7</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    assert <span class="Constant">7</span>:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty <span class="muRecipe">after</span> writing 'b']
     <span class="Comment"># write newline</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 10/newline
-    restart 4:number/buffer-routine
-    wait-for-routine 4:number/buffer-routine
-    8:boolean<span class="Special"> &lt;- </span>channel-empty? 2:address:channel/buffered-stdin
-    9:boolean/completed?<span class="Special"> &lt;- </span>not 8:boolean
-    <span class="Identifier">assert</span> 9:boolean/completed?, [
-F buffer-lines-blocks-until-newline: channel should contain data after writing newline]
-    trace 1, [test], [reached end]
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10/newline</span>
+    restart <span class="Constant">4</span>:number/buffer-routine
+    wait-for-routine <span class="Constant">4</span>:number/buffer-routine
+    <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>channel-empty? <span class="Constant">2</span>:address:channel/buffered-stdin
+    <span class="Constant">9</span>:boolean/completed?<span class="Special"> &lt;- </span>not <span class="Constant">8</span>:boolean
+    assert <span class="Constant">9</span>:boolean/completed?, [
+F buffer-lines-blocks-until-newline: channel should contain data <span class="muRecipe">after</span> writing newline]
+    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
   ]
   trace-should-contain [
     test: reached end
diff --git a/html/062array.mu.html b/html/062array.mu.html
index 350f8d6a..b65da102 100644
--- a/html/062array.mu.html
+++ b/html/062array.mu.html
@@ -13,10 +13,13 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Underlined { color: #c000c0; text-decoration: underline; }
+.muScenario { color: #00af00; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -28,45 +31,45 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 </head>
 <body>
 <pre id='vimCodeElement'>
-scenario <span class="Identifier">array</span>-from-<span class="Identifier">args</span> [
+<span class="muScenario">scenario</span> array-from-args [
   run [
-    1:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span>-<span class="Identifier">array</span> 0, 1, 2
-    2:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *1:address:<span class="Identifier">array</span>:location
+    <span class="Constant">1</span>:address:array:location<span class="Special"> &lt;- </span>new-array <span class="Constant">0</span>, <span class="Constant">1</span>, <span class="Constant">2</span>
+    <span class="Constant">2</span>:array:location<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:array:location
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>3  <span class="Comment"># array length</span>
-    3<span class="Special"> &lt;- </span>0
-    4<span class="Special"> &lt;- </span>1
-    5<span class="Special"> &lt;- </span>2
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># array length</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
   ]
 ]
 
 <span class="Comment"># create an array out of a list of scalar args</span>
-recipe <span class="Identifier">new</span>-<span class="Identifier">array</span> [
-  <span class="Underlined">local</span>-scope
-  capacity:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+<span class="muRecipe">recipe</span> new-array [
+  <span class="Constant">local-scope</span>
+  capacity:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while read curr-value</span>
-    curr-value:location, exists?:boolean<span class="Special"> &lt;- </span>next-ingredient
-    break-unless exists?
-    capacity<span class="Special"> &lt;- </span>add capacity, 1
-    loop
-  }
-  result:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, capacity
+    curr-value:location, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+    <span class="muControl">break-unless</span> exists?
+    capacity<span class="Special"> &lt;- </span>add capacity, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  result:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, capacity
   rewind-ingredients
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># while read curr-value</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, capacity
-    break-if done?
-    curr-value:location, exists?:boolean<span class="Special"> &lt;- </span>next-ingredient
-    <span class="Identifier">assert</span> exists?, [<span class="Identifier">error</span> <span class="Identifier">in</span> rewinding ingredients to <span class="Identifier">new</span>-<span class="Identifier">array</span>]
+    <span class="muControl">break-if</span> done?
+    curr-value:location, exists?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+    assert exists?, <span class="Constant">[error in rewinding ingredients to new-array]</span>
     tmp:address:location<span class="Special"> &lt;- </span>index-address *result, i
-    *tmp<span class="Special"> &lt;- </span><span class="Identifier">copy</span> curr-value
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop
-  }
-  reply result
+    *tmp<span class="Special"> &lt;- </span>copy curr-value
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 </pre>
 </body>
diff --git a/html/063list.mu.html b/html/063list.mu.html
index 320049a1..a4c4e02e 100644
--- a/html/063list.mu.html
+++ b/html/063list.mu.html
@@ -13,10 +13,13 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -29,62 +32,62 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># A list links up multiple objects together to make them easier to manage.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># Try to make all objects in a single list of the same type, it'll help avoid bugs.</span>
 <span class="Comment"># If you want to store multiple types in a single list, use an exclusive-container.</span>
 
-container list [
+<span class="muData">container</span> list [
   value:location
   next:address:list
 ]
 
 <span class="Comment"># result:address:list &lt;- push x:location, in:address:list</span>
-recipe push [
-  <span class="Underlined">local</span>-scope
-  x:location<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">in</span>:address:list<span class="Special"> &lt;- </span>next-ingredient
-  result:address:list<span class="Special"> &lt;- </span><span class="Identifier">new</span> list:<span class="Identifier">type</span>
-  <span class="Identifier">val</span>:address:location<span class="Special"> &lt;- </span>get-address *result, value:offset
-  *<span class="Identifier">val</span><span class="Special"> &lt;- </span><span class="Identifier">copy</span> x
-  next:address:address:list<span class="Special"> &lt;- </span>get-address *result, next:offset
-  *next<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-  reply result
+<span class="muRecipe">recipe</span> push [
+  <span class="Constant">local-scope</span>
+  x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:address:list<span class="Special"> &lt;- </span>new <span class="Constant">list:type</span>
+  val:address:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span>
+  *val<span class="Special"> &lt;- </span>copy x
+  next:address:address:list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span>
+  *next<span class="Special"> &lt;- </span>copy in
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:location &lt;- first in:address:list</span>
-recipe first [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:list<span class="Special"> &lt;- </span>next-ingredient
-  result:location<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, value:offset
-  reply result
+<span class="muRecipe">recipe</span> first [
+  <span class="Constant">local-scope</span>
+  in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:location<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span>
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:address:list &lt;- rest in:address:list</span>
-recipe rest [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:list<span class="Special"> &lt;- </span>next-ingredient
-  result:address:list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, next:offset
-  reply result
+<span class="muRecipe">recipe</span> rest [
+  <span class="Constant">local-scope</span>
+  in:address:list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:address:list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario list-handling [
+<span class="muScenario">scenario</span> list-handling [
   run [
-    1:address:list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    1:address:list<span class="Special"> &lt;- </span>push 3, 1:address:list
-    1:address:list<span class="Special"> &lt;- </span>push 4, 1:address:list
-    1:address:list<span class="Special"> &lt;- </span>push 5, 1:address:list
-    2:number<span class="Special"> &lt;- </span>first 1:address:list
-    1:address:list<span class="Special"> &lt;- </span>rest 1:address:list
-    3:number<span class="Special"> &lt;- </span>first 1:address:list
-    1:address:list<span class="Special"> &lt;- </span>rest 1:address:list
-    4:number<span class="Special"> &lt;- </span>first 1:address:list
-    1:address:list<span class="Special"> &lt;- </span>rest 1:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">3</span>, <span class="Constant">1</span>:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">4</span>, <span class="Constant">1</span>:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>push <span class="Constant">5</span>, <span class="Constant">1</span>:address:list
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first <span class="Constant">1</span>:address:list
+    <span class="Constant">1</span>:address:list<span class="Special"> &lt;- </span>rest <span class="Constant">1</span>:address:list
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>0  <span class="Comment"># empty to empty, dust to dust..</span>
-    2<span class="Special"> &lt;- </span>5
-    3<span class="Special"> &lt;- </span>4
-    4<span class="Special"> &lt;- </span>3
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># empty to empty, dust to dust..</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
   ]
 ]
 </pre>
diff --git a/html/065duplex_list.mu.html b/html/065duplex_list.mu.html
index a0744bef..bf7634a0 100644
--- a/html/065duplex_list.mu.html
+++ b/html/065duplex_list.mu.html
@@ -13,10 +13,14 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,370 +34,370 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># A doubly linked list permits bidirectional traversal.</span>
 
-container duplex-list [
+<span class="muData">container</span> duplex-list [
   value:location
   next:address:duplex-list
   prev:address:duplex-list
 ]
 
 <span class="Comment"># result:address:duplex-list &lt;- push-duplex x:location, in:address:duplex-list</span>
-recipe push-duplex [
-  <span class="Underlined">local</span>-scope
-  x:location<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  result:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">new</span> duplex-list:<span class="Identifier">type</span>
-  <span class="Identifier">val</span>:address:location<span class="Special"> &lt;- </span>get-address *result, value:offset
-  *<span class="Identifier">val</span><span class="Special"> &lt;- </span><span class="Identifier">copy</span> x
-  next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, next:offset
-  *next<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-  reply-unless <span class="Identifier">in</span>, result
-  prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, prev:offset
-  *prev<span class="Special"> &lt;- </span><span class="Identifier">copy</span> result
-  reply result
+<span class="muRecipe">recipe</span> push-duplex [
+  <span class="Constant">local-scope</span>
+  x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>new <span class="Constant">duplex-list:type</span>
+  val:address:location<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">value:offset</span>
+  *val<span class="Special"> &lt;- </span>copy x
+  next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">next:offset</span>
+  *next<span class="Special"> &lt;- </span>copy in
+  <span class="muControl">reply-unless</span> in, result
+  prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">prev:offset</span>
+  *prev<span class="Special"> &lt;- </span>copy result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:location &lt;- first-duplex in:address:duplex-list</span>
-recipe first-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless <span class="Identifier">in</span>, 0
-  result:location<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, value:offset
-  reply result
+<span class="muRecipe">recipe</span> first-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> in, <span class="Constant">0</span>
+  result:location<span class="Special"> &lt;- </span>get *in, <span class="Constant">value:offset</span>
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:address:duplex-list &lt;- next-duplex in:address:duplex-list</span>
-recipe next-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless <span class="Identifier">in</span>, 0
-  result:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, next:offset
-  reply result
+<span class="muRecipe">recipe</span> next-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> in, <span class="Constant">0</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span>
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># result:address:duplex-list &lt;- prev-duplex in:address:duplex-list</span>
-recipe prev-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless <span class="Identifier">in</span>, 0
-  result:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, prev:offset
-  reply result
+<span class="muRecipe">recipe</span> prev-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> in, <span class="Constant">0</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span>
+  <span class="muControl">reply</span> result
 ]
 
-scenario duplex-list-handling [
+<span class="muScenario">scenario</span> duplex-list-handling [
   run [
     <span class="Comment"># reserve locations 0, 1 and 2 to check for missing null check</span>
-    1:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 34
-    2:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 35
-    3:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    3:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 3:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 3:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 3:address:duplex-list
-    4:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 3:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 4:address:duplex-list
-    4:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 4:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>first-duplex 4:address:duplex-list
-    4:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 4:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 4:address:duplex-list
-    8:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 4:address:duplex-list
-    9:number<span class="Special"> &lt;- </span>first-duplex 8:address:duplex-list
-    10:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 8:address:duplex-list
-    11:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 8:address:duplex-list
-    4:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 4:address:duplex-list
-    12:number<span class="Special"> &lt;- </span>first-duplex 4:address:duplex-list
-    4:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 4:address:duplex-list
-    13:number<span class="Special"> &lt;- </span>first-duplex 4:address:duplex-list
-    14:boolean<span class="Special"> &lt;- </span>equal 3:address:duplex-list, 4:address:duplex-list
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">8</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">8</span>:address:duplex-list
+    <span class="Constant">10</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">8</span>:address:duplex-list
+    <span class="Constant">11</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">8</span>:address:duplex-list
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">4</span>:address:duplex-list
+    <span class="Constant">14</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:address:duplex-list, <span class="Constant">4</span>:address:duplex-list
   ]
   memory-should-contain [
-    0<span class="Special"> &lt;- </span>0  <span class="Comment"># no modifications to null pointers</span>
-    1<span class="Special"> &lt;- </span>34
-    2<span class="Special"> &lt;- </span>35
-    5<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next</span>
-    6<span class="Special"> &lt;- </span>4
-    7<span class="Special"> &lt;- </span>3
-    8<span class="Special"> &lt;- </span>0  <span class="Comment"># null</span>
-    9<span class="Special"> &lt;- </span>0  <span class="Comment"># first of null</span>
-    10<span class="Special"> &lt;- </span>0  <span class="Comment"># next of null</span>
-    11<span class="Special"> &lt;- </span>0  <span class="Comment"># prev of null</span>
-    12<span class="Special"> &lt;- </span>4  <span class="Comment"># then start scanning prev</span>
-    13<span class="Special"> &lt;- </span>5
-    14<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">0</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no modifications to null pointers</span>
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">34</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">35</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># null</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># first of null</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># next of null</span>
+    <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># prev of null</span>
+    <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># then start scanning prev</span>
+    <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+    <span class="Constant">14</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
 <span class="Comment"># l:address:duplex-list &lt;- insert-duplex x:location, in:address:duplex-list</span>
 <span class="Comment"># Inserts 'x' after 'in'. Returns some pointer into the list.</span>
-recipe insert-duplex [
-  <span class="Underlined">local</span>-scope
-  x:location<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">new</span>-node:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">new</span> duplex-list:<span class="Identifier">type</span>
-  <span class="Identifier">val</span>:address:location<span class="Special"> &lt;- </span>get-address *<span class="Identifier">new</span>-node, value:offset
-  *<span class="Identifier">val</span><span class="Special"> &lt;- </span><span class="Identifier">copy</span> x
-  next-node:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, next:offset
+<span class="muRecipe">recipe</span> insert-duplex [
+  <span class="Constant">local-scope</span>
+  x:location<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  new-node:address:duplex-list<span class="Special"> &lt;- </span>new <span class="Constant">duplex-list:type</span>
+  val:address:location<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">value:offset</span>
+  *val<span class="Special"> &lt;- </span>copy x
+  next-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span>
   <span class="Comment"># in.next = new-node</span>
-  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, next:offset
-  *y<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-node
+  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span>
+  *y<span class="Special"> &lt;- </span>copy new-node
   <span class="Comment"># new-node.prev = in</span>
-  y<span class="Special"> &lt;- </span>get-address *<span class="Identifier">new</span>-node, prev:offset
-  *y<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
+  y<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">prev:offset</span>
+  *y<span class="Special"> &lt;- </span>copy in
   <span class="Comment"># new-node.next = next-node</span>
-  y<span class="Special"> &lt;- </span>get-address *<span class="Identifier">new</span>-node, next:offset
-  *y<span class="Special"> &lt;- </span><span class="Identifier">copy</span> next-node
+  y<span class="Special"> &lt;- </span>get-address *new-node, <span class="Constant">next:offset</span>
+  *y<span class="Special"> &lt;- </span>copy next-node
   <span class="Comment"># if next-node is not null</span>
-  reply-unless next-node, <span class="Identifier">new</span>-node
+  <span class="muControl">reply-unless</span> next-node, new-node
   <span class="Comment"># next-node.prev = new-node</span>
-  y<span class="Special"> &lt;- </span>get-address *next-node, prev:offset
-  *y<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-node
-  reply <span class="Identifier">new</span>-node  <span class="Comment"># just signalling something changed; don't rely on the result</span>
+  y<span class="Special"> &lt;- </span>get-address *next-node, <span class="Constant">prev:offset</span>
+  *y<span class="Special"> &lt;- </span>copy new-node
+  <span class="muControl">reply</span> new-node  <span class="Comment"># just signalling something changed; don't rely on the result</span>
 ]
 
-scenario inserting-into-duplex-list [
+<span class="muScenario">scenario</span> inserting-into-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list  <span class="Comment"># 2 points inside list</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex 6, 2:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list  <span class="Comment"># 2 points inside list</span>
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    3:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    8:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    9:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    10:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next</span>
-    4<span class="Special"> &lt;- </span>4
-    5<span class="Special"> &lt;- </span>6  <span class="Comment"># inserted element</span>
-    6<span class="Special"> &lt;- </span>3
-    7<span class="Special"> &lt;- </span>6  <span class="Comment"># then prev</span>
-    8<span class="Special"> &lt;- </span>4
-    9<span class="Special"> &lt;- </span>5
-    10<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># inserted element</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># then prev</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
-scenario inserting-at-end-of-duplex-list [
+<span class="muScenario">scenario</span> inserting-at-end-of-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list  <span class="Comment"># 2 points inside list</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list  <span class="Comment"># now at end of list</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex 6, 2:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list  <span class="Comment"># 2 points inside list</span>
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list  <span class="Comment"># now at end of list</span>
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">2</span>:address:duplex-list
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    3:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    8:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    9:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    10:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next</span>
-    4<span class="Special"> &lt;- </span>4
-    5<span class="Special"> &lt;- </span>3
-    6<span class="Special"> &lt;- </span>6  <span class="Comment"># inserted element</span>
-    7<span class="Special"> &lt;- </span>3  <span class="Comment"># then prev</span>
-    8<span class="Special"> &lt;- </span>4
-    9<span class="Special"> &lt;- </span>5
-    10<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># inserted element</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># then prev</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
-scenario inserting-after-start-of-duplex-list [
+<span class="muScenario">scenario</span> inserting-after-start-of-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex 6, 1:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>insert-duplex <span class="Constant">6</span>, <span class="Constant">1</span>:address:duplex-list
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    3:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    8:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    9:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    10:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">9</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">10</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next</span>
-    4<span class="Special"> &lt;- </span>6  <span class="Comment"># inserted element</span>
-    5<span class="Special"> &lt;- </span>4
-    6<span class="Special"> &lt;- </span>3
-    7<span class="Special"> &lt;- </span>4  <span class="Comment"># then prev</span>
-    8<span class="Special"> &lt;- </span>6
-    9<span class="Special"> &lt;- </span>5
-    10<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># inserted element</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># then prev</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">6</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
 <span class="Comment"># l:address:duplex-list &lt;- remove-duplex in:address:duplex-list</span>
 <span class="Comment"># Removes 'in' from its surrounding list. Returns some valid pointer into the</span>
 <span class="Comment"># rest of the list.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># Returns null if and only if list is empty. Beware: in that case any pointers</span>
 <span class="Comment"># to the head are now invalid.</span>
-recipe remove-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> remove-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if 'in' is null, return</span>
-  reply-unless <span class="Identifier">in</span>, <span class="Identifier">in</span>
-  next-node:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, next:offset
-  prev-node:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, prev:offset
+  <span class="muControl">reply-unless</span> in, in
+  next-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">next:offset</span>
+  prev-node:address:duplex-list<span class="Special"> &lt;- </span>get *in, <span class="Constant">prev:offset</span>
   <span class="Comment"># null in's pointers</span>
-  x:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, next:offset
-  *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  x<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, prev:offset
-  *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+  x:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span>
+  *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  x<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">prev:offset</span>
+  *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># if next-node is not null</span>
-    break-unless next-node
+    <span class="muControl">break-unless</span> next-node
     <span class="Comment"># next-node.prev = prev-node</span>
-    x<span class="Special"> &lt;- </span>get-address *next-node, prev:offset
-    *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> prev-node
-  }
-  {
+    x<span class="Special"> &lt;- </span>get-address *next-node, <span class="Constant">prev:offset</span>
+    *x<span class="Special"> &lt;- </span>copy prev-node
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># if prev-node is not null</span>
-    break-unless prev-node
+    <span class="muControl">break-unless</span> prev-node
     <span class="Comment"># prev-node.next = next-node</span>
-    x<span class="Special"> &lt;- </span>get-address *prev-node, next:offset
-    *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> next-node
-    reply prev-node
-  }
-  reply next-node
+    x<span class="Special"> &lt;- </span>get-address *prev-node, <span class="Constant">next:offset</span>
+    *x<span class="Special"> &lt;- </span>copy next-node
+    <span class="muControl">reply</span> prev-node
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> next-node
 ]
 
-scenario removing-from-duplex-list [
+<span class="muScenario">scenario</span> removing-from-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list  <span class="Comment"># 2 points at second element</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex 2:address:duplex-list
-    3:boolean<span class="Special"> &lt;- </span>equal 2:address:duplex-list, 0
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list  <span class="Comment"># 2 points at second element</span>
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span>
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    6:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    8:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># remove returned non-null</span>
-    4<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next, skipping deleted element</span>
-    5<span class="Special"> &lt;- </span>3
-    6<span class="Special"> &lt;- </span>0  <span class="Comment"># no more elements</span>
-    7<span class="Special"> &lt;- </span>5  <span class="Comment"># prev of final element</span>
-    8<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># remove returned non-null</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next, skipping deleted element</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no more elements</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># prev of final element</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
-scenario removing-from-start-of-duplex-list [
+<span class="muScenario">scenario</span> removing-from-start-of-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
     <span class="Comment"># removing from head? return value matters.</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex 1:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    3:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    5:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    7:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>4  <span class="Comment"># scanning next, skipping deleted element</span>
-    4<span class="Special"> &lt;- </span>3
-    5<span class="Special"> &lt;- </span>0  <span class="Comment"># no more elements</span>
-    6<span class="Special"> &lt;- </span>4  <span class="Comment"># prev of final element</span>
-    7<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># scanning next, skipping deleted element</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no more elements</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># prev of final element</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
-scenario removing-from-end-of-duplex-list [
+<span class="muScenario">scenario</span> removing-from-end-of-duplex-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to head of list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 4, 1:address:duplex-list
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 5, 1:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to head of list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">4</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">5</span>, <span class="Constant">1</span>:address:duplex-list
     <span class="Comment"># delete last element</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex 2:address:duplex-list
-    3:boolean<span class="Special"> &lt;- </span>equal 2:address:duplex-list, 0
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">3</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span>
     <span class="Comment"># check structure like before</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1:address:duplex-list
-    4:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    5:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    6:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex 2:address:duplex-list
-    7:number<span class="Special"> &lt;- </span>first-duplex 2:address:duplex-list
-    8:boolean<span class="Special"> &lt;- </span>equal 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">6</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>first-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># remove returned non-null</span>
-    4<span class="Special"> &lt;- </span>5  <span class="Comment"># scanning next, skipping deleted element</span>
-    5<span class="Special"> &lt;- </span>4
-    6<span class="Special"> &lt;- </span>0  <span class="Comment"># no more elements</span>
-    7<span class="Special"> &lt;- </span>5  <span class="Comment"># prev of final element</span>
-    8<span class="Special"> &lt;- </span>1  <span class="Comment"># list back at start</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># remove returned non-null</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># scanning next, skipping deleted element</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># no more elements</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">5</span>  <span class="Comment"># prev of final element</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># list back at start</span>
   ]
 ]
 
-scenario removing-from-singleton-list [
+<span class="muScenario">scenario</span> removing-from-singleton-list [
   run [
-    1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to singleton list</span>
-    1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 3, 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex 1:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>get *1:address:duplex-list, next:offset
-    4:address:duplex-list<span class="Special"> &lt;- </span>get *1:address:duplex-list, prev:offset
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to singleton list</span>
+    <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">3</span>, <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>remove-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">next:offset</span>
+    <span class="Constant">4</span>:address:duplex-list<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">prev:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># remove returned null</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># removed node is also detached</span>
-    4<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># remove returned null</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># removed node is also detached</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
@@ -401,193 +405,193 @@ scenario removing-from-singleton-list [
 <span class="Comment"># Remove values between 'start' and 'end' (both exclusive). Returns some valid</span>
 <span class="Comment"># pointer into the rest of the list.</span>
 <span class="Comment"># Also clear pointers back out from start/end for hygiene.</span>
-recipe remove-duplex-between [
-  <span class="Underlined">local</span>-scope
-  start:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  end:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless start, start
+<span class="muRecipe">recipe</span> remove-duplex-between [
+  <span class="Constant">local-scope</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  end:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> start, start
   <span class="Comment"># start-&gt;next-&gt;prev = 0</span>
   <span class="Comment"># start-&gt;next = end</span>
-  next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *start, next:offset
-  nothing-to-<span class="Identifier">delete</span>?:boolean<span class="Special"> &lt;- </span>equal *next, end
-  reply-if nothing-to-<span class="Identifier">delete</span>?, start
-  prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address **next, prev:offset
-  *prev<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  *next<span class="Special"> &lt;- </span><span class="Identifier">copy</span> end
-  reply-unless end, start
+  next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">next:offset</span>
+  nothing-to-delete?:boolean<span class="Special"> &lt;- </span>equal *next, end
+  <span class="muControl">reply-if</span> nothing-to-delete?, start
+  prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address **next, <span class="Constant">prev:offset</span>
+  *prev<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  *next<span class="Special"> &lt;- </span>copy end
+  <span class="muControl">reply-unless</span> end, start
   <span class="Comment"># end-&gt;prev-&gt;next = 0</span>
   <span class="Comment"># end-&gt;prev = start</span>
-  prev<span class="Special"> &lt;- </span>get-address *end, prev:offset
-  next<span class="Special"> &lt;- </span>get-address **prev, next:offset
-  *next<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  *prev<span class="Special"> &lt;- </span><span class="Identifier">copy</span> start
-  reply start
+  prev<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">prev:offset</span>
+  next<span class="Special"> &lt;- </span>get-address **prev, <span class="Constant">next:offset</span>
+  *next<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  *prev<span class="Special"> &lt;- </span>copy start
+  <span class="muControl">reply</span> start
 ]
 
-scenario remove-range [
+<span class="muScenario">scenario</span> remove-range [
   <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to singleton list</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 18, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 17, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 16, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 15, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 14, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 13, 1:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to singleton list</span>
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list
   run [
     <span class="Comment"># delete 16 onwards</span>
     <span class="Comment"># first pointer: to the third element</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    remove-duplex-between 2:address:duplex-list, 0
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    remove-duplex-between <span class="Constant">2</span>:address:duplex-list, <span class="Constant">0</span>
     <span class="Comment"># now check the list</span>
-    4:number<span class="Special"> &lt;- </span>get *1:address:duplex-list, value:offset
-    5:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>get *5:address:duplex-list, value:offset
-    7:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 5:address:duplex-list
-    8:number<span class="Special"> &lt;- </span>get *7:address:duplex-list, value:offset
-    9:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 7:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list
+    <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">9</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list
   ]
   memory-should-contain [
-    4<span class="Special"> &lt;- </span>13
-    6<span class="Special"> &lt;- </span>14
-    8<span class="Special"> &lt;- </span>15
-    9<span class="Special"> &lt;- </span>0
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">14</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">15</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario remove-range-to-end [
+<span class="muScenario">scenario</span> remove-range-to-end [
   <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to singleton list</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 18, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 17, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 16, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 15, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 14, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 13, 1:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to singleton list</span>
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">18</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">17</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">16</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">15</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list
   run [
     <span class="Comment"># delete 15, 16 and 17</span>
     <span class="Comment"># first pointer: to the third element</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
     <span class="Comment"># second pointer: to the fifth element</span>
-    3:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 2:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 3:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 3:address:duplex-list
-    3:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 3:address:duplex-list
-    remove-duplex-between 2:address:duplex-list, 3:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">2</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list
+    <span class="Constant">3</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">3</span>:address:duplex-list
+    remove-duplex-between <span class="Constant">2</span>:address:duplex-list, <span class="Constant">3</span>:address:duplex-list
     <span class="Comment"># now check the list</span>
-    4:number<span class="Special"> &lt;- </span>get *1:address:duplex-list, value:offset
-    5:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>get *5:address:duplex-list, value:offset
-    7:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 5:address:duplex-list
-    8:number<span class="Special"> &lt;- </span>get *7:address:duplex-list, value:offset
-    9:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 7:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list
+    <span class="Constant">8</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">7</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">9</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">7</span>:address:duplex-list
   ]
   memory-should-contain [
-    4<span class="Special"> &lt;- </span>13
-    6<span class="Special"> &lt;- </span>14
-    8<span class="Special"> &lt;- </span>18
-    9<span class="Special"> &lt;- </span>0
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">14</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">18</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario remove-range-empty [
+<span class="muScenario">scenario</span> remove-range-empty [
   <span class="Comment"># construct a duplex list with six elements [13, 14, 15, 16, 17, 18]</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0  <span class="Comment"># 1 points to singleton list</span>
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 14, 1:address:duplex-list
-  1:address:duplex-list<span class="Special"> &lt;- </span>push-duplex 13, 1:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># 1 points to singleton list</span>
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">14</span>, <span class="Constant">1</span>:address:duplex-list
+  <span class="Constant">1</span>:address:duplex-list<span class="Special"> &lt;- </span>push-duplex <span class="Constant">13</span>, <span class="Constant">1</span>:address:duplex-list
   run [
     <span class="Comment"># delete 16 onwards</span>
     <span class="Comment"># first pointer: to the third element</span>
-    2:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    remove-duplex-between 1:address:duplex-list, 2:address:duplex-list
+    <span class="Constant">2</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    remove-duplex-between <span class="Constant">1</span>:address:duplex-list, <span class="Constant">2</span>:address:duplex-list
     <span class="Comment"># now check the list</span>
-    4:number<span class="Special"> &lt;- </span>get *1:address:duplex-list, value:offset
-    5:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 1:address:duplex-list
-    6:number<span class="Special"> &lt;- </span>get *5:address:duplex-list, value:offset
-    7:address:duplex-list<span class="Special"> &lt;- </span>next-duplex 5:address:duplex-list
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">5</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">1</span>:address:duplex-list
+    <span class="Constant">6</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">5</span>:address:duplex-list, <span class="Constant">value:offset</span>
+    <span class="Constant">7</span>:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Constant">5</span>:address:duplex-list
   ]
   memory-should-contain [
-    4<span class="Special"> &lt;- </span>13
-    6<span class="Special"> &lt;- </span>14
-    7<span class="Special"> &lt;- </span>0
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">13</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">14</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
 <span class="Comment"># l:address:duplex-list &lt;- insert-duplex-range in:address:duplex-list, new:address:duplex-list</span>
 <span class="Comment"># Inserts list beginning at 'new' after 'in'. Returns some pointer into the list.</span>
-recipe insert-duplex-range [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  start:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless <span class="Identifier">in</span>, <span class="Identifier">in</span>
-  reply-unless start, <span class="Identifier">in</span>
-  end:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> start
-  {
+<span class="muRecipe">recipe</span> insert-duplex-range [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> in, in
+  <span class="muControl">reply-unless</span> start, in
+  end:address:duplex-list<span class="Special"> &lt;- </span>copy start
+  <span class="Delimiter">{</span>
     next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex end
-    break-unless next
-    end<span class="Special"> &lt;- </span><span class="Identifier">copy</span> next
-    loop
-  }
-  next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex <span class="Identifier">in</span>
-  dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *end, next:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> next
-  {
-    break-unless next
-    dest<span class="Special"> &lt;- </span>get-address *next, prev:offset
-    *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> end
-  }
-  dest<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, next:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> start
-  dest<span class="Special"> &lt;- </span>get-address *start, prev:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-  reply <span class="Identifier">in</span>
+    <span class="muControl">break-unless</span> next
+    end<span class="Special"> &lt;- </span>copy next
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex in
+  dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">next:offset</span>
+  *dest<span class="Special"> &lt;- </span>copy next
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> next
+    dest<span class="Special"> &lt;- </span>get-address *next, <span class="Constant">prev:offset</span>
+    *dest<span class="Special"> &lt;- </span>copy end
+  <span class="Delimiter">}</span>
+  dest<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">next:offset</span>
+  *dest<span class="Special"> &lt;- </span>copy start
+  dest<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">prev:offset</span>
+  *dest<span class="Special"> &lt;- </span>copy in
+  <span class="muControl">reply</span> in
 ]
 
-recipe <span class="Identifier">append</span>-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">new</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">last</span>:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">last</span>-duplex <span class="Identifier">in</span>
-  dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *<span class="Identifier">last</span>, next:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>
-  reply-unless <span class="Identifier">new</span>, <span class="Identifier">in</span>/same-as-ingredient:0
-  dest<span class="Special"> &lt;- </span>get-address *<span class="Identifier">new</span>, prev:offset
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">last</span>
-  reply <span class="Identifier">in</span>/same-as-ingredient:0
+<span class="muRecipe">recipe</span> append-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  new:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  last:address:duplex-list<span class="Special"> &lt;- </span>last-duplex in
+  dest:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *last, <span class="Constant">next:offset</span>
+  *dest<span class="Special"> &lt;- </span>copy new
+  <span class="muControl">reply-unless</span> new, in/same-as-ingredient:<span class="Constant">0</span>
+  dest<span class="Special"> &lt;- </span>get-address *new, <span class="Constant">prev:offset</span>
+  *dest<span class="Special"> &lt;- </span>copy last
+  <span class="muControl">reply</span> in/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe <span class="Identifier">last</span>-duplex [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  result:address:duplex-list<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">in</span>
-  {
+<span class="muRecipe">recipe</span> last-duplex [
+  <span class="Constant">local-scope</span>
+  in:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>copy in
+  <span class="Delimiter">{</span>
     next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex result
-    break-unless next
-    result<span class="Special"> &lt;- </span><span class="Identifier">copy</span> next
-    loop
-  }
-  reply result
+    <span class="muControl">break-unless</span> next
+    result<span class="Special"> &lt;- </span>copy next
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># helper for debugging</span>
-recipe dump-duplex-from [
-  <span class="Underlined">local</span>-scope
-  x:address:duplex-list<span class="Special"> &lt;- </span>next-ingredient
-  $<span class="Identifier">print</span> x, [: ]
-  {
-    break-unless x
-    c:character<span class="Special"> &lt;- </span>get *x, value:offset
-    $<span class="Identifier">print</span> c, [ ]
+<span class="muRecipe">recipe</span> dump-duplex-from [
+  <span class="Constant">local-scope</span>
+  x:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  $print x, <span class="Constant">[: ]</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x
+    c:character<span class="Special"> &lt;- </span>get *x, <span class="Constant">value:offset</span>
+    $print c, <span class="Constant">[ ]</span>
     x<span class="Special"> &lt;- </span>next-duplex x
-    {
-      <span class="Identifier">is</span>-newline?:boolean<span class="Special"> &lt;- </span>equal c, 10/newline
-      break-unless <span class="Identifier">is</span>-newline?
-      $<span class="Identifier">print</span> 10/newline
-      $<span class="Identifier">print</span> x, [: ]
-    }
-    loop
-  }
-  $<span class="Identifier">print</span> 10/newline, [---], 10/newline
+    <span class="Delimiter">{</span>
+      is-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> is-newline?
+      $print <span class="Constant">10/newline</span>
+      $print x, <span class="Constant">[: ]</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  $print <span class="Constant">10/newline</span>, <span class="Constant">[---]</span>, <span class="Constant">10/newline</span>
 ]
 </pre>
 </body>
diff --git a/html/066stream.mu.html b/html/066stream.mu.html
index a43f8090..23a019f6 100644
--- a/html/066stream.mu.html
+++ b/html/066stream.mu.html
@@ -13,10 +13,12 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -29,48 +31,48 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># new type to help incrementally read strings</span>
-container stream [
+<span class="muData">container</span> stream [
   index:number
-  data:address:<span class="Identifier">array</span>:character
+  data:address:array:character
 ]
 
-recipe <span class="Identifier">new</span>-stream [
-  <span class="Underlined">local</span>-scope
-  result:address:stream<span class="Special"> &lt;- </span><span class="Identifier">new</span> stream:<span class="Identifier">type</span>
-  i:address:number<span class="Special"> &lt;- </span>get-address *result, index:offset
-  *i<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  d:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get-address *result, data:offset
-  *d<span class="Special"> &lt;- </span>next-ingredient
-  reply result
+<span class="muRecipe">recipe</span> new-stream [
+  <span class="Constant">local-scope</span>
+  result:address:stream<span class="Special"> &lt;- </span>new <span class="Constant">stream:type</span>
+  i:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">index:offset</span>
+  *i<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  d:address:address:array:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *d<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply</span> result
 ]
 
-recipe rewind-stream [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:stream<span class="Special"> &lt;- </span>next-ingredient
-  x:address:number<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, index:offset
-  *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  reply <span class="Identifier">in</span>/same-as-<span class="Identifier">arg</span>:0
+<span class="muRecipe">recipe</span> rewind-stream [
+  <span class="Constant">local-scope</span>
+  in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  x:address:number<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">index:offset</span>
+  *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="muControl">reply</span> in/same-as-arg:<span class="Constant">0</span>
 ]
 
-recipe <span class="Identifier">read</span>-line [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:stream<span class="Special"> &lt;- </span>next-ingredient
-  idx:address:number<span class="Special"> &lt;- </span>get-address *<span class="Identifier">in</span>, index:offset
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, data:offset
-  next-idx:number<span class="Special"> &lt;- </span>find-next s, 10/newline, *idx
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>string-<span class="Identifier">copy</span> s, *idx, next-idx
-  *idx<span class="Special"> &lt;- </span>add next-idx, 1  <span class="Comment"># skip newline</span>
-  reply result
+<span class="muRecipe">recipe</span> read-line [
+  <span class="Constant">local-scope</span>
+  in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:address:number<span class="Special"> &lt;- </span>get-address *in, <span class="Constant">index:offset</span>
+  s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
+  next-idx:number<span class="Special"> &lt;- </span>find-next s, <span class="Constant">10/newline</span>, *idx
+  result:address:array:character<span class="Special"> &lt;- </span>string-copy s, *idx, next-idx
+  *idx<span class="Special"> &lt;- </span>add next-idx, <span class="Constant">1</span>  <span class="Comment"># skip newline</span>
+  <span class="muControl">reply</span> result
 ]
 
-recipe end-of-stream? [
-  <span class="Underlined">local</span>-scope
-  <span class="Identifier">in</span>:address:stream<span class="Special"> &lt;- </span>next-ingredient
-  idx:address:number<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, index:offset
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get *<span class="Identifier">in</span>, data:offset
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
+<span class="muRecipe">recipe</span> end-of-stream? [
+  <span class="Constant">local-scope</span>
+  in:address:stream<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:address:number<span class="Special"> &lt;- </span>get *in, <span class="Constant">index:offset</span>
+  s:address:array:character<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span>
+  len:number<span class="Special"> &lt;- </span>length *s
   result:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
-  reply result
+  <span class="muControl">reply</span> result
 ]
 </pre>
 </body>
diff --git a/html/071print.mu.html b/html/071print.mu.html
index ce70d068..c4334f55 100644
--- a/html/071print.mu.html
+++ b/html/071print.mu.html
@@ -13,10 +13,14 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -31,686 +35,686 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># Wrappers around print primitives that take a 'screen' object and are thus</span>
 <span class="Comment"># easier to test.</span>
 
-container screen [
+<span class="muData">container</span> screen [
   num-rows:number
   num-columns:number
   cursor-row:number
   cursor-column:number
-  data:address:<span class="Identifier">array</span>:screen-cell
+  data:address:array:screen-cell
 ]
 
-container screen-cell [
+<span class="muData">container</span> screen-cell [
   contents:character
   color:number
 ]
 
-recipe <span class="Identifier">new</span>-fake-screen [
-  <span class="Underlined">local</span>-scope
-  result:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span> screen:<span class="Identifier">type</span>
-  width:address:number<span class="Special"> &lt;- </span>get-address *result, num-columns:offset
-  *width<span class="Special"> &lt;- </span>next-ingredient
-  height:address:number<span class="Special"> &lt;- </span>get-address *result, num-rows:offset
-  *height<span class="Special"> &lt;- </span>next-ingredient
-  row:address:number<span class="Special"> &lt;- </span>get-address *result, cursor-row:offset
-  *row<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  column:address:number<span class="Special"> &lt;- </span>get-address *result, cursor-column:offset
-  *column<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+<span class="muRecipe">recipe</span> new-fake-screen [
+  <span class="Constant">local-scope</span>
+  result:address:screen<span class="Special"> &lt;- </span>new <span class="Constant">screen:type</span>
+  width:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">num-columns:offset</span>
+  *width<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  height:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">num-rows:offset</span>
+  *height<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-row:offset</span>
+  *row<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  column:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-column:offset</span>
+  *column<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   bufsize:number<span class="Special"> &lt;- </span>multiply *width, *height
-  buf:address:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get-address *result, data:offset
-  *buf<span class="Special"> &lt;- </span><span class="Identifier">new</span> screen-cell:<span class="Identifier">type</span>, bufsize
+  buf:address:address:array:screen-cell<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *buf<span class="Special"> &lt;- </span>new <span class="Constant">screen-cell:type</span>, bufsize
   clear-screen result
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
-recipe clear-screen [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> clear-screen [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists</span>
-  {
-    break-unless sc
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
     <span class="Comment"># clear fake screen</span>
-    buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *sc, data:offset
-    <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *buf
-    i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    {
-      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, <span class="Identifier">max</span>
-      break-if done?
+    buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *sc, <span class="Constant">data:offset</span>
+    max:number<span class="Special"> &lt;- </span>length *buf
+    i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, max
+      <span class="muControl">break-if</span> done?
       curr:address:screen-cell<span class="Special"> &lt;- </span>index-address *buf, i
-      curr-<span class="Identifier">content</span>:address:character<span class="Special"> &lt;- </span>get-address *curr, contents:offset
-      *curr-<span class="Identifier">content</span><span class="Special"> &lt;- </span><span class="Identifier">copy</span> [ ]
-      curr-color:address:character<span class="Special"> &lt;- </span>get-address *curr, color:offset
-      *curr-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7/white
-      i<span class="Special"> &lt;- </span>add i, 1
-      loop
-    }
+      curr-content:address:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">contents:offset</span>
+      *curr-content<span class="Special"> &lt;- </span>copy <span class="Constant">[ ]</span>
+      curr-color:address:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">color:offset</span>
+      *curr-color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># reset cursor</span>
-    x:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-row:offset
-    *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    x<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-    *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    reply sc/same-as-ingredient:0
-  }
+    x:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-row:offset</span>
+    *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    x<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+    *x<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   clear-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe sync-screen [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
-  {
-    break-if sc
+<span class="muRecipe">recipe</span> sync-screen [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sc
     sync-display
-  }
+  <span class="Delimiter">}</span>
   <span class="Comment"># do nothing for fake screens</span>
 ]
 
-recipe fake-screen-<span class="Identifier">is</span>-empty? [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
-  reply-unless sc, 1/true
-  buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *sc, data:offset
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *buf
-  {
+<span class="muRecipe">recipe</span> fake-screen-is-empty? [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> sc, <span class="Constant">1/true</span>
+  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *sc, <span class="Constant">data:offset</span>
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  len:number<span class="Special"> &lt;- </span>length *buf
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     curr:screen-cell<span class="Special"> &lt;- </span>index *buf, i
-    curr-contents:character<span class="Special"> &lt;- </span>get curr, contents:offset
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop-unless curr-contents
+    curr-contents:character<span class="Special"> &lt;- </span>get curr, <span class="Constant">contents:offset</span>
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop-unless</span> curr-contents
     <span class="Comment"># not 0</span>
-    reply 0/false
-  }
-  reply 1/true
+    <span class="muControl">reply</span> <span class="Constant">0/false</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">1/true</span>
 ]
 
-recipe <span class="Identifier">print</span>-character [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
-  c:character<span class="Special"> &lt;- </span>next-ingredient
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> print-character [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default color to white</span>
-    break-if color-found?
-    color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7/white
-  }
-  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+    <span class="muControl">break-if</span> color-found?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+  <span class="Delimiter">}</span>
+  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default bg-color to black</span>
-    break-if bg-color-found?
-    bg-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0/black
-  }
-  trace 90, [<span class="Identifier">print</span>-character], c
-  {
+    <span class="muControl">break-if</span> bg-color-found?
+    bg-color<span class="Special"> &lt;- </span>copy <span class="Constant">0/black</span>
+  <span class="Delimiter">}</span>
+  trace <span class="Constant">90</span>, <span class="Constant">[print-character]</span>, c
+  <span class="Delimiter">{</span>
     <span class="Comment"># if x exists</span>
     <span class="Comment"># (handle special cases exactly like in the real screen)</span>
-    break-unless sc
-    width:number<span class="Special"> &lt;- </span>get *sc, num-columns:offset
-    height:number<span class="Special"> &lt;- </span>get *sc, num-rows:offset
+    <span class="muControl">break-unless</span> sc
+    width:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-columns:offset</span>
+    height:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-rows:offset</span>
     <span class="Comment"># if cursor is out of bounds, silently exit</span>
-    row:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-row:offset
-    legal?:boolean<span class="Special"> &lt;- </span>greater-or-equal *row, 0
-    reply-unless legal?, sc
+    row:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-row:offset</span>
+    legal?:boolean<span class="Special"> &lt;- </span>greater-or-equal *row, <span class="Constant">0</span>
+    <span class="muControl">reply-unless</span> legal?, sc
     legal?<span class="Special"> &lt;- </span>lesser-than *row, height
-    reply-unless legal?, sc
-    column:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-    legal?<span class="Special"> &lt;- </span>greater-or-equal *column, 0
-    reply-unless legal?, sc
+    <span class="muControl">reply-unless</span> legal?, sc
+    column:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+    legal?<span class="Special"> &lt;- </span>greater-or-equal *column, <span class="Constant">0</span>
+    <span class="muControl">reply-unless</span> legal?, sc
     legal?<span class="Special"> &lt;- </span>lesser-than *column, width
-    reply-unless legal?, sc
+    <span class="muControl">reply-unless</span> legal?, sc
     <span class="Comment"># special-case: newline</span>
-    {
-      newline?:boolean<span class="Special"> &lt;- </span>equal c, 10/newline
-      break-unless newline?
-      {
+    <span class="Delimiter">{</span>
+      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> newline?
+      <span class="Delimiter">{</span>
         <span class="Comment"># unless cursor is already at bottom</span>
-        bottom:number<span class="Special"> &lt;- </span>subtract height, 1
+        bottom:number<span class="Special"> &lt;- </span>subtract height, <span class="Constant">1</span>
         at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *row, bottom
-        break-if at-bottom?
+        <span class="muControl">break-if</span> at-bottom?
         <span class="Comment"># move it to the next row</span>
-        *column<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-        *row<span class="Special"> &lt;- </span>add *row, 1
-      }
-      reply sc/same-as-ingredient:0
-    }
+        *column<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+        *row<span class="Special"> &lt;- </span>add *row, <span class="Constant">1</span>
+      <span class="Delimiter">}</span>
+      <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># save character in fake screen</span>
     index:number<span class="Special"> &lt;- </span>multiply *row, width
     index<span class="Special"> &lt;- </span>add index, *column
-    buf:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *sc, data:offset
-    len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *buf
+    buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *sc, <span class="Constant">data:offset</span>
+    len:number<span class="Special"> &lt;- </span>length *buf
     <span class="Comment"># special-case: backspace</span>
-    {
-      backspace?:boolean<span class="Special"> &lt;- </span>equal c, 8
-      break-unless backspace?
-      {
+    <span class="Delimiter">{</span>
+      backspace?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8</span>
+      <span class="muControl">break-unless</span> backspace?
+      <span class="Delimiter">{</span>
         <span class="Comment"># unless cursor is already at left margin</span>
-        at-left?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *column, 0
-        break-if at-left?
+        at-left?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *column, <span class="Constant">0</span>
+        <span class="muControl">break-if</span> at-left?
         <span class="Comment"># clear previous location</span>
-        *column<span class="Special"> &lt;- </span>subtract *column, 1
-        index<span class="Special"> &lt;- </span>subtract index, 1
+        *column<span class="Special"> &lt;- </span>subtract *column, <span class="Constant">1</span>
+        index<span class="Special"> &lt;- </span>subtract index, <span class="Constant">1</span>
         cursor:address:screen-cell<span class="Special"> &lt;- </span>index-address *buf, index
-        cursor-contents:address:character<span class="Special"> &lt;- </span>get-address *cursor, contents:offset
-        *cursor-contents<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 32/space
-        cursor-color:address:number<span class="Special"> &lt;- </span>get-address *cursor, color:offset
-        *cursor-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7/white
-      }
-      reply sc/same-as-ingredient:0
-    }
+        cursor-contents:address:character<span class="Special"> &lt;- </span>get-address *cursor, <span class="Constant">contents:offset</span>
+        *cursor-contents<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
+        cursor-color:address:number<span class="Special"> &lt;- </span>get-address *cursor, <span class="Constant">color:offset</span>
+        *cursor-color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+      <span class="Delimiter">}</span>
+      <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+    <span class="Delimiter">}</span>
     cursor:address:screen-cell<span class="Special"> &lt;- </span>index-address *buf, index
-    cursor-contents:address:character<span class="Special"> &lt;- </span>get-address *cursor, contents:offset
-    *cursor-contents<span class="Special"> &lt;- </span><span class="Identifier">copy</span> c
-    cursor-color:address:number<span class="Special"> &lt;- </span>get-address *cursor, color:offset
-    *cursor-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> color
+    cursor-contents:address:character<span class="Special"> &lt;- </span>get-address *cursor, <span class="Constant">contents:offset</span>
+    *cursor-contents<span class="Special"> &lt;- </span>copy c
+    cursor-color:address:number<span class="Special"> &lt;- </span>get-address *cursor, <span class="Constant">color:offset</span>
+    *cursor-color<span class="Special"> &lt;- </span>copy color
     <span class="Comment"># increment column unless it's already all the way to the right</span>
-    {
-      right:number<span class="Special"> &lt;- </span>subtract width, 1
+    <span class="Delimiter">{</span>
+      right:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">1</span>
       at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal *column, right
-      break-if at-right?
-      *column<span class="Special"> &lt;- </span>add *column, 1
-    }
-    reply sc/same-as-ingredient:0
-  }
+      <span class="muControl">break-if</span> at-right?
+      *column<span class="Special"> &lt;- </span>add *column, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
-  <span class="Identifier">print</span>-character-to-display c, color, bg-color
-  reply sc/same-as-ingredient:0
+  print-character-to-display c, color, bg-color
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario <span class="Identifier">print</span>-character-at-top-left [
+<span class="muScenario">scenario</span> print-character-at-top-left [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    3:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">3</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    4<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    5<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    6<span class="Special"> &lt;- </span>0
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-character-color [
+<span class="muScenario">scenario</span> print-character-color [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97/a, 1/red
-    2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    3:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97/a</span>, <span class="Constant">1/red</span>
+    <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">3</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    4<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    5<span class="Special"> &lt;- </span>1  <span class="Comment"># red</span>
-    6<span class="Special"> &lt;- </span>0
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># red</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-backspace-character [
+<span class="muScenario">scenario</span> print-backspace-character [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 8  <span class="Comment"># backspace</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
-    3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    4:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span>  <span class="Comment"># backspace</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">4</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
-    4<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    5<span class="Special"> &lt;- </span>32  <span class="Comment"># space, not 'a'</span>
-    6<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    7<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">32</span>  <span class="Comment"># space, not 'a'</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-extra-backspace-character [
+<span class="muScenario">scenario</span> print-extra-backspace-character [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 8  <span class="Comment"># backspace</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 8  <span class="Comment"># backspace</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
-    3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    4:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span>  <span class="Comment"># backspace</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">8</span>  <span class="Comment"># backspace</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">4</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
-    4<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    5<span class="Special"> &lt;- </span>32  <span class="Comment"># space, not 'a'</span>
-    6<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    7<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">32</span>  <span class="Comment"># space, not 'a'</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-at-right-margin [
+<span class="muScenario">scenario</span> print-at-right-margin [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 2/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 98  <span class="Comment"># 'b'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 99  <span class="Comment"># 'c'</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
-    3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    4:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">99</span>  <span class="Comment"># 'c'</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">4</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor column</span>
-    4<span class="Special"> &lt;- </span>4  <span class="Comment"># width*height</span>
-    5<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    6<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    7<span class="Special"> &lt;- </span>99  <span class="Comment"># 'c' over 'b'</span>
-    8<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    9<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor column</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">99</span>  <span class="Comment"># 'c' over 'b'</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-newline-character [
+<span class="muScenario">scenario</span> print-newline-character [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-row:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
-    4:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    5:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">4</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">5</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
-    5<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    6<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    7<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    8<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-newline-at-bottom-line [
+<span class="muScenario">scenario</span> print-newline-at-bottom-line [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-row:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
   ]
 ]
 
-scenario <span class="Identifier">print</span>-at-bottom-right [
+<span class="muScenario">scenario</span> print-at-bottom-right [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 2/width, 2/height
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 98  <span class="Comment"># 'b'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 99  <span class="Comment"># 'c'</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 10/newline
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 100  <span class="Comment"># 'd'</span>
-    2:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-row:offset
-    3:number<span class="Special"> &lt;- </span>get *1:address:screen, cursor-column:offset
-    4:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    5:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *4:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">2/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">99</span>  <span class="Comment"># 'c'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">10/newline</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">100</span>  <span class="Comment"># 'd'</span>
+    <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">4</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">5</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">4</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
-    3<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor column</span>
-    5<span class="Special"> &lt;- </span>4  <span class="Comment"># width*height</span>
-    6<span class="Special"> &lt;- </span>0  <span class="Comment"># unused</span>
-    7<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    8<span class="Special"> &lt;- </span>0  <span class="Comment"># unused</span>
-    9<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    10<span class="Special"> &lt;- </span>97 <span class="Comment"># 'a'</span>
-    11<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    12<span class="Special"> &lt;- </span>100  <span class="Comment"># 'd' over 'b' and 'c' and newline</span>
-    13<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    14<span class="Special"> &lt;- </span>0
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor column</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># unused</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># unused</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span>
+    <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">100</span>  <span class="Comment"># 'd' over 'b' and 'c' and newline</span>
+    <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">14</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
   ]
 ]
 
-recipe clear-line [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> clear-line [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, clear line in fake screen</span>
-  {
-    break-unless sc
-    width:number<span class="Special"> &lt;- </span>get *sc, num-columns:offset
-    column:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-    original-column:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *column
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    width:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-columns:offset</span>
+    column:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+    original-column:number<span class="Special"> &lt;- </span>copy *column
     <span class="Comment"># space over the entire line</span>
-    {
-      right:number<span class="Special"> &lt;- </span>subtract width, 1
+    <span class="Delimiter">{</span>
+      right:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">1</span>
       done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *column, right
-      break-if done?
-      <span class="Identifier">print</span>-character sc, [ ]  <span class="Comment"># implicitly updates 'column'</span>
-      loop
-    }
+      <span class="muControl">break-if</span> done?
+      print-character sc, <span class="Constant">[ ]</span>  <span class="Comment"># implicitly updates 'column'</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
     <span class="Comment"># now back to where the cursor was</span>
-    *column<span class="Special"> &lt;- </span><span class="Identifier">copy</span> original-column
-    reply sc/same-as-ingredient:0
-  }
+    *column<span class="Special"> &lt;- </span>copy original-column
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   clear-line-on-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-position [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-position [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, lookup cursor in fake screen</span>
-  {
-    break-unless sc
-    row:number<span class="Special"> &lt;- </span>get *sc, cursor-row:offset
-    column:number<span class="Special"> &lt;- </span>get *sc, cursor-column:offset
-    reply row, column, sc/same-as-ingredient:0
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    row:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">cursor-row:offset</span>
+    column:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">cursor-column:offset</span>
+    <span class="muControl">reply</span> row, column, sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   row, column<span class="Special"> &lt;- </span>cursor-position-on-display
-  reply row, column, sc/same-as-ingredient:0
+  <span class="muControl">reply</span> row, column, sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe move-cursor [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">new</span>-row:number<span class="Special"> &lt;- </span>next-ingredient
-  <span class="Identifier">new</span>-column:number<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> move-cursor [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  new-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  new-column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    row:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-row:offset
-    *row<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-row
-    column:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-    *column<span class="Special"> &lt;- </span><span class="Identifier">copy</span> <span class="Identifier">new</span>-column
-    reply sc/same-as-ingredient:0
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    row:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-row:offset</span>
+    *row<span class="Special"> &lt;- </span>copy new-row
+    column:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+    *column<span class="Special"> &lt;- </span>copy new-column
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
-  move-cursor-on-display <span class="Identifier">new</span>-row, <span class="Identifier">new</span>-column
-  reply sc/same-as-ingredient:0
+  move-cursor-on-display new-row, new-column
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario clear-line-erases-printed-characters [
+<span class="muScenario">scenario</span> clear-line-erases-printed-characters [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
     <span class="Comment"># print a character</span>
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character 1:address:screen, 97  <span class="Comment"># 'a'</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-character <span class="Constant">1</span>:address:screen, <span class="Constant">97</span>  <span class="Comment"># 'a'</span>
     <span class="Comment"># move cursor to start of line</span>
-    1:address:screen<span class="Special"> &lt;- </span>move-cursor 1:address:screen, 0/row, 0/column
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>move-cursor <span class="Constant">1</span>:address:screen, <span class="Constant">0/row</span>, <span class="Constant">0/column</span>
     <span class="Comment"># clear line</span>
-    1:address:screen<span class="Special"> &lt;- </span>clear-line 1:address:screen
-    2:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    3:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *2:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>clear-line <span class="Constant">1</span>:address:screen
+    <span class="Constant">2</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">3</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">2</span>:address:array:screen-cell
   ]
   <span class="Comment"># screen should be blank</span>
   memory-should-contain [
-    3<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    4<span class="Special"> &lt;- </span>0
-    5<span class="Special"> &lt;- </span>7
-    6<span class="Special"> &lt;- </span>0
-    7<span class="Special"> &lt;- </span>7
-    8<span class="Special"> &lt;- </span>0
-    9<span class="Special"> &lt;- </span>7
-    10<span class="Special"> &lt;- </span>0
-    11<span class="Special"> &lt;- </span>7
-    12<span class="Special"> &lt;- </span>0
-    13<span class="Special"> &lt;- </span>7
-    14<span class="Special"> &lt;- </span>0
-    15<span class="Special"> &lt;- </span>7
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+    <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+    <span class="Constant">14</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+    <span class="Constant">15</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
   ]
 ]
 
-recipe cursor-down [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-down [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    {
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    <span class="Delimiter">{</span>
       <span class="Comment"># increment row unless it's already all the way down</span>
-      height:number<span class="Special"> &lt;- </span>get *sc, num-rows:offset
-      row:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-row:offset
-      <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span>subtract height, 1
-      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *row, <span class="Identifier">max</span>
-      break-if at-bottom?
-      *row<span class="Special"> &lt;- </span>add *row, 1
-    }
-    reply sc/same-as-ingredient:0
-  }
+      height:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-rows:offset</span>
+      row:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-row:offset</span>
+      max:number<span class="Special"> &lt;- </span>subtract height, <span class="Constant">1</span>
+      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *row, max
+      <span class="muControl">break-if</span> at-bottom?
+      *row<span class="Special"> &lt;- </span>add *row, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   move-cursor-down-on-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-up [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-up [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    {
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    <span class="Delimiter">{</span>
       <span class="Comment"># decrement row unless it's already all the way up</span>
-      row:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-row:offset
-      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *row, 0
-      break-if at-top?
-      *row<span class="Special"> &lt;- </span>subtract *row, 1
-    }
-    reply sc/same-as-ingredient:0
-  }
+      row:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-row:offset</span>
+      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *row, <span class="Constant">0</span>
+      <span class="muControl">break-if</span> at-top?
+      *row<span class="Special"> &lt;- </span>subtract *row, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   move-cursor-up-on-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-right [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-right [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    {
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    <span class="Delimiter">{</span>
       <span class="Comment"># increment column unless it's already all the way to the right</span>
-      width:number<span class="Special"> &lt;- </span>get *sc, num-columns:offset
-      column:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-      <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span>subtract width, 1
-      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *column, <span class="Identifier">max</span>
-      break-if at-bottom?
-      *column<span class="Special"> &lt;- </span>add *column, 1
-    }
-    reply sc/same-as-ingredient:0
-  }
+      width:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-columns:offset</span>
+      column:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+      max:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">1</span>
+      at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *column, max
+      <span class="muControl">break-if</span> at-bottom?
+      *column<span class="Special"> &lt;- </span>add *column, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   move-cursor-right-on-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-left [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-left [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    {
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    <span class="Delimiter">{</span>
       <span class="Comment"># decrement column unless it's already all the way to the left</span>
-      column:address:number<span class="Special"> &lt;- </span>get-address *sc, cursor-column:offset
-      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *column, 0
-      break-if at-top?
-      *column<span class="Special"> &lt;- </span>subtract *column, 1
-    }
-    reply sc/same-as-ingredient:0
-  }
+      column:address:number<span class="Special"> &lt;- </span>get-address *sc, <span class="Constant">cursor-column:offset</span>
+      at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *column, <span class="Constant">0</span>
+      <span class="muControl">break-if</span> at-top?
+      *column<span class="Special"> &lt;- </span>subtract *column, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   move-cursor-left-on-display
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-to-start-of-line [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-to-start-of-line [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   row:number, _, sc<span class="Special"> &lt;- </span>cursor-position sc
-  column:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
+  column:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
   sc<span class="Special"> &lt;- </span>move-cursor sc, row, column
-  reply sc/same-as-ingredient:0
+  <span class="muControl">reply</span> sc/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe cursor-to-next-line [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> cursor-to-next-line [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   screen<span class="Special"> &lt;- </span>cursor-down screen
   screen<span class="Special"> &lt;- </span>cursor-to-start-of-line screen
-  reply screen/same-as-ingredient:0
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-recipe screen-width [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> screen-width [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    width:number<span class="Special"> &lt;- </span>get *sc, num-columns:offset
-    reply width
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    width:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-columns:offset</span>
+    <span class="muControl">reply</span> width
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   width:number<span class="Special"> &lt;- </span>display-width
-  reply width
+  <span class="muControl">reply</span> width
 ]
 
-recipe screen-height [
-  <span class="Underlined">local</span>-scope
-  sc:address:screen<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> screen-height [
+  <span class="Constant">local-scope</span>
+  sc:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists, move cursor in fake screen</span>
-  {
-    break-unless sc
-    height:number<span class="Special"> &lt;- </span>get *sc, num-rows:offset
-    reply height
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sc
+    height:number<span class="Special"> &lt;- </span>get *sc, <span class="Constant">num-rows:offset</span>
+    <span class="muControl">reply</span> height
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   height:number<span class="Special"> &lt;- </span>display-height
-  reply height
+  <span class="muControl">reply</span> height
 ]
 
-recipe hide-cursor [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> hide-cursor [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
-  {
-    break-unless screen
-    reply screen
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> screen
+    <span class="muControl">reply</span> screen
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   hide-cursor-on-display
-  reply screen
+  <span class="muControl">reply</span> screen
 ]
 
-recipe show-cursor [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> show-cursor [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
-  {
-    break-unless screen
-    reply screen
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> screen
+    <span class="muControl">reply</span> screen
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   show-cursor-on-display
-  reply screen
+  <span class="muControl">reply</span> screen
 ]
 
-recipe hide-screen [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> hide-screen [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Comment"># todo: help test this</span>
-  {
-    break-unless screen
-    reply screen
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> screen
+    <span class="muControl">reply</span> screen
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   hide-display
-  reply screen
+  <span class="muControl">reply</span> screen
 ]
 
-recipe show-screen [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> show-screen [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># if x exists (not real display), do nothing</span>
   <span class="Comment"># todo: help test this</span>
-  {
-    break-unless screen
-    reply screen
-  }
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> screen
+    <span class="muControl">reply</span> screen
+  <span class="Delimiter">}</span>
   <span class="Comment"># otherwise, real screen</span>
   show-display
-  reply screen
+  <span class="muControl">reply</span> screen
 ]
 
-recipe <span class="Identifier">print</span>-string [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> print-string [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default color to white</span>
-    break-if color-found?
-    color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7/white
-  }
-  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+    <span class="muControl">break-if</span> color-found?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+  <span class="Delimiter">}</span>
+  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default bg-color to black</span>
-    break-if bg-color-found?
-    bg-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0/black
-  }
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *s
-  i:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
+    <span class="muControl">break-if</span> bg-color-found?
+    bg-color<span class="Special"> &lt;- </span>copy <span class="Constant">0/black</span>
+  <span class="Delimiter">}</span>
+  len:number<span class="Special"> &lt;- </span>length *s
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    break-if done?
+    <span class="muControl">break-if</span> done?
     c:character<span class="Special"> &lt;- </span>index *s, i
-    <span class="Identifier">print</span>-character screen, c, color, bg-color
-    i<span class="Special"> &lt;- </span>add i, 1
-    loop
-  }
-  reply screen/same-as-ingredient:0
+    print-character screen, c, color, bg-color
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario <span class="Identifier">print</span>-string-stops-at-right-margin [
+<span class="muScenario">scenario</span> print-string-stops-at-right-margin [
   run [
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">new</span>-fake-screen 3/width, 2/height
-    2:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [abcd]
-    1:address:screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-string 1:address:screen, 2:address:<span class="Identifier">array</span>:character
-    3:address:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span>get *1:address:screen, data:offset
-    4:<span class="Identifier">array</span>:screen-cell<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *3:address:<span class="Identifier">array</span>:screen-cell
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>new-fake-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+    <span class="Constant">1</span>:address:screen<span class="Special"> &lt;- </span>print-string <span class="Constant">1</span>:address:screen, <span class="Constant">2</span>:address:array:character
+    <span class="Constant">3</span>:address:array:screen-cell<span class="Special"> &lt;- </span>get *<span class="Constant">1</span>:address:screen, <span class="Constant">data:offset</span>
+    <span class="Constant">4</span>:array:screen-cell<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:screen-cell
   ]
   memory-should-contain [
-    4<span class="Special"> &lt;- </span>6  <span class="Comment"># width*height</span>
-    5<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    6<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    7<span class="Special"> &lt;- </span>98  <span class="Comment"># 'b'</span>
-    8<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    9<span class="Special"> &lt;- </span>100  <span class="Comment"># 'd' overwrites 'c'</span>
-    10<span class="Special"> &lt;- </span>7  <span class="Comment"># white</span>
-    11<span class="Special"> &lt;- </span>0  <span class="Comment"># unused</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">6</span>  <span class="Comment"># width*height</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">100</span>  <span class="Comment"># 'd' overwrites 'c'</span>
+    <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">7</span>  <span class="Comment"># white</span>
+    <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># unused</span>
   ]
 ]
 
-recipe <span class="Identifier">print</span>-integer [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  n:number<span class="Special"> &lt;- </span>next-ingredient
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> print-integer [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default color to white</span>
-    break-if color-found?
-    color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7/white
-  }
-  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span>next-ingredient
-  {
+    <span class="muControl">break-if</span> color-found?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+  <span class="Delimiter">}</span>
+  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># default bg-color to black</span>
-    break-if bg-color-found?
-    bg-color<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0/black
-  }
+    <span class="muControl">break-if</span> bg-color-found?
+    bg-color<span class="Special"> &lt;- </span>copy <span class="Constant">0/black</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># todo: other bases besides decimal</span>
-  s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>integer-to-decimal-string n
-  <span class="Identifier">print</span>-string screen, s, color, bg-color
-  reply screen/same-as-ingredient:0
+  s:address:array:character<span class="Special"> &lt;- </span>integer-to-decimal-string n
+  print-string screen, s, color, bg-color
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
 ]
 </pre>
 </body>
diff --git a/html/073scenario_screen_test.mu.html b/html/073scenario_screen_test.mu.html
index 556fe973..aa6f42b9 100644
--- a/html/073scenario_screen_test.mu.html
+++ b/html/073scenario_screen_test.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -29,31 +30,31 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># To check our support for screens in scenarios, rewrite tests from print.mu</span>
 
-scenario <span class="Identifier">print</span>-character-at-top-left-2 [
-  <span class="Identifier">assume</span>-screen 3/width, 2/height
+<span class="muScenario">scenario</span> print-character-at-top-left-2 [
+  assume-screen <span class="Constant">3/width</span>, <span class="Constant">2/height</span>
   run [
-    screen:address<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character screen:address, 97/a
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">97/a</span>
   ]
   screen-should-contain [
-    .a  .
-    .   .
+   <span class="Constant"> .a  .</span>
+   <span class="Constant"> .   .</span>
   ]
 ]
 
-scenario clear-line-erases-printed-characters-2 [
-  <span class="Identifier">assume</span>-screen 5/width, 3/height
+<span class="muScenario">scenario</span> clear-line-erases-printed-characters-2 [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span>
   run [
     <span class="Comment"># print a character</span>
-    screen:address<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character screen:address, 97/a
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">97/a</span>
     <span class="Comment"># move cursor to start of line</span>
-    screen:address<span class="Special"> &lt;- </span>move-cursor screen:address, 0/row, 0/column
+    screen:address<span class="Special"> &lt;- </span>move-cursor screen:address, <span class="Constant">0/row</span>, <span class="Constant">0/column</span>
     <span class="Comment"># clear line</span>
     screen:address<span class="Special"> &lt;- </span>clear-line screen:address
   ]
   screen-should-contain [
-    .     .
-    .     .
-    .     .
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
   ]
 ]
 </pre>
diff --git a/html/074console.mu.html b/html/074console.mu.html
index f2eb5552..191c33e8 100644
--- a/html/074console.mu.html
+++ b/html/074console.mu.html
@@ -13,10 +13,13 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -31,7 +34,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># Wrappers around interaction primitives that take a potentially fake object</span>
 <span class="Comment"># and are thus easier to test.</span>
 
-exclusive-container event [
+<span class="muData">exclusive-container</span> event [
   text:character
   keycode:number  <span class="Comment"># keys on keyboard without a unicode representation</span>
   touch:touch-event  <span class="Comment"># mouse, track ball, etc.</span>
@@ -39,107 +42,107 @@ exclusive-container event [
   <span class="Comment"># update the assume-console handler if you add more variants</span>
 ]
 
-container touch-event [
-  <span class="Identifier">type</span>:number
+<span class="muData">container</span> touch-event [
+  type:number
   row:number
   column:number
 ]
 
-container resize-event [
+<span class="muData">container</span> resize-event [
   width:number
   height:number
 ]
 
-container console [
+<span class="muData">container</span> console [
   index:number
-  data:address:<span class="Identifier">array</span>:event
+  data:address:array:event
 ]
 
-recipe <span class="Identifier">new</span>-fake-console [
-  <span class="Underlined">local</span>-scope
-  result:address:console<span class="Special"> &lt;- </span><span class="Identifier">new</span> console:<span class="Identifier">type</span>
-  buf:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>get-address *result, data:offset
-  *buf<span class="Special"> &lt;- </span>next-ingredient
-  idx:address:number<span class="Special"> &lt;- </span>get-address *result, index:offset
-  *idx<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  reply result
+<span class="muRecipe">recipe</span> new-fake-console [
+  <span class="Constant">local-scope</span>
+  result:address:console<span class="Special"> &lt;- </span>new <span class="Constant">console:type</span>
+  buf:address:address:array:character<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *buf<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  idx:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">index:offset</span>
+  *idx<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="muControl">reply</span> result
 ]
 
-recipe <span class="Identifier">read</span>-event [
-  <span class="Underlined">local</span>-scope
-  x:address:console<span class="Special"> &lt;- </span>next-ingredient
-  {
-    break-unless x
-    idx:address:number<span class="Special"> &lt;- </span>get-address *x, index:offset
-    buf:address:<span class="Identifier">array</span>:event<span class="Special"> &lt;- </span>get *x, data:offset
-    {
-      <span class="Identifier">max</span>:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *buf
-      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *idx, <span class="Identifier">max</span>
-      break-unless done?
-      dummy:address:event<span class="Special"> &lt;- </span><span class="Identifier">new</span> event:<span class="Identifier">type</span>
-      reply *dummy, x/same-as-ingredient:0, 1/found, 1/<span class="Identifier">quit</span>
-    }
+<span class="muRecipe">recipe</span> read-event [
+  <span class="Constant">local-scope</span>
+  x:address:console<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x
+    idx:address:number<span class="Special"> &lt;- </span>get-address *x, <span class="Constant">index:offset</span>
+    buf:address:array:event<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span>
+    <span class="Delimiter">{</span>
+      max:number<span class="Special"> &lt;- </span>length *buf
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *idx, max
+      <span class="muControl">break-unless</span> done?
+      dummy:address:event<span class="Special"> &lt;- </span>new <span class="Constant">event:type</span>
+      <span class="muControl">reply</span> *dummy, x/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">1/quit</span>
+    <span class="Delimiter">}</span>
     result:event<span class="Special"> &lt;- </span>index *buf, *idx
-    *idx<span class="Special"> &lt;- </span>add *idx, 1
-    reply result, x/same-as-ingredient:0, 1/found, 0/<span class="Identifier">quit</span>
-  }
+    *idx<span class="Special"> &lt;- </span>add *idx, <span class="Constant">1</span>
+    <span class="muControl">reply</span> result, x/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span>
+  <span class="Delimiter">}</span>
   switch  <span class="Comment"># real event source is infrequent; avoid polling it too much</span>
   result:event, found?:boolean<span class="Special"> &lt;- </span>check-for-interaction
-  reply result, x/same-as-ingredient:0, found?, 0/<span class="Identifier">quit</span>
+  <span class="muControl">reply</span> result, x/same-as-ingredient:<span class="Constant">0</span>, found?, <span class="Constant">0/quit</span>
 ]
 
 <span class="Comment"># variant of read-event for just keyboard events. Discards everything that</span>
 <span class="Comment"># isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get</span>
 <span class="Comment"># newlines, tabs, ctrl-d..</span>
-recipe <span class="Identifier">read</span>-key [
-  <span class="Underlined">local</span>-scope
-  console:address<span class="Special"> &lt;- </span>next-ingredient
-  x:event, console, found?:boolean, <span class="Identifier">quit</span>?:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-event console
-  reply-if <span class="Identifier">quit</span>?, 0, console/same-as-ingredient:0, found?, <span class="Identifier">quit</span>?
-  reply-unless found?, 0, console/same-as-ingredient:0, found?, <span class="Identifier">quit</span>?
-  c:address:character<span class="Special"> &lt;- </span>maybe-convert x, text:variant
-  reply-unless c, 0, console/same-as-ingredient:0, 0/found, 0/<span class="Identifier">quit</span>
-  reply *c, console/same-as-ingredient:0, 1/found, 0/<span class="Identifier">quit</span>
+<span class="muRecipe">recipe</span> read-key [
+  <span class="Constant">local-scope</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  x:event, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console
+  <span class="muControl">reply-if</span> quit?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit?
+  <span class="muControl">reply-unless</span> found?, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, found?, quit?
+  c:address:character<span class="Special"> &lt;- </span>maybe-convert x, <span class="Constant">text:variant</span>
+  <span class="muControl">reply-unless</span> c, <span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/found</span>, <span class="Constant">0/quit</span>
+  <span class="muControl">reply</span> *c, console/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/found</span>, <span class="Constant">0/quit</span>
 ]
 
-recipe send-keys-to-channel [
-  <span class="Underlined">local</span>-scope
-  console:address<span class="Special"> &lt;- </span>next-ingredient
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  {
-    c:character, console, found?:boolean, <span class="Identifier">quit</span>?:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-key console
-    loop-unless found?
-    break-if <span class="Identifier">quit</span>?
-    <span class="Identifier">assert</span> c, [invalid event, expected text]
-    screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character screen, c
-    chan<span class="Special"> &lt;- </span><span class="Identifier">write</span> chan, c
-    loop
-  }
-  reply console/same-as-ingredient:0, chan/same-as-ingredient:1, screen/same-as-ingredient:2
+<span class="muRecipe">recipe</span> send-keys-to-channel [
+  <span class="Constant">local-scope</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    c:character, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-key console
+    <span class="muControl">loop-unless</span> found?
+    <span class="muControl">break-if</span> quit?
+    assert c, <span class="Constant">[invalid event, expected text]</span>
+    screen<span class="Special"> &lt;- </span>print-character screen, c
+    chan<span class="Special"> &lt;- </span>write chan, c
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> console/same-as-ingredient:<span class="Constant">0</span>, chan/same-as-ingredient:<span class="Constant">1</span>, screen/same-as-ingredient:<span class="Constant">2</span>
 ]
 
-recipe wait-for-event [
-  <span class="Underlined">local</span>-scope
-  console:address<span class="Special"> &lt;- </span>next-ingredient
-  {
-    _, console, found?:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-event console
-    loop-unless found?
-  }
-  reply console/same-as-ingredient:0
+<span class="muRecipe">recipe</span> wait-for-event [
+  <span class="Constant">local-scope</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    _, console, found?:boolean<span class="Special"> &lt;- </span>read-event console
+    <span class="muControl">loop-unless</span> found?
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> console/same-as-ingredient:<span class="Constant">0</span>
 ]
 
 <span class="Comment"># use this helper to skip rendering if there's lots of other events queued up</span>
-recipe <span class="Identifier">has</span>-more-events? [
-  <span class="Underlined">local</span>-scope
-  console:address<span class="Special"> &lt;- </span>next-ingredient
-  {
-    break-unless console
+<span class="muRecipe">recipe</span> has-more-events? [
+  <span class="Constant">local-scope</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> console
     <span class="Comment"># fake consoles should be plenty fast; never skip</span>
-    reply 0/false
-  }
+    <span class="muControl">reply</span> <span class="Constant">0/false</span>
+  <span class="Delimiter">}</span>
   result:boolean<span class="Special"> &lt;- </span>interactions-left?
-  reply result
+  <span class="muControl">reply</span> result
 ]
 </pre>
 </body>
diff --git a/html/076scenario_console_test.mu.html b/html/076scenario_console_test.mu.html
index 7b38078c..b33cb4cd 100644
--- a/html/076scenario_console_test.mu.html
+++ b/html/076scenario_console_test.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -31,25 +32,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># scenario_console.mu</span>
 <span class="Comment"># Tests for console interface.</span>
 
-scenario <span class="Identifier">read</span>-key-<span class="Identifier">in</span>-mu [
-  <span class="Identifier">assume</span>-console [
-    <span class="Identifier">type</span> [abc]
+<span class="muScenario">scenario</span> read-key-in-mu [
+  assume-console [
+    type <span class="Constant">[abc]</span>
   ]
   run [
-    1:character, console:address, 2:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-key console:address
-    3:character, console:address, 4:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-key console:address
-    5:character, console:address, 6:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-key console:address
-    7:character, console:address, 8:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-key console:address
+    <span class="Constant">1</span>:character, console:address, <span class="Constant">2</span>:boolean<span class="Special"> &lt;- </span>read-key console:address
+    <span class="Constant">3</span>:character, console:address, <span class="Constant">4</span>:boolean<span class="Special"> &lt;- </span>read-key console:address
+    <span class="Constant">5</span>:character, console:address, <span class="Constant">6</span>:boolean<span class="Special"> &lt;- </span>read-key console:address
+    <span class="Constant">7</span>:character, console:address, <span class="Constant">8</span>:boolean<span class="Special"> &lt;- </span>read-key console:address
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    2<span class="Special"> &lt;- </span>1
-    3<span class="Special"> &lt;- </span>98  <span class="Comment"># 'b'</span>
-    4<span class="Special"> &lt;- </span>1
-    5<span class="Special"> &lt;- </span>99  <span class="Comment"># 'c'</span>
-    6<span class="Special"> &lt;- </span>1
-    7<span class="Special"> &lt;- </span>0  <span class="Comment"># eof</span>
-    8<span class="Special"> &lt;- </span>1
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
+    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">98</span>  <span class="Comment"># 'b'</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">99</span>  <span class="Comment"># 'c'</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># eof</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
   ]
 ]
 </pre>
diff --git a/html/callcc.mu.html b/html/callcc.mu.html
index 805a182e..20ebd83c 100644
--- a/html/callcc.mu.html
+++ b/html/callcc.mu.html
@@ -13,9 +13,11 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -29,20 +31,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: saving and reusing call-stacks or continuations</span>
 
-recipe main [
+<span class="muRecipe">recipe</span> main [
   c:continuation<span class="Special"> &lt;- </span>f
-  continue-from c                         <span class="Comment"># &lt;-- ..when you hit this</span>
+  <span class="muControl">continue-from</span> c                         <span class="Comment"># &lt;-- ..when you hit this</span>
 ]
 
-recipe f [
+<span class="muRecipe">recipe</span> f [
   c:continuation<span class="Special"> &lt;- </span>g
-  reply c
+  <span class="muControl">reply</span> c
 ]
 
-recipe g [
-  c:continuation<span class="Special"> &lt;- </span>current-continuation  <span class="Comment"># &lt;-- loop back to here</span>
-  $<span class="Identifier">print</span> 1
-  reply c  <span class="Comment"># threaded through unmodified after first iteration</span>
+<span class="muRecipe">recipe</span> g [
+  c:continuation<span class="Special"> &lt;- </span><span class="muControl">current-continuation</span>  <span class="Comment"># &lt;-- loop back to here</span>
+  $print <span class="Constant">1</span>
+  <span class="muControl">reply</span> c  <span class="Comment"># threaded through unmodified after first iteration</span>
 ]
 </pre>
 </body>
diff --git a/html/channel.mu.html b/html/channel.mu.html
index ce564ded..420eed5e 100644
--- a/html/channel.mu.html
+++ b/html/channel.mu.html
@@ -13,10 +13,12 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,44 +32,44 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: communicating between routines using channels</span>
 
-recipe producer [
+<span class="muRecipe">recipe</span> producer [
   <span class="Comment"># produce numbers 1 to 5 on a channel</span>
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># n = 0</span>
-  n:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
-    done?:boolean<span class="Special"> &lt;- </span>lesser-than n, 5
-    break-unless done?
+  n:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>lesser-than n, <span class="Constant">5</span>
+    <span class="muControl">break-unless</span> done?
     <span class="Comment"># other threads might get between these prints</span>
-    $<span class="Identifier">print</span> [produce: ], n, [
-]
-    chan:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> chan, n
-    n<span class="Special"> &lt;- </span>add n, 1
-    loop
-  }
+    $print <span class="Constant">[produce: ]</span>, n, <span class="Constant">[ </span>
+<span class="Constant">]</span>
+    chan:address:channel<span class="Special"> &lt;- </span>write chan, n
+    n<span class="Special"> &lt;- </span>add n, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
 ]
 
-recipe consumer [
+<span class="muRecipe">recipe</span> consumer [
   <span class="Comment"># consume and print integers from a channel</span>
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  {
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># read an integer from the channel</span>
-    n:number, chan:address:channel<span class="Special"> &lt;- </span><span class="Identifier">read</span> chan
+    n:number, chan:address:channel<span class="Special"> &lt;- </span>read chan
     <span class="Comment"># other threads might get between these prints</span>
-    $<span class="Identifier">print</span> [consume: ], n:number, [
-]
-    loop
-  }
+    $print <span class="Constant">[consume: ]</span>, n:number, <span class="Constant">[ </span>
+<span class="Constant">]</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
 ]
 
-recipe main [
-  <span class="Underlined">local</span>-scope
-  chan:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 3
+<span class="muRecipe">recipe</span> main [
+  <span class="Constant">local-scope</span>
+  chan:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">3</span>
   <span class="Comment"># create two background 'routines' that communicate by a channel</span>
-  routine1:number<span class="Special"> &lt;- </span>start-running producer:recipe, chan
-  routine2:number<span class="Special"> &lt;- </span>start-running consumer:recipe, chan
+  routine1:number<span class="Special"> &lt;- </span>start-running <span class="Constant">producer:recipe</span>, chan
+  routine2:number<span class="Special"> &lt;- </span>start-running <span class="Constant">consumer:recipe</span>, chan
   wait-for-routine routine1
   wait-for-routine routine2
 ]
diff --git a/html/chessboard.mu.html b/html/chessboard.mu.html
index 75e01db0..56b4842e 100644
--- a/html/chessboard.mu.html
+++ b/html/chessboard.mu.html
@@ -13,12 +13,16 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
 .SalientComment { color: #00ffff; }
-.CommentedCode { color: #6c6c6c; }
-.Underlined { color: #c000c0; text-decoration: underline; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.CommentedCode { color: #6c6c6c; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -34,195 +38,195 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># display the position after each move.</span>
 
 <span class="Comment"># recipes are mu's names for functions</span>
-recipe main [
+<span class="muRecipe">recipe</span> main [
   open-console  <span class="Comment"># take control of screen, keyboard and mouse</span>
 
   <span class="Comment"># The chessboard recipe takes keyboard and screen objects as 'ingredients'.</span>
-  #
+  <span class="Comment">#</span>
   <span class="Comment"># In mu it is good form (though not required) to explicitly show the</span>
   <span class="Comment"># hardware you rely on.</span>
-  #
+  <span class="Comment">#</span>
   <span class="Comment"># The chessboard also returns the same keyboard and screen objects. In mu it</span>
   <span class="Comment"># is good form to not modify ingredients of a recipe unless they are also</span>
   <span class="Comment"># results. Here we clearly modify both keyboard and screen, so we return</span>
   <span class="Comment"># both.</span>
-  #
+  <span class="Comment">#</span>
   <span class="Comment"># Here the console and screen are both 0, which usually indicates real</span>
   <span class="Comment"># hardware rather than a fake for testing as you'll see below.</span>
-  0/screen, 0/console<span class="Special"> &lt;- </span>chessboard 0/screen, 0/console
+  <span class="Constant">0/screen</span>, <span class="Constant">0/console</span><span class="Special"> &lt;- </span>chessboard <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>
 
   close-console  <span class="Comment"># cleanup screen, keyboard and mouse</span>
 ]
 
 <span class="SalientComment">## But enough about mu. Here's what it looks like to run the chessboard program.</span>
 
-scenario <span class="Identifier">print</span>-board-and-<span class="Identifier">read</span>-move [
+<span class="muScenario">scenario</span> print-board-and-read-move [
   $close-trace  <span class="Comment"># administrivia: most scenarios save and check traces, but this one gets too large/slow</span>
   <span class="Comment"># we'll make the screen really wide because the program currently prints out a long line</span>
-  <span class="Identifier">assume</span>-screen 120/width, 20/height
+  assume-screen <span class="Constant">120/width</span>, <span class="Constant">20/height</span>
   <span class="Comment"># initialize keyboard to type in a move</span>
-  <span class="Identifier">assume</span>-console [
-    <span class="Identifier">type</span> [a2-a4
-]
+  assume-console [
+    type <span class="Constant">[a2-a4</span>
+<span class="Constant">]</span>
   ]
   run [
     screen:address, console:address<span class="Special"> &lt;- </span>chessboard screen:address, console:address
     <span class="Comment"># icon for the cursor</span>
-    screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-character screen, 9251/␣
+    screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">9251/␣</span>
   ]
   screen-should-contain [
   <span class="Comment">#            1         2         3         4         5         6         7         8         9         10        11</span>
   <span class="Comment">#  012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789</span>
-    .Stupid text-mode chessboard. White pieces <span class="Identifier">in</span> uppercase; black pieces <span class="Identifier">in</span> lowercase. No checking for legal moves.         .
-    .                                                                                                                        .
-    .8 | r n b q k b n r                                                                                                     .
-    .7 | p p p p p p p p                                                                                                     .
-    .6 |                                                                                                                     .
-    .5 |                                                                                                                     .
-    .4 | P                                                                                                                   .
-    .3 |                                                                                                                     .
-    .2 |   P P P P P P P                                                                                                     .
-    .1 | R N B Q K B N R                                                                                                     .
-    .  +----------------                                                                                                     .
-    .    a b c d e f g h                                                                                                     .
-    .                                                                                                                        .
-    .Type <span class="Identifier">in</span> your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.                               .
-    .                                                                                                                        .
-    .Hit 'q' to exit.                                                                                                        .
-    .                                                                                                                        .
-    .move: ␣                                                                                                                 .
-    .                                                                                                                        .
-    .                                                                                                                        .
+   <span class="Constant"> .Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.         .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
+   <span class="Constant"> .8 | r n b q k b n r                                                                                                     .</span>
+   <span class="Constant"> .7 | p p p p p p p p                                                                                                     .</span>
+   <span class="Constant"> .6 |                                                                                                                     .</span>
+   <span class="Constant"> .5 |                                                                                                                     .</span>
+   <span class="Constant"> .4 | P                                                                                                                   .</span>
+   <span class="Constant"> .3 |                                                                                                                     .</span>
+   <span class="Constant"> .2 |   P P P P P P P                                                                                                     .</span>
+   <span class="Constant"> .1 | R N B Q K B N R                                                                                                     .</span>
+   <span class="Constant"> .  +----------------                                                                                                     .</span>
+   <span class="Constant"> .    a b c d e f g h                                                                                                     .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
+   <span class="Constant"> .Type in your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.                               .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
+   <span class="Constant"> .Hit 'q' to exit.                                                                                                        .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
+   <span class="Constant"> .move: ␣                                                                                                                 .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
+   <span class="Constant"> .                                                                                                                        .</span>
   ]
 ]
 
 <span class="SalientComment">## Here's how 'chessboard' is implemented.</span>
 
-recipe chessboard [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  console:address<span class="Special"> &lt;- </span>next-ingredient
-  board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>initial-position
+<span class="muRecipe">recipe</span> chessboard [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position
   <span class="Comment"># hook up stdin</span>
-  stdin:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-  start-running send-keys-to-channel:recipe, console, stdin, screen
+  stdin:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+  start-running <span class="Constant">send-keys-to-channel:recipe</span>, console, stdin, screen
   <span class="Comment"># buffer lines in stdin</span>
-  buffered-stdin:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 10/capacity
-  start-running buffer-lines:recipe, stdin, buffered-stdin
-  {
-    msg:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [Stupid text-mode chessboard. White pieces <span class="Identifier">in</span> uppercase; black pieces <span class="Identifier">in</span> lowercase. No checking for legal moves.
-]
-    <span class="Identifier">print</span>-string screen, msg
+  buffered-stdin:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
+  start-running <span class="Constant">buffer-lines:recipe</span>, stdin, buffered-stdin
+  <span class="Delimiter">{</span>
+    msg:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span>
+<span class="Constant">]</span>
+    print-string screen, msg
     cursor-to-next-line screen
-    <span class="Identifier">print</span>-board screen, board
+    print-board screen, board
     cursor-to-next-line screen
-    msg<span class="Special"> &lt;- </span><span class="Identifier">new</span> [Type <span class="Identifier">in</span> your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.
-]
-    <span class="Identifier">print</span>-string screen, msg
+    msg<span class="Special"> &lt;- </span>new <span class="Constant">[Type in your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.</span>
+<span class="Constant">]</span>
+    print-string screen, msg
     cursor-to-next-line screen
-    msg<span class="Special"> &lt;- </span><span class="Identifier">new</span> [Hit 'q' to exit.
-]
-    <span class="Identifier">print</span>-string screen, msg
-    {
+    msg<span class="Special"> &lt;- </span>new <span class="Constant">[Hit 'q' to exit.</span>
+<span class="Constant">]</span>
+    print-string screen, msg
+    <span class="Delimiter">{</span>
       cursor-to-next-line screen
-      msg<span class="Special"> &lt;- </span><span class="Identifier">new</span> [move: ]
-      <span class="Identifier">print</span>-string screen, msg
-      m:address:move, <span class="Identifier">quit</span>:boolean, <span class="Identifier">error</span>:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-move buffered-stdin, screen
-      break-if <span class="Identifier">quit</span>, +<span class="Identifier">quit</span>:label
+      msg<span class="Special"> &lt;- </span>new <span class="Constant">[move: ]</span>
+      print-string screen, msg
+      m:address:move, quit:boolean, error:boolean<span class="Special"> &lt;- </span>read-move buffered-stdin, screen
+      <span class="muControl">break-if</span> quit, <span class="Constant">+quit:label</span>
       buffered-stdin<span class="Special"> &lt;- </span>clear-channel buffered-stdin  <span class="Comment"># cleanup after error. todo: test this?</span>
-      loop-if <span class="Identifier">error</span>
-    }
+      <span class="muControl">loop-if</span> error
+    <span class="Delimiter">}</span>
     board<span class="Special"> &lt;- </span>make-move board, m
     clear-screen screen
-    loop
-  }
-  +<span class="Identifier">quit</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+<span class="Constant">  +quit</span>
 ]
 
 <span class="SalientComment">## a board is an array of files, a file is an array of characters (squares)</span>
 
-recipe <span class="Identifier">new</span>-board [
-  <span class="Underlined">local</span>-scope
-  initial-position:address:<span class="Identifier">array</span>:number<span class="Special"> &lt;- </span>next-ingredient
+<span class="muRecipe">recipe</span> new-board [
+  <span class="Constant">local-scope</span>
+  initial-position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Comment"># assert(length(initial-position) == 64)</span>
-  len:number<span class="Special"> &lt;- </span><span class="Identifier">length</span> *initial-position
-  correct-<span class="Identifier">length</span>?:boolean<span class="Special"> &lt;- </span>equal len, 64
-  <span class="Identifier">assert</span> correct-<span class="Identifier">length</span>?, [chessboard had incorrect size]
+  len:number<span class="Special"> &lt;- </span>length *initial-position
+  correct-length?:boolean<span class="Special"> &lt;- </span>equal len, <span class="Constant">64</span>
+  assert correct-length?, <span class="Constant">[chessboard had incorrect size]</span>
   <span class="Comment"># board is an array of pointers to files; file is an array of characters</span>
-  board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 8
-  col:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
-    done?:boolean<span class="Special"> &lt;- </span>equal col, 8
-    break-if done?
-    file:address:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index-address *board, col
-    *file<span class="Special"> &lt;- </span><span class="Identifier">new</span>-file initial-position, col
-    col<span class="Special"> &lt;- </span>add col, 1
-    loop
-  }
-  reply board
+  board:address:array:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">8</span>
+  col:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>equal col, <span class="Constant">8</span>
+    <span class="muControl">break-if</span> done?
+    file:address:address:array:character<span class="Special"> &lt;- </span>index-address *board, col
+    *file<span class="Special"> &lt;- </span>new-file initial-position, col
+    col<span class="Special"> &lt;- </span>add col, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> board
 ]
 
-recipe <span class="Identifier">new</span>-file [
-  <span class="Underlined">local</span>-scope
-  position:address:<span class="Identifier">array</span>:number<span class="Special"> &lt;- </span>next-ingredient
-  index:number<span class="Special"> &lt;- </span>next-ingredient
-  index<span class="Special"> &lt;- </span>multiply index, 8
-  result:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> character:<span class="Identifier">type</span>, 8
-  row:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-  {
-    done?:boolean<span class="Special"> &lt;- </span>equal row, 8
-    break-if done?
+<span class="muRecipe">recipe</span> new-file [
+  <span class="Constant">local-scope</span>
+  position:address:array:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  index:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  index<span class="Special"> &lt;- </span>multiply index, <span class="Constant">8</span>
+  result:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">8</span>
+  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>equal row, <span class="Constant">8</span>
+    <span class="muControl">break-if</span> done?
     dest:address:character<span class="Special"> &lt;- </span>index-address *result, row
     *dest<span class="Special"> &lt;- </span>index *position, index
-    row<span class="Special"> &lt;- </span>add row, 1
-    index<span class="Special"> &lt;- </span>add index, 1
-    loop
-  }
-  reply result
+    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+    index<span class="Special"> &lt;- </span>add index, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
 ]
 
-recipe <span class="Identifier">print</span>-board [
-  <span class="Underlined">local</span>-scope
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  row:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 7  <span class="Comment"># start printing from the top of the board</span>
+<span class="muRecipe">recipe</span> print-board [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  board:address:array:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">7</span>  <span class="Comment"># start printing from the top of the board</span>
   <span class="Comment"># print each row</span>
-  {
-    done?:boolean<span class="Special"> &lt;- </span>lesser-than row, 0
-    break-if done?
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>lesser-than row, <span class="Constant">0</span>
+    <span class="muControl">break-if</span> done?
     <span class="Comment"># print rank number as a legend</span>
-    rank:number<span class="Special"> &lt;- </span>add row, 1
-    <span class="Identifier">print</span>-integer screen, rank
-    s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [ | ]
-    <span class="Identifier">print</span>-string screen, s
+    rank:number<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+    print-integer screen, rank
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ | ]</span>
+    print-string screen, s
     <span class="Comment"># print each square in the row</span>
-    col:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 0
-    {
-      done?:boolean<span class="Special"> &lt;- </span>equal col:number, 8
-      break-if done?:boolean
-      f:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *board, col
+    col:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>equal col:number, <span class="Constant">8</span>
+      <span class="muControl">break-if</span> done?:boolean
+      f:address:array:character<span class="Special"> &lt;- </span>index *board, col
       c:character<span class="Special"> &lt;- </span>index *f, row
-      <span class="Identifier">print</span>-character screen, c
-      <span class="Identifier">print</span>-character screen, 32/space
-      col<span class="Special"> &lt;- </span>add col, 1
-      loop
-    }
-    row<span class="Special"> &lt;- </span>subtract row, 1
+      print-character screen, c
+      print-character screen, <span class="Constant">32/space</span>
+      col<span class="Special"> &lt;- </span>add col, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    row<span class="Special"> &lt;- </span>subtract row, <span class="Constant">1</span>
     cursor-to-next-line screen
-    loop
-  }
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># print file letters as legend</span>
-  s<span class="Special"> &lt;- </span><span class="Identifier">new</span> [  +----------------]
-  <span class="Identifier">print</span>-string screen, s
+  s<span class="Special"> &lt;- </span>new <span class="Constant">[  +----------------]</span>
+  print-string screen, s
   screen<span class="Special"> &lt;- </span>cursor-to-next-line screen
-  s<span class="Special"> &lt;- </span><span class="Identifier">new</span> [    a b c d e f g h]
-  screen<span class="Special"> &lt;- </span><span class="Identifier">print</span>-string screen, s
+  s<span class="Special"> &lt;- </span>new <span class="Constant">[    a b c d e f g h]</span>
+  screen<span class="Special"> &lt;- </span>print-string screen, s
   screen<span class="Special"> &lt;- </span>cursor-to-next-line screen
 ]
 
 <span class="Comment"># board:address:array:address:array:character &lt;- initial-position</span>
-recipe initial-position [
-  <span class="Underlined">local</span>-scope
+<span class="muRecipe">recipe</span> initial-position [
+  <span class="Constant">local-scope</span>
   <span class="Comment"># layout in memory (in raster order):</span>
   <span class="Comment">#   R P _ _ _ _ p r</span>
   <span class="Comment">#   N P _ _ _ _ p n</span>
@@ -232,7 +236,7 @@ recipe initial-position [
   <span class="Comment">#   B P _ _ _ _ p B</span>
   <span class="Comment">#   N P _ _ _ _ p n</span>
   <span class="Comment">#   R P _ _ _ _ p r</span>
-  initial-position:address:<span class="Identifier">array</span>:number<span class="Special"> &lt;- </span><span class="Identifier">new</span>-<span class="Identifier">array</span> 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 81/Q, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 113/q, 75/K, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 107/k, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r
+  initial-position:address:array:number<span class="Special"> &lt;- </span>new-array <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">81/Q</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">113/q</span>, <span class="Constant">75/K</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">107/k</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>
 <span class="CommentedCode">#?       82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r,</span>
 <span class="CommentedCode">#?       78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span>
 <span class="CommentedCode">#?       66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, </span>
@@ -241,36 +245,36 @@ recipe initial-position [
 <span class="CommentedCode">#?       66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b,</span>
 <span class="CommentedCode">#?       78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span>
 <span class="CommentedCode">#?       82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r</span>
-  board:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span>-board initial-position
-  reply board
+  board:address:array:address:array:character<span class="Special"> &lt;- </span>new-board initial-position
+  <span class="muControl">reply</span> board
 ]
 
-scenario printing-the-board [
-  <span class="Identifier">assume</span>-screen 30/width, 12/height
+<span class="muScenario">scenario</span> printing-the-board [
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span>
   run [
-    1:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> &lt;- </span>initial-position
-    screen:address<span class="Special"> &lt;- </span><span class="Identifier">print</span>-board screen:address, 1:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board
+    <span class="Constant">1</span>:address:array:address:array:character/board<span class="Special"> &lt;- </span>initial-position
+    screen:address<span class="Special"> &lt;- </span>print-board screen:address, <span class="Constant">1</span>:address:array:address:array:character/board
   ]
   screen-should-contain [
   <span class="Comment">#  012345678901234567890123456789</span>
-    .8 | r n b q k b n r           .
-    .7 | p p p p p p p p           .
-    .6 |                           .
-    .5 |                           .
-    .4 |                           .
-    .3 |                           .
-    .2 | P P P P P P P P           .
-    .1 | R N B Q K B N R           .
-    .  +----------------           .
-    .    a b c d e f g h           .
-    .                              .
-    .                              .
+   <span class="Constant"> .8 | r n b q k b n r           .</span>
+   <span class="Constant"> .7 | p p p p p p p p           .</span>
+   <span class="Constant"> .6 |                           .</span>
+   <span class="Constant"> .5 |                           .</span>
+   <span class="Constant"> .4 |                           .</span>
+   <span class="Constant"> .3 |                           .</span>
+   <span class="Constant"> .2 | P P P P P P P P           .</span>
+   <span class="Constant"> .1 | R N B Q K B N R           .</span>
+   <span class="Constant"> .  +----------------           .</span>
+   <span class="Constant"> .    a b c d e f g h           .</span>
+   <span class="Constant"> .                              .</span>
+   <span class="Constant"> .                              .</span>
   ]
 ]
 
 <span class="SalientComment">## data structure: move</span>
 
-container move [
+<span class="muData">container</span> move [
   <span class="Comment"># valid range: 0-7</span>
   from-file:number
   from-rank:number
@@ -280,360 +284,360 @@ container move [
 
 <span class="Comment"># result:address:move, quit?:boolean, error?:boolean &lt;- read-move stdin:address:channel, screen:address</span>
 <span class="Comment"># prints only error messages to screen</span>
-recipe <span class="Identifier">read</span>-move [
-  <span class="Underlined">local</span>-scope
-  stdin:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  from-file:number, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean<span class="Special"> &lt;- </span><span class="Identifier">read</span>-file stdin, screen
-  reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
-  reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
+<span class="muRecipe">recipe</span> read-move [
+  <span class="Constant">local-scope</span>
+  stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  from-file:number, quit?:boolean, error?:boolean<span class="Special"> &lt;- </span>read-file stdin, screen
+  <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error?
+  <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error?
   <span class="Comment"># construct the move object</span>
-  result:address:move<span class="Special"> &lt;- </span><span class="Identifier">new</span> move:<span class="Identifier">type</span>
-  x:address:number<span class="Special"> &lt;- </span>get-address *result, from-file:offset
-  *x<span class="Special"> &lt;- </span><span class="Identifier">copy</span> from-file
-  x<span class="Special"> &lt;- </span>get-address *result, from-rank:offset
-  *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> &lt;- </span><span class="Identifier">read</span>-rank stdin, screen
-  reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
-  reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
-  <span class="Identifier">error</span>?<span class="Special"> &lt;- </span>expect-from-channel stdin, 45/dash, screen
-  reply-if <span class="Identifier">error</span>?, 0/dummy, 0/<span class="Identifier">quit</span>, <span class="Identifier">error</span>?
-  x<span class="Special"> &lt;- </span>get-address *result, to-file:offset
-  *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> &lt;- </span><span class="Identifier">read</span>-file stdin, screen
-  reply-if <span class="Identifier">quit</span>?:boolean, 0/dummy, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean
-  reply-if <span class="Identifier">error</span>?:boolean, 0/dummy, <span class="Identifier">quit</span>?:boolean, <span class="Identifier">error</span>?:boolean
-  x:address:number<span class="Special"> &lt;- </span>get-address *result, to-rank:offset
-  *x, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?<span class="Special"> &lt;- </span><span class="Identifier">read</span>-rank stdin, screen
-  reply-if <span class="Identifier">quit</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
-  reply-if <span class="Identifier">error</span>?, 0/dummy, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
-  <span class="Identifier">error</span>?<span class="Special"> &lt;- </span>expect-from-channel stdin, 10/newline, screen
-  reply-if <span class="Identifier">error</span>?, 0/dummy, 0/<span class="Identifier">quit</span>, <span class="Identifier">error</span>?
-  reply result, <span class="Identifier">quit</span>?, <span class="Identifier">error</span>?
+  result:address:move<span class="Special"> &lt;- </span>new <span class="Constant">move:type</span>
+  x:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">from-file:offset</span>
+  *x<span class="Special"> &lt;- </span>copy from-file
+  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">from-rank:offset</span>
+  *x, quit?, error?<span class="Special"> &lt;- </span>read-rank stdin, screen
+  <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error?
+  <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error?
+  error?<span class="Special"> &lt;- </span>expect-from-channel stdin, <span class="Constant">45/dash</span>, screen
+  <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, error?
+  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">to-file:offset</span>
+  *x, quit?, error?<span class="Special"> &lt;- </span>read-file stdin, screen
+  <span class="muControl">reply-if</span> quit?:boolean, <span class="Constant">0/dummy</span>, quit?:boolean, error?:boolean
+  <span class="muControl">reply-if</span> error?:boolean, <span class="Constant">0/dummy</span>, quit?:boolean, error?:boolean
+  x:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">to-rank:offset</span>
+  *x, quit?, error?<span class="Special"> &lt;- </span>read-rank stdin, screen
+  <span class="muControl">reply-if</span> quit?, <span class="Constant">0/dummy</span>, quit?, error?
+  <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, quit?, error?
+  error?<span class="Special"> &lt;- </span>expect-from-channel stdin, <span class="Constant">10/newline</span>, screen
+  <span class="muControl">reply-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, error?
+  <span class="muControl">reply</span> result, quit?, error?
 ]
 
 <span class="Comment"># file:number, quit:boolean, error:boolean &lt;- read-file stdin:address:channel, screen:address</span>
 <span class="Comment"># valid values for file: 0-7</span>
-recipe <span class="Identifier">read</span>-file [
-  <span class="Underlined">local</span>-scope
-  stdin:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  c:character, stdin<span class="Special"> &lt;- </span><span class="Identifier">read</span> stdin
-  {
-    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, 81/Q
-    break-unless q-pressed?
-    reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
-  }
-  {
-    q-pressed?<span class="Special"> &lt;- </span>equal c, 113/q
-    break-unless q-pressed?
-    reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
-  }
-  {
-    empty-fake-keyboard?:boolean<span class="Special"> &lt;- </span>equal c, 0/eof
-    break-unless empty-fake-keyboard?
-    reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
-  }
-  {
-    newline?:boolean<span class="Special"> &lt;- </span>equal c, 10/newline
-    break-unless newline?
-    <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [that's not enough]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  file:number<span class="Special"> &lt;- </span>subtract c, 97/a
+<span class="muRecipe">recipe</span> read-file [
+  <span class="Constant">local-scope</span>
+  stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character, stdin<span class="Special"> &lt;- </span>read stdin
+  <span class="Delimiter">{</span>
+    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">81/Q</span>
+    <span class="muControl">break-unless</span> q-pressed?
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    q-pressed?<span class="Special"> &lt;- </span>equal c, <span class="Constant">113/q</span>
+    <span class="muControl">break-unless</span> q-pressed?
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    empty-fake-keyboard?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">0/eof</span>
+    <span class="muControl">break-unless</span> empty-fake-keyboard?
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> newline?
+    error-message:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[that's not enough]</span>
+    print-string screen, error-message
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  file:number<span class="Special"> &lt;- </span>subtract c, <span class="Constant">97/a</span>
   <span class="Comment"># 'a' &lt;= file &lt;= 'h'</span>
-  {
-    above-<span class="Identifier">min</span>:boolean<span class="Special"> &lt;- </span>greater-or-equal file, 0
-    break-if above-<span class="Identifier">min</span>
-    <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [file too low: ]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    <span class="Identifier">print</span>-character screen, c
+  <span class="Delimiter">{</span>
+    above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal file, <span class="Constant">0</span>
+    <span class="muControl">break-if</span> above-min
+    error-message:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[file too low: ]</span>
+    print-string screen, error-message
+    print-character screen, c
     cursor-to-next-line screen
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  {
-    below-<span class="Identifier">max</span>:boolean<span class="Special"> &lt;- </span>lesser-than file, 8
-    break-if below-<span class="Identifier">max</span>
-    <span class="Identifier">error</span>-message<span class="Special"> &lt;- </span><span class="Identifier">new</span> [file too high: ]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    <span class="Identifier">print</span>-character screen, c
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  reply file, 0/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    below-max:boolean<span class="Special"> &lt;- </span>lesser-than file, <span class="Constant">8</span>
+    <span class="muControl">break-if</span> below-max
+    error-message<span class="Special"> &lt;- </span>new <span class="Constant">[file too high: ]</span>
+    print-string screen, error-message
+    print-character screen, c
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> file, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span>
 ]
 
 <span class="Comment"># rank:number &lt;- read-rank stdin:address:channel, screen:address</span>
 <span class="Comment"># valid values: 0-7, -1 (quit), -2 (error)</span>
-recipe <span class="Identifier">read</span>-rank [
-  <span class="Underlined">local</span>-scope
-  stdin:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  c:character, stdin<span class="Special"> &lt;- </span><span class="Identifier">read</span> stdin
-  {
-    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, 8/Q
-    break-unless q-pressed?
-    reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
-  }
-  {
-    q-pressed?<span class="Special"> &lt;- </span>equal c, 113/q
-    break-unless q-pressed?
-    reply 0/dummy, 1/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
-  }
-  {
-    newline?:boolean<span class="Special"> &lt;- </span>equal c, 10  <span class="Comment"># newline</span>
-    break-unless newline?
-    <span class="Identifier">error</span>-message:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [that's not enough]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  rank:number<span class="Special"> &lt;- </span>subtract c, 49/'1'
+<span class="muRecipe">recipe</span> read-rank [
+  <span class="Constant">local-scope</span>
+  stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character, stdin<span class="Special"> &lt;- </span>read stdin
+  <span class="Delimiter">{</span>
+    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/Q</span>
+    <span class="muControl">break-unless</span> q-pressed?
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    q-pressed?<span class="Special"> &lt;- </span>equal c, <span class="Constant">113/q</span>
+    <span class="muControl">break-unless</span> q-pressed?
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10</span>  <span class="Comment"># newline</span>
+    <span class="muControl">break-unless</span> newline?
+    error-message:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[that's not enough]</span>
+    print-string screen, error-message
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  rank:number<span class="Special"> &lt;- </span>subtract c, <span class="Constant">49/'1'</span>
   <span class="Comment"># assert'1' &lt;= rank &lt;= '8'</span>
-  {
-    above-<span class="Identifier">min</span>:boolean<span class="Special"> &lt;- </span>greater-or-equal rank, 0
-    break-if above-<span class="Identifier">min</span>
-    <span class="Identifier">error</span>-message<span class="Special"> &lt;- </span><span class="Identifier">new</span> [rank too low: ]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    <span class="Identifier">print</span>-character screen, c
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  {
-    below-<span class="Identifier">max</span>:boolean<span class="Special"> &lt;- </span>lesser-or-equal rank, 7
-    break-if below-<span class="Identifier">max</span>
-    <span class="Identifier">error</span>-message<span class="Special"> &lt;- </span><span class="Identifier">new</span> [rank too high: ]
-    <span class="Identifier">print</span>-string screen, <span class="Identifier">error</span>-message
-    <span class="Identifier">print</span>-character screen, c
-    reply 0/dummy, 0/<span class="Identifier">quit</span>, 1/<span class="Identifier">error</span>
-  }
-  reply rank, 0/<span class="Identifier">quit</span>, 0/<span class="Identifier">error</span>
+  <span class="Delimiter">{</span>
+    above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal rank, <span class="Constant">0</span>
+    <span class="muControl">break-if</span> above-min
+    error-message<span class="Special"> &lt;- </span>new <span class="Constant">[rank too low: ]</span>
+    print-string screen, error-message
+    print-character screen, c
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    below-max:boolean<span class="Special"> &lt;- </span>lesser-or-equal rank, <span class="Constant">7</span>
+    <span class="muControl">break-if</span> below-max
+    error-message<span class="Special"> &lt;- </span>new <span class="Constant">[rank too high: ]</span>
+    print-string screen, error-message
+    print-character screen, c
+    <span class="muControl">reply</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> rank, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span>
 ]
 
 <span class="Comment"># read a character from the given channel and check that it's what we expect</span>
 <span class="Comment"># return true on error</span>
-recipe expect-from-channel [
-  <span class="Underlined">local</span>-scope
-  stdin:address:channel<span class="Special"> &lt;- </span>next-ingredient
-  expected:character<span class="Special"> &lt;- </span>next-ingredient
-  screen:address<span class="Special"> &lt;- </span>next-ingredient
-  c:character, stdin<span class="Special"> &lt;- </span><span class="Identifier">read</span> stdin
-  {
-    <span class="Identifier">match</span>?:boolean<span class="Special"> &lt;- </span>equal c, expected
-    break-if <span class="Identifier">match</span>?
-    s:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span><span class="Identifier">new</span> [expected character not found]
-    <span class="Identifier">print</span>-string screen, s
-  }
-  result:boolean<span class="Special"> &lt;- </span>not <span class="Identifier">match</span>?
-  reply result
+<span class="muRecipe">recipe</span> expect-from-channel [
+  <span class="Constant">local-scope</span>
+  stdin:address:channel<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  expected:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character, stdin<span class="Special"> &lt;- </span>read stdin
+  <span class="Delimiter">{</span>
+    match?:boolean<span class="Special"> &lt;- </span>equal c, expected
+    <span class="muControl">break-if</span> match?
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[expected character not found]</span>
+    print-string screen, s
+  <span class="Delimiter">}</span>
+  result:boolean<span class="Special"> &lt;- </span>not match?
+  <span class="muControl">reply</span> result
 ]
 
-scenario <span class="Identifier">read</span>-move-blocking [
-  <span class="Identifier">assume</span>-screen 20/width, 2/height
+<span class="muScenario">scenario</span> read-move-blocking [
+  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 2
-    2:number/routine<span class="Special"> &lt;- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span>
+    <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after coming up (before any keys were pressed)]
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
     <span class="Comment"># press 'a'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after rank 'a']
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a']
     <span class="Comment"># press '2'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 50/'2'
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">50/'2'</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after file 'a2']
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2']
     <span class="Comment"># press '-'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 45/'-'
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">45/'-'</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?/routine-state, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after hyphen 'a2-']
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?/routine-state, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> hyphen 'a2-']
     <span class="Comment"># press 'a'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?/routine-state, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after rank 'a2-a']
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?/routine-state, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> rank 'a2-a']
     <span class="Comment"># press '4'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 52/'4'
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">52/'4'</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' still waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to pause after file 'a2-a4']
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-blocking: routine failed to pause <span class="muRecipe">after</span> file 'a2-a4']
     <span class="Comment"># press 'newline'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 10  <span class="Comment"># newline</span>
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10</span>  <span class="Comment"># newline</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' now completes</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number
-    4:boolean/completed?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 1/completed
-    <span class="Identifier">assert</span> 4:boolean/completed?, [
-F <span class="Identifier">read</span>-move-blocking: routine failed to terminate on newline]
-    trace 1, [test], [reached end]
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number
+    <span class="Constant">4</span>:boolean/completed?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">1/completed</span>
+    assert <span class="Constant">4</span>:boolean/completed?, [
+F read-move-blocking: routine failed to terminate on newline]
+    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
   ]
   trace-should-contain [
     test: reached end
   ]
 ]
 
-scenario <span class="Identifier">read</span>-move-<span class="Identifier">quit</span> [
-  <span class="Identifier">assume</span>-screen 20/width, 2/height
+<span class="muScenario">scenario</span> read-move-quit [
+  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 2
-    2:number/routine<span class="Special"> &lt;- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span>
+    <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-<span class="Identifier">quit</span>: routine failed to pause after coming up (before any keys were pressed)]
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-quit: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
     <span class="Comment"># press 'q'</span>
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 113/q
-    restart 2:number/routine
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">113/q</span>
+    restart <span class="Constant">2</span>:number/routine
     <span class="Comment"># 'read-move' completes</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/completed?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 1/completed
-    <span class="Identifier">assert</span> 4:boolean/completed?, [
-F <span class="Identifier">read</span>-move-<span class="Identifier">quit</span>: routine failed to terminate on 'q']
-    trace 1, [test], [reached end]
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/completed?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">1/completed</span>
+    assert <span class="Constant">4</span>:boolean/completed?, [
+F read-move-quit: routine failed to terminate on 'q']
+    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
   ]
   trace-should-contain [
     test: reached end
   ]
 ]
 
-scenario <span class="Identifier">read</span>-move-illegal-file [
-  <span class="Identifier">assume</span>-screen 20/width, 2/height
+<span class="muScenario">scenario</span> read-move-illegal-file [
+  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 2
-    2:number/routine<span class="Special"> &lt;- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span>
+    <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)]
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 50/'2'
-    restart 2:number/routine
-    wait-for-routine 2:number
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">50/'2'</span>
+    restart <span class="Constant">2</span>:number/routine
+    wait-for-routine <span class="Constant">2</span>:number
   ]
   screen-should-contain [
-    .file too low: 2     .
-    .                    .
+   <span class="Constant"> .file too low: 2     .</span>
+   <span class="Constant"> .                    .</span>
   ]
 ]
 
-scenario <span class="Identifier">read</span>-move-illegal-rank [
-  <span class="Identifier">assume</span>-screen 20/width, 2/height
+<span class="muScenario">scenario</span> read-move-illegal-rank [
+  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 2
-    2:number/routine<span class="Special"> &lt;- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span>
+    <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)]
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 2:number/routine
-    wait-for-routine 2:number
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">2</span>:number/routine
+    wait-for-routine <span class="Constant">2</span>:number
   ]
   screen-should-contain [
-    .rank too high: a    .
-    .                    .
+   <span class="Constant"> .rank too high: a    .</span>
+   <span class="Constant"> .                    .</span>
   ]
 ]
 
-scenario <span class="Identifier">read</span>-move-empty [
-  <span class="Identifier">assume</span>-screen 20/width, 2/height
+<span class="muScenario">scenario</span> read-move-empty [
+  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
   run [
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">new</span>-channel 2
-    2:number/routine<span class="Special"> &lt;- </span>start-running <span class="Identifier">read</span>-move:recipe, 1:address:channel, screen:address
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>new-channel <span class="Constant">2</span>
+    <span class="Constant">2</span>:number/routine<span class="Special"> &lt;- </span>start-running <span class="Constant">read-move:recipe</span>, <span class="Constant">1</span>:address:channel, screen:address
     <span class="Comment"># 'read-move' is waiting for input</span>
-    wait-for-routine 2:number
-    3:number<span class="Special"> &lt;- </span>routine-state 2:number/<span class="Identifier">id</span>
-    4:boolean/waiting?<span class="Special"> &lt;- </span>equal 3:number/routine-state, 3/waiting
-    <span class="Identifier">assert</span> 4:boolean/waiting?, [
-F <span class="Identifier">read</span>-move-file: routine failed to pause after coming up (before any keys were pressed)]
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 10/newline
-    1:address:channel<span class="Special"> &lt;- </span><span class="Identifier">write</span> 1:address:channel, 97/a
-    restart 2:number/routine
-    wait-for-routine 2:number
+    wait-for-routine <span class="Constant">2</span>:number
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>routine-state <span class="Constant">2</span>:number/id
+    <span class="Constant">4</span>:boolean/waiting?<span class="Special"> &lt;- </span>equal <span class="Constant">3</span>:number/routine-state, <span class="Constant">3/waiting</span>
+    assert <span class="Constant">4</span>:boolean/waiting?, [
+F read-move-file: routine failed to pause <span class="muRecipe">after</span> coming up (<span class="muRecipe">before</span> any keys were pressed)]
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">10/newline</span>
+    <span class="Constant">1</span>:address:channel<span class="Special"> &lt;- </span>write <span class="Constant">1</span>:address:channel, <span class="Constant">97/a</span>
+    restart <span class="Constant">2</span>:number/routine
+    wait-for-routine <span class="Constant">2</span>:number
   ]
   screen-should-contain [
-    .that's not enough   .
-    .                    .
+   <span class="Constant"> .that's not enough   .</span>
+   <span class="Constant"> .                    .</span>
   ]
 ]
 
-recipe make-move [
-  <span class="Underlined">local</span>-scope
-  b:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>next-ingredient
-  m:address:move<span class="Special"> &lt;- </span>next-ingredient
-  from-file:number<span class="Special"> &lt;- </span>get *m, from-file:offset
-  from-rank:number<span class="Special"> &lt;- </span>get *m, from-rank:offset
-  to-file:number<span class="Special"> &lt;- </span>get *m, to-file:offset
-  to-rank:number<span class="Special"> &lt;- </span>get *m, to-rank:offset
-  f:address:<span class="Identifier">array</span>:character<span class="Special"> &lt;- </span>index *b, from-file
+<span class="muRecipe">recipe</span> make-move [
+  <span class="Constant">local-scope</span>
+  b:address:array:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  m:address:move<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  from-file:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">from-file:offset</span>
+  from-rank:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">from-rank:offset</span>
+  to-file:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">to-file:offset</span>
+  to-rank:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">to-rank:offset</span>
+  f:address:array:character<span class="Special"> &lt;- </span>index *b, from-file
   src:address:character/square<span class="Special"> &lt;- </span>index-address *f, from-rank
   f<span class="Special"> &lt;- </span>index *b, to-file
   dest:address:character/square<span class="Special"> &lt;- </span>index-address *f, to-rank
-  *dest<span class="Special"> &lt;- </span><span class="Identifier">copy</span> *src
-  *src<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 32/space
-  reply b/same-as-ingredient:0
+  *dest<span class="Special"> &lt;- </span>copy *src
+  *src<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
+  <span class="muControl">reply</span> b/same-as-ingredient:<span class="Constant">0</span>
 ]
 
-scenario making-a-move [
-  <span class="Identifier">assume</span>-screen 30/width, 12/height
+<span class="muScenario">scenario</span> making-a-move [
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span>
   run [
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> &lt;- </span>initial-position
-    3:address:move<span class="Special"> &lt;- </span><span class="Identifier">new</span> move:<span class="Identifier">type</span>
-    4:address:number<span class="Special"> &lt;- </span>get-address *3:address:move, from-file:offset
-    *4:address:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 6/g
-    5:address:number<span class="Special"> &lt;- </span>get-address *3:address:move, from-rank:offset
-    *5:address:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1/'2'
-    6:address:number<span class="Special"> &lt;- </span>get-address *3:address:move, to-file:offset
-    *6:address:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 6/g
-    7:address:number<span class="Special"> &lt;- </span>get-address *3:address:move, to-rank:offset
-    *7:address:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 3/'4'
-    2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board<span class="Special"> &lt;- </span>make-move 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board, 3:address:move
-    screen:address<span class="Special"> &lt;- </span><span class="Identifier">print</span>-board screen:address, 2:address:<span class="Identifier">array</span>:address:<span class="Identifier">array</span>:character/board
+    <span class="Constant">2</span>:address:array:address:array:character/board<span class="Special"> &lt;- </span>initial-position
+    <span class="Constant">3</span>:address:move<span class="Special"> &lt;- </span>new <span class="Constant">move:type</span>
+    <span class="Constant">4</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">3</span>:address:move, <span class="Constant">from-file:offset</span>
+    *<span class="Constant">4</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">6/g</span>
+    <span class="Constant">5</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">3</span>:address:move, <span class="Constant">from-rank:offset</span>
+    *<span class="Constant">5</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/'2'</span>
+    <span class="Constant">6</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">3</span>:address:move, <span class="Constant">to-file:offset</span>
+    *<span class="Constant">6</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">6/g</span>
+    <span class="Constant">7</span>:address:number<span class="Special"> &lt;- </span>get-address *<span class="Constant">3</span>:address:move, <span class="Constant">to-rank:offset</span>
+    *<span class="Constant">7</span>:address:number<span class="Special"> &lt;- </span>copy <span class="Constant">3/'4'</span>
+    <span class="Constant">2</span>:address:array:address:array:character/board<span class="Special"> &lt;- </span>make-move <span class="Constant">2</span>:address:array:address:array:character/board, <span class="Constant">3</span>:address:move
+    screen:address<span class="Special"> &lt;- </span>print-board screen:address, <span class="Constant">2</span>:address:array:address:array:character/board
   ]
   screen-should-contain [
   <span class="Comment">#  012345678901234567890123456789</span>
-    .8 | r n b q k b n r           .
-    .7 | p p p p p p p p           .
-    .6 |                           .
-    .5 |                           .
-    .4 |             P             .
-    .3 |                           .
-    .2 | P P P P P P   P           .
-    .1 | R N B Q K B N R           .
-    .  +----------------           .
-    .    a b c d e f g h           .
-    .                              .
+   <span class="Constant"> .8 | r n b q k b n r           .</span>
+   <span class="Constant"> .7 | p p p p p p p p           .</span>
+   <span class="Constant"> .6 |                           .</span>
+   <span class="Constant"> .5 |                           .</span>
+   <span class="Constant"> .4 |             P             .</span>
+   <span class="Constant"> .3 |                           .</span>
+   <span class="Constant"> .2 | P P P P P P   P           .</span>
+   <span class="Constant"> .1 | R N B Q K B N R           .</span>
+   <span class="Constant"> .  +----------------           .</span>
+   <span class="Constant"> .    a b c d e f g h           .</span>
+   <span class="Constant"> .                              .</span>
   ]
 ]
 </pre>
diff --git a/html/console.mu.html b/html/console.mu.html
index 203cbd20..116fb450 100644
--- a/html/console.mu.html
+++ b/html/console.mu.html
@@ -13,9 +13,12 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Delimiter { color: #a04060; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -28,19 +31,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: reading events from keyboard or mouse</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># Keeps printing 'a' until you press a key or click on the mouse.</span>
 
-recipe main [
+<span class="muRecipe">recipe</span> main [
   open-console
-  {
+  <span class="Delimiter">{</span>
     e:event, found?:boolean<span class="Special"> &lt;- </span>check-for-interaction
-    break-if found?
-    <span class="Identifier">print</span>-character-to-display 97, 7/white
-    loop
-  }
+    <span class="muControl">break-if</span> found?
+    print-character-to-display <span class="Constant">97</span>, <span class="Constant">7/white</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
   close-console
-  $<span class="Identifier">print</span> e, 10/newline
+  $print e, <span class="Constant">10/newline</span>
 ]
 </pre>
 </body>
diff --git a/html/counters.mu.html b/html/counters.mu.html
index 45ca7a5d..9a02adca 100644
--- a/html/counters.mu.html
+++ b/html/counters.mu.html
@@ -13,10 +13,11 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Underlined { color: #c000c0; text-decoration: underline; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -31,36 +32,36 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="Comment"># example program: maintain multiple counters with isolated lexical scopes</span>
 <span class="Comment"># (spaces)</span>
 
-recipe <span class="Identifier">new</span>-counter [
-  default-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 30
-  n:number<span class="Special"> &lt;- </span>next-ingredient
-  reply default-space
+<span class="muRecipe">recipe</span> new-counter [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">30</span>
+  n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply</span> <span class="Constant">default-space</span>
 ]
 
-recipe increment-counter [
-  <span class="Underlined">local</span>-scope
-  0:address:<span class="Identifier">array</span>:location/names:<span class="Identifier">new</span>-counter<span class="Special"> &lt;- </span>next-ingredient  <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span>
-  x:number<span class="Special"> &lt;- </span>next-ingredient
-  n:number/space:1<span class="Special"> &lt;- </span>add n:number/space:1, x
-  reply n:number/space:1
+<span class="muRecipe">recipe</span> increment-counter [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">0</span>:address:array:location/names:new-counter<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>  <span class="Comment"># setup outer space; it *must* come from 'new-counter'</span>
+  x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  n:number/space:<span class="Constant">1</span><span class="Special"> &lt;- </span>add n:number/space:<span class="Constant">1</span>, x
+  <span class="muControl">reply</span> n:number/space:<span class="Constant">1</span>
 ]
 
-recipe main [
-  <span class="Underlined">local</span>-scope
+<span class="muRecipe">recipe</span> main [
+  <span class="Constant">local-scope</span>
   <span class="Comment"># counter A</span>
-  a:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span>-counter 34
+  a:address:array:location<span class="Special"> &lt;- </span>new-counter <span class="Constant">34</span>
   <span class="Comment"># counter B</span>
-  b:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span>-counter 23
+  b:address:array:location<span class="Special"> &lt;- </span>new-counter <span class="Constant">23</span>
   <span class="Comment"># increment both by 2 but in different ways</span>
-  increment-counter a, 1
-  b-value:number<span class="Special"> &lt;- </span>increment-counter b, 2
-  a-value:number<span class="Special"> &lt;- </span>increment-counter a, 1
+  increment-counter a, <span class="Constant">1</span>
+  b-value:number<span class="Special"> &lt;- </span>increment-counter b, <span class="Constant">2</span>
+  a-value:number<span class="Special"> &lt;- </span>increment-counter a, <span class="Constant">1</span>
   <span class="Comment"># check results</span>
-  $<span class="Identifier">print</span> [Contents of counters
-]
+  $print <span class="Constant">[Contents of counters</span>
+<span class="Constant">]</span>
   <span class="Comment"># trailing space in next line is to help with syntax highlighting</span>
-  $<span class="Identifier">print</span> [a: ], a-value, [ b: ], b-value, [
-]
+  $print <span class="Constant">[a: ]</span>, a-value, <span class="Constant">[ b: ]</span>, b-value, <span class="Constant">[ </span>
+<span class="Constant">]</span>
 ]
 </pre>
 </body>
diff --git a/html/display.mu.html b/html/display.mu.html
index fea2d45a..ce820d27 100644
--- a/html/display.mu.html
+++ b/html/display.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -29,16 +30,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: managing the display</span>
 
-recipe main [
+<span class="muRecipe">recipe</span> main [
   open-console
-  <span class="Identifier">print</span>-character-to-display 97, 1/red, 2/green
-  1:number/<span class="Special">raw</span>, 2:number/<span class="Special">raw &lt;- </span>cursor-position-on-display
+  print-character-to-display <span class="Constant">97</span>, <span class="Constant">1/red</span>, <span class="Constant">2/green</span>
+  <span class="Constant">1</span>:number/<span class="Special">raw</span>, <span class="Constant">2</span>:number/<span class="Special">raw &lt;- </span>cursor-position-on-display
   wait-for-some-interaction
   clear-display
-  move-cursor-on-display 0, 4
-  <span class="Identifier">print</span>-character-to-display 98
+  move-cursor-on-display <span class="Constant">0</span>, <span class="Constant">4</span>
+  print-character-to-display <span class="Constant">98</span>
   wait-for-some-interaction
-  move-cursor-on-display 0, 0
+  move-cursor-on-display <span class="Constant">0</span>, <span class="Constant">0</span>
   clear-line-on-display
   wait-for-some-interaction
   move-cursor-down-on-display
diff --git a/html/edit.mu.html b/html/edit.mu.html
deleted file mode 100644
index d50b41f2..00000000
--- a/html/edit.mu.html
+++ /dev/null
@@ -1,6555 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - edit.mu</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="none">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.muRecipe { color: #ff8700; }
-.SalientComment { color: #00ffff; }
-.muScenario { color: #00af00; }
-.Comment { color: #9090ff; }
-.Constant { color: #00a0a0; }
-.Special { color: #ff6060; }
-.CommentedCode { color: #6c6c6c; }
-.Delimiter { color: #a04060; }
-.muControl { color: #c0a020; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment"># Environment for learning programming using mu: <a href="http://akkartik.name/post/mu">http://akkartik.name/post/mu</a></span>
-<span class="Comment">#</span>
-<span class="Comment"># Consists of one editor on the left for recipes and one on the right for the</span>
-<span class="Comment"># sandbox.</span>
-
-<span class="muRecipe">recipe</span> main [
-  <span class="Constant">local-scope</span>
-  open-console
-  initial-recipe:address:array:character<span class="Special"> &lt;- </span>restore <span class="Constant">[recipes.mu]</span>
-  initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  hide-screen <span class="Constant">0/screen</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox
-  env<span class="Special"> &lt;- </span>restore-sandboxes env
-  render-all <span class="Constant">0/screen</span>, env
-  event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env
-  <span class="Comment"># never gets here</span>
-]
-
-<span class="SalientComment">## the basic editor data structure, and how it displays text to the screen</span>
-
-<span class="muScenario">scenario</span> editor-initially-prints-string-to-screen [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  run [
-    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-container editor-data [
-  <span class="Comment"># editable text: doubly linked list of characters (head contains a special sentinel)</span>
-  data:address:duplex-list
-  top-of-screen:address:duplex-list
-  bottom-of-screen:address:duplex-list
-  <span class="Comment"># location before cursor inside data</span>
-  before-cursor:address:duplex-list
-
-  <span class="Comment"># raw bounds of display area on screen</span>
-  <span class="Comment"># always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen</span>
-  left:number
-  right:number
-  <span class="Comment"># raw screen coordinates of cursor</span>
-  cursor-row:number
-  cursor-column:number
-]
-
-<span class="Comment"># editor:address, screen &lt;- new-editor s:address:array:character, screen:address, left:number, right:number</span>
-<span class="Comment"># creates a new editor widget and renders its initial appearance to screen.</span>
-<span class="Comment">#   top/left/right constrain the screen area available to the new editor.</span>
-<span class="Comment">#   right is exclusive.</span>
-<span class="muRecipe">recipe</span> new-editor [
-  <span class="Constant">local-scope</span>
-  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># no clipping of bounds</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
-  result:address:editor-data<span class="Special"> &lt;- </span>new <span class="Constant">editor-data:type</span>
-  <span class="Comment"># initialize screen-related fields</span>
-  x:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">left:offset</span>
-  *x<span class="Special"> &lt;- </span>copy left
-  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">right:offset</span>
-  *x<span class="Special"> &lt;- </span>copy right
-  <span class="Comment"># initialize cursor</span>
-  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-row:offset</span>
-  *x<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
-  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-column:offset</span>
-  *x<span class="Special"> &lt;- </span>copy left
-  init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
-  *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span>
-  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">top-of-screen:offset</span>
-  *top-of-screen<span class="Special"> &lt;- </span>copy *init
-  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span>
-  *y<span class="Special"> &lt;- </span>copy *init
-  result<span class="Special"> &lt;- </span>insert-text result, s
-  <span class="Comment"># initialize cursor to top of screen</span>
-  y<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span>
-  *y<span class="Special"> &lt;- </span>copy *init
-  <span class="Comment"># initial render to screen, just for some old tests</span>
-  _, _, screen, result<span class="Special"> &lt;- </span>render screen, result
-<span class="Constant">  +editor-initialization</span>
-  <span class="muControl">reply</span> result
-]
-
-<span class="muRecipe">recipe</span> insert-text [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># early exit if text is empty</span>
-  <span class="muControl">reply-unless</span> text, editor/same-as-ingredient:<span class="Constant">0</span>
-  len:number<span class="Special"> &lt;- </span>length *text
-  <span class="muControl">reply-unless</span> len, editor/same-as-ingredient:<span class="Constant">0</span>
-  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="Comment"># now we can start appending the rest, character by character</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  <span class="Delimiter">{</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
-    <span class="muControl">break-if</span> done?
-    c:character<span class="Special"> &lt;- </span>index *text, idx
-    insert-duplex c, curr
-    <span class="Comment"># next iter</span>
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muScenario">scenario</span> editor-initializes-without-data [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span>
-  run [
-    <span class="Constant">1</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">0/data</span>, screen:address, <span class="Constant">2/left</span>, <span class="Constant">5/right</span>
-    <span class="Constant">2</span>:editor-data<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:editor-data
-  ]
-  memory-should-contain [
-    <span class="Comment"># 2 (data) &lt;- just the § sentinel</span>
-    <span class="Comment"># 3 (top of screen) &lt;- the § sentinel</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># bottom-of-screen; null since text fits on screen</span>
-    <span class="Comment"># 5 (before cursor) &lt;- the § sentinel</span>
-    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># left</span>
-    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># right  (inclusive)</span>
-    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="Comment"># last-row:number, last-column:number, screen, editor &lt;- render screen:address, editor:address:editor-data</span>
-<span class="Comment">#</span>
-<span class="Comment"># Assumes cursor should be at coordinates (cursor-row, cursor-column) and</span>
-<span class="Comment"># updates before-cursor to match. Might also move coordinates if they're</span>
-<span class="Comment"># outside text.</span>
-<span class="muRecipe">recipe</span> render [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  <span class="Comment"># traversing editor</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
-  prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span>
-  curr<span class="Special"> &lt;- </span>next-duplex curr
-  <span class="Comment"># traversing screen</span>
-<span class="Constant">  +render-loop-initialization</span>
-  color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
-  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
-  column:number<span class="Special"> &lt;- </span>copy left
-  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-  <span class="Delimiter">{</span>
-<span class="Constant">    +next-character</span>
-    <span class="muControl">break-unless</span> curr
-    off-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-    <span class="muControl">break-if</span> off-screen?
-    <span class="Comment"># update editor-data.before-cursor</span>
-    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
-    <span class="Comment"># the current character.</span>
-    <span class="Delimiter">{</span>
-      at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-      <span class="muControl">break-unless</span> at-cursor-row?
-      at-cursor?:boolean<span class="Special"> &lt;- </span>equal column, *cursor-column
-      <span class="muControl">break-unless</span> at-cursor?
-      *before-cursor<span class="Special"> &lt;- </span>copy prev
-    <span class="Delimiter">}</span>
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-<span class="Constant">    +character-c-received</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># newline? move to left rather than 0</span>
-      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-      <span class="muControl">break-unless</span> newline?
-      <span class="Comment"># adjust cursor if necessary</span>
-      <span class="Delimiter">{</span>
-        at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-        <span class="muControl">break-unless</span> at-cursor-row?
-        left-of-cursor?:boolean<span class="Special"> &lt;- </span>lesser-than column, *cursor-column
-        <span class="muControl">break-unless</span> left-of-cursor?
-        *cursor-column<span class="Special"> &lt;- </span>copy column
-        *before-cursor<span class="Special"> &lt;- </span>prev-duplex curr
-      <span class="Delimiter">}</span>
-      <span class="Comment"># clear rest of line in this window</span>
-      clear-line-delimited screen, column, right
-      <span class="Comment"># skip to next line</span>
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      column<span class="Special"> &lt;- </span>copy left
-      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-      curr<span class="Special"> &lt;- </span>next-duplex curr
-      prev<span class="Special"> &lt;- </span>next-duplex prev
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
-      <span class="Comment"># room for clicking on the cursor after it.</span>
-      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
-      <span class="muControl">break-unless</span> at-right?
-      <span class="Comment"># print wrap icon</span>
-      print-character screen, <span class="Constant">8617/loop-back-to-left</span>, <span class="Constant">245/grey</span>
-      column<span class="Special"> &lt;- </span>copy left
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-      <span class="Comment"># don't increment curr</span>
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
-    <span class="Delimiter">}</span>
-    print-character screen, c, color
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    prev<span class="Special"> &lt;- </span>next-duplex prev
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># save first character off-screen</span>
-  bottom-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">bottom-of-screen:offset</span>
-  *bottom-of-screen<span class="Special"> &lt;- </span>copy curr
-  <span class="Comment"># is cursor to the right of the last line? move to end</span>
-  <span class="Delimiter">{</span>
-    at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-    cursor-outside-line?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column, *cursor-column
-    before-cursor-on-same-line?:boolean<span class="Special"> &lt;- </span>and at-cursor-row?, cursor-outside-line?
-    above-cursor-row?:boolean<span class="Special"> &lt;- </span>lesser-than row, *cursor-row
-    before-cursor?:boolean<span class="Special"> &lt;- </span>or before-cursor-on-same-line?, above-cursor-row?
-    <span class="muControl">break-unless</span> before-cursor?
-    *cursor-row<span class="Special"> &lt;- </span>copy row
-    *cursor-column<span class="Special"> &lt;- </span>copy column
-    *before-cursor<span class="Special"> &lt;- </span>copy prev
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>
-]
-
-<span class="Comment"># row, screen &lt;- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number</span>
-<span class="Comment"># move cursor at start of next line</span>
-<span class="Comment"># print a string 's' to 'editor' in 'color' starting at 'row'</span>
-<span class="Comment"># clear rest of last line, but don't move cursor to next line</span>
-<span class="muRecipe">recipe</span> render-string [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-  column:number<span class="Special"> &lt;- </span>copy left
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  len:number<span class="Special"> &lt;- </span>length *s
-  <span class="Delimiter">{</span>
-<span class="Constant">    +next-character</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    <span class="muControl">break-if</span> done?
-    done?<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-    <span class="muControl">break-if</span> done?
-    c:character<span class="Special"> &lt;- </span>index *s, i
-    <span class="Delimiter">{</span>
-      <span class="Comment"># at right? wrap.</span>
-      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
-      <span class="muControl">break-unless</span> at-right?
-      <span class="Comment"># print wrap icon</span>
-      print-character screen, <span class="Constant">8617/loop-back-to-left</span>, <span class="Constant">245/grey</span>
-      column<span class="Special"> &lt;- </span>copy left
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>  <span class="Comment"># retry i</span>
-    <span class="Delimiter">}</span>
-    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># newline? move to left rather than 0</span>
-      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-      <span class="muControl">break-unless</span> newline?
-      <span class="Comment"># clear rest of line in this window</span>
-      <span class="Delimiter">{</span>
-        done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
-        <span class="muControl">break-if</span> done?
-        print-character screen, <span class="Constant">32/space</span>
-        column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-        <span class="muControl">loop</span>
-      <span class="Delimiter">}</span>
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      column<span class="Special"> &lt;- </span>copy left
-      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
-    <span class="Delimiter">}</span>
-    print-character screen, c, color
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># clear rest of current line</span>
-    line-done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
-    <span class="muControl">break-if</span> line-done?
-    print-character screen, <span class="Constant">32/space</span>
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> clear-line-delimited [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
-    <span class="muControl">break-if</span> done?
-    print-character screen, <span class="Constant">32/space</span>
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> clear-screen-from [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># if it's the real screen, use the optimized primitive</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> screen
-    clear-display-from row, column, left, right
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if not, go the slower route</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-  clear-line-delimited screen, column, right
-  clear-rest-of-screen screen, row, left, right
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> clear-rest-of-screen [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Delimiter">{</span>
-    at-bottom-of-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-    <span class="muControl">break-if</span> at-bottom-of-screen?
-    screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
-    clear-line-delimited screen, left, right
-    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-initially-prints-multiple-lines [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .abc  .</span>
-   <span class="Constant"> .def  .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-initially-handles-offsets [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> . abc .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-initially-prints-multiple-lines-at-offset [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> . abc .</span>
-   <span class="Constant"> . def .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-initially-wraps-long-lines [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc def]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .abc ↩.</span>
-   <span class="Constant"> .def  .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">245/grey</span> [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .    ↩.</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-initially-wraps-barely-long-lines [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  ]
-  <span class="Comment"># still wrap, even though the line would fit. We need room to click on the</span>
-  <span class="Comment"># end of the line</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-<span class="Constant">    .abcd↩.</span>
-   <span class="Constant"> .e    .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">245/grey</span> [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .    ↩.</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-initializes-empty-text [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-    <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
-  ]
-]
-
-<span class="Comment"># just a little color for mu code</span>
-
-<span class="muScenario">scenario</span> render-colors-comments [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant"># de</span>
-<span class="Constant">f]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .abc  .</span>
-   <span class="Constant"> .# de .</span>
-   <span class="Constant"> .f    .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">12/lightblue</span>, [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .# de .</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">7/white</span>, [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .abc  .</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .f    .</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +character-c-received [
-  color<span class="Special"> &lt;- </span>get-color color, c
-]
-
-<span class="Comment"># color &lt;- get-color color:number, c:character</span>
-<span class="Comment"># so far the previous color is all the information we need; that may change</span>
-<span class="muRecipe">recipe</span> get-color [
-  <span class="Constant">local-scope</span>
-  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color-is-white?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">7/white</span>
-<span class="CommentedCode">#?   $print [character: ], c, 10/newline #? 1</span>
-  <span class="Comment"># if color is white and next character is '#', switch color to blue</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> color-is-white?
-    starting-comment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">35/#</span>
-    <span class="muControl">break-unless</span> starting-comment?
-<span class="CommentedCode">#?     $print [switch color back to blue], 10/newline #? 1</span>
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">12/lightblue</span>
-    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if color is blue and next character is newline, switch color to white</span>
-  <span class="Delimiter">{</span>
-    color-is-blue?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">12/lightblue</span>
-    <span class="muControl">break-unless</span> color-is-blue?
-    ending-comment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-unless</span> ending-comment?
-<span class="CommentedCode">#?     $print [switch color back to white], 10/newline #? 1</span>
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
-    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if color is white (no comments) and next character is '&lt;', switch color to red</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> color-is-white?
-    starting-assignment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">60/&lt;</span>
-    <span class="muControl">break-unless</span> starting-assignment?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">1/red</span>
-    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if color is red and next character is space, switch color to white</span>
-  <span class="Delimiter">{</span>
-    color-is-red?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">1/red</span>
-    <span class="muControl">break-unless</span> color-is-red?
-    ending-assignment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span>
-    <span class="muControl">break-unless</span> ending-assignment?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
-    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># otherwise no change</span>
-<span class="Constant">  +exit</span>
-  <span class="muControl">reply</span> color
-]
-
-<span class="muScenario">scenario</span> render-colors-assignment [
-  assume-screen <span class="Constant">8/width</span>, <span class="Constant">5/height</span>
-  run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d &lt;- e</span>
-<span class="Constant">f]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">8/right</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .        .</span>
-   <span class="Constant"> .abc     .</span>
-   <span class="Constant"> .d &lt;- e  .</span>
-   <span class="Constant"> .f       .</span>
-   <span class="Constant"> .        .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">1/red</span>, [
-   <span class="Constant"> .        .</span>
-   <span class="Constant"> .        .</span>
-   <span class="Constant"> .  &lt;-    .</span>
-   <span class="Constant"> .        .</span>
-   <span class="Constant"> .        .</span>
-  ]
-]
-
-<span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span>
-
-<span class="muRecipe">recipe</span> editor-event-loop [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span>
-<span class="Constant">    +next-event</span>
-    e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console
-    <span class="muControl">loop-unless</span> found?
-    <span class="muControl">break-if</span> quit?  <span class="Comment"># only in tests</span>
-    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
-    <span class="Comment"># 'touch' event</span>
-    t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e, <span class="Constant">touch:variant</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-unless</span> t
-      move-cursor-in-editor screen, editor, *t
-      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># keyboard events</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> t
-      screen, editor, go-render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, editor, e
-      <span class="Delimiter">{</span>
-        <span class="muControl">break-unless</span> go-render?
-        editor-render screen, editor
-      <span class="Delimiter">}</span>
-    <span class="Delimiter">}</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># screen, editor, go-render?:boolean &lt;- handle-keyboard-event screen:address, editor:address:editor-data, e:event</span>
-<span class="Comment"># Process an event 'e' and try to minimally update the screen.</span>
-<span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span>
-<span class="muRecipe">recipe</span> handle-keyboard-event [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  e:event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="muControl">reply-unless</span> editor, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  save-row:number<span class="Special"> &lt;- </span>copy *cursor-row
-  save-column:number<span class="Special"> &lt;- </span>copy *cursor-column
-  <span class="Comment"># character</span>
-  <span class="Delimiter">{</span>
-    c:address:character<span class="Special"> &lt;- </span>maybe-convert e, <span class="Constant">text:variant</span>
-    <span class="muControl">break-unless</span> c
-<span class="CommentedCode">#?     trace 10, [app], [handle-keyboard-event: special character] #? 1</span>
-    <span class="Comment"># exceptions for special characters go here</span>
-<span class="Constant">    +handle-special-character</span>
-    <span class="Comment"># ignore any other special characters</span>
-    regular-character?:boolean<span class="Special"> &lt;- </span>greater-or-equal *c, <span class="Constant">32/space</span>
-    newline?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">10/newline</span>
-    regular-character?<span class="Special"> &lt;- </span>or regular-character?, newline?
-    <span class="muControl">reply-unless</span> regular-character?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-    <span class="Comment"># otherwise type it in</span>
-    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, *c, screen
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
-  <span class="Delimiter">}</span>
-  <span class="Comment"># special key to modify the text or move the cursor</span>
-  k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span>
-  assert k, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
-  <span class="Comment"># handlers for each special key will go here</span>
-<span class="Constant">  +handle-special-key</span>
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-]
-
-<span class="Comment"># process click, return if it was on current editor</span>
-<span class="Comment"># todo: ignores menu bar (for now just displays shortcuts)</span>
-<span class="muRecipe">recipe</span> move-cursor-in-editor [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="muControl">reply-unless</span> editor, <span class="Constant">0/false</span>
-  click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  too-far-left?:boolean<span class="Special"> &lt;- </span>lesser-than click-column, left
-  <span class="muControl">reply-if</span> too-far-left?, <span class="Constant">0/false</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  too-far-right?:boolean<span class="Special"> &lt;- </span>greater-than click-column, right
-  <span class="muControl">reply-if</span> too-far-right?, <span class="Constant">0/false</span>
-  <span class="Comment"># position cursor</span>
-<span class="CommentedCode">#?   trace 1, [print-character], [foo] #? 1</span>
-  click-row:number<span class="Special"> &lt;- </span>get t, <span class="Constant">row:offset</span>
-  click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span>
-  editor<span class="Special"> &lt;- </span>snap-cursor screen, editor, click-row, click-column
-<span class="CommentedCode">#?   trace 1, [print-character], [foo done] #? 1</span>
-  <span class="Comment"># gain focus</span>
-  <span class="muControl">reply</span> <span class="Constant">1/true</span>
-]
-
-<span class="Comment"># editor &lt;- snap-cursor screen:address, editor:address:editor-data, target-row:number, target-column:number</span>
-<span class="Comment">#</span>
-<span class="Comment"># Variant of 'render' that only moves the cursor (coordinates and</span>
-<span class="Comment"># before-cursor). If it's past the end of a line, it 'slides' it left. If it's</span>
-<span class="Comment"># past the last line it positions at end of last line.</span>
-<span class="muRecipe">recipe</span> snap-cursor [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  target-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  target-column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, editor/same-as-ingredient:<span class="Constant">1</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Comment"># count newlines until screen row</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
-  prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span>
-  curr<span class="Special"> &lt;- </span>next-duplex curr
-  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
-  column:number<span class="Special"> &lt;- </span>copy left
-  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
-  *cursor-row<span class="Special"> &lt;- </span>copy target-row
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  *cursor-column<span class="Special"> &lt;- </span>copy target-column
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  <span class="Delimiter">{</span>
-<span class="Constant">    +next-character</span>
-    <span class="muControl">break-unless</span> curr
-    off-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-    <span class="muControl">break-if</span> off-screen?
-    <span class="Comment"># update editor-data.before-cursor</span>
-    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
-    <span class="Comment"># the current character.</span>
-    <span class="Delimiter">{</span>
-      at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-      <span class="muControl">break-unless</span> at-cursor-row?
-      at-cursor?:boolean<span class="Special"> &lt;- </span>equal column, *cursor-column
-      <span class="muControl">break-unless</span> at-cursor?
-      *before-cursor<span class="Special"> &lt;- </span>copy prev
-    <span class="Delimiter">}</span>
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># newline? move to left rather than 0</span>
-      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-      <span class="muControl">break-unless</span> newline?
-      <span class="Comment"># adjust cursor if necessary</span>
-      <span class="Delimiter">{</span>
-        at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-        <span class="muControl">break-unless</span> at-cursor-row?
-        left-of-cursor?:boolean<span class="Special"> &lt;- </span>lesser-than column, *cursor-column
-        <span class="muControl">break-unless</span> left-of-cursor?
-        *cursor-column<span class="Special"> &lt;- </span>copy column
-        *before-cursor<span class="Special"> &lt;- </span>copy prev
-      <span class="Delimiter">}</span>
-      <span class="Comment"># skip to next line</span>
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      column<span class="Special"> &lt;- </span>copy left
-      curr<span class="Special"> &lt;- </span>next-duplex curr
-      prev<span class="Special"> &lt;- </span>next-duplex prev
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
-      <span class="Comment"># room for clicking on the cursor after it.</span>
-      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
-      <span class="muControl">break-unless</span> at-right?
-      column<span class="Special"> &lt;- </span>copy left
-      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-      <span class="Comment"># don't increment curr/prev</span>
-      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
-    <span class="Delimiter">}</span>
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    prev<span class="Special"> &lt;- </span>next-duplex prev
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># is cursor to the right of the last line? move to end</span>
-  <span class="Delimiter">{</span>
-    at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
-    cursor-outside-line?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column, *cursor-column
-    before-cursor-on-same-line?:boolean<span class="Special"> &lt;- </span>and at-cursor-row?, cursor-outside-line?
-    above-cursor-row?:boolean<span class="Special"> &lt;- </span>lesser-than row, *cursor-row
-    before-cursor?:boolean<span class="Special"> &lt;- </span>or before-cursor-on-same-line?, above-cursor-row?
-    <span class="muControl">break-unless</span> before-cursor?
-    *cursor-row<span class="Special"> &lt;- </span>copy row
-    *cursor-column<span class="Special"> &lt;- </span>copy column
-    *before-cursor<span class="Special"> &lt;- </span>copy prev
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">1</span>
-]
-
-<span class="muRecipe">recipe</span> insert-at-cursor [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  insert-duplex c, *before-cursor
-  *before-cursor<span class="Special"> &lt;- </span>next-duplex *before-cursor
-  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  save-row:number<span class="Special"> &lt;- </span>copy *cursor-row
-  save-column:number<span class="Special"> &lt;- </span>copy *cursor-column
-  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Comment"># occasionally we'll need to mess with the cursor</span>
-<span class="Constant">  +insert-character-special-case</span>
-  <span class="Comment"># but mostly we'll just move the cursor right</span>
-  *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
-  next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-  <span class="Delimiter">{</span>
-    <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span>
-    at-end?:boolean<span class="Special"> &lt;- </span>equal next, <span class="Constant">0/null</span>
-    <span class="muControl">break-unless</span> at-end?
-    bottom:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1</span>
-    at-bottom?:boolean<span class="Special"> &lt;- </span>equal save-row, bottom
-    at-right?:boolean<span class="Special"> &lt;- </span>equal save-column, right
-    overflow?:boolean<span class="Special"> &lt;- </span>and at-bottom?, at-right?
-    <span class="muControl">break-if</span> overflow?
-    move-cursor screen, save-row, save-column
-    print-character screen, c
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># not at right margin? print the character and rest of line</span>
-    <span class="muControl">break-unless</span> next
-    at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, screen-width
-    <span class="muControl">break-if</span> at-right?
-    curr:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
-    move-cursor screen, save-row, save-column
-    curr-column:number<span class="Special"> &lt;- </span>copy save-column
-    <span class="Delimiter">{</span>
-      <span class="Comment"># hit right margin? give up and let caller render</span>
-      at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width
-      <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
-      <span class="muControl">break-unless</span> curr
-      <span class="Comment"># newline? done.</span>
-      currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-      at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-      <span class="muControl">break-if</span> at-newline?
-      print-character screen, currc
-      curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
-      curr<span class="Special"> &lt;- </span>next-duplex curr
-      <span class="muControl">loop</span>
-    <span class="Delimiter">}</span>
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
-]
-
-<span class="Comment"># helper for tests</span>
-<span class="muRecipe">recipe</span> editor-render [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  row:number, column:number<span class="Special"> &lt;- </span>render screen, editor
-  clear-line-delimited screen, column, right
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  clear-screen-from screen, row, left, left, right
-]
-
-<span class="muScenario">scenario</span> editor-handles-empty-event-queue [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-  assume-console <span class="Constant">[]</span>
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-handles-mouse-clicks [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>  <span class="Comment"># on the 'b'</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor is at row 0..</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># ..and column 1</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">7</span>  <span class="Comment"># last line, to the right of text</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">7</span>  <span class="Comment"># interior line, to the right of text</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">7</span>  <span class="Comment"># below text</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Comment"># editor occupies only left half of screen</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    <span class="Comment"># click on right half of screen</span>
-    left-click <span class="Constant">3</span>, <span class="Constant">8</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># no change to cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># ..or column</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    type <span class="Constant">[abc]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># type two letters at different places</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
-    type <span class="Constant">[d]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .0adbc     .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">7</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># 4 for first letter, 3 for second</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">5</span>  <span class="Comment"># right of last line</span>
-    type <span class="Constant">[d]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">5</span>  <span class="Comment"># right of non-last line</span>
-    type <span class="Constant">[e]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abce      .</span>
-   <span class="Constant"> .d         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
-    type <span class="Constant">[d]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
-    type <span class="Constant">[e]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .de        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
-    type <span class="Constant">[ef]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .def       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-  assume-console [
-    type <span class="Constant">[01]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .01ab      .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="Comment"># if the cursor reaches the right margin, wrap the line</span>
-
-<span class="muScenario">scenario</span> editor-wraps-line-on-insert [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-  <span class="Comment"># type a letter</span>
-  assume-console [
-    type <span class="Constant">[e]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># no wrap yet</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .eabc .</span>
-<span class="Constant">    .┈┈┈┈┈.</span>
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  <span class="Comment"># type a second letter</span>
-  assume-console [
-    type <span class="Constant">[f]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># now wrap</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-<span class="Constant">    .efab↩.</span>
-   <span class="Constant"> .c    .</span>
-<span class="Constant">    .┈┈┈┈┈.</span>
-   <span class="Constant"> .     .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +insert-character-special-case [
-  <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># if we're at the column just before the wrap indicator</span>
-    wrap-column:number<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
-    at-wrap?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, wrap-column
-    <span class="muControl">break-unless</span> at-wrap?
-    *cursor-column<span class="Special"> &lt;- </span>subtract *cursor-column, wrap-column
-    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
-    <span class="Comment"># if we're out of the screen, scroll down</span>
-    <span class="Delimiter">{</span>
-      below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height
-      <span class="muControl">break-unless</span> below-screen?
-<span class="Constant">      +scroll-down</span>
-    <span class="Delimiter">}</span>
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">4</span>  <span class="Comment"># line is full; no wrap icon yet</span>
-    type <span class="Constant">[f]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .fe        .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor column</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>  <span class="Comment"># right before the wrap icon</span>
-    type <span class="Constant">[f]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcf↩     .</span>
-   <span class="Constant"> .de        .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
-  ]
-]
-
-<span class="Comment"># if newline, move cursor to start of next line, and maybe align indent with previous line</span>
-
-container editor-data [
-  indent:boolean
-]
-
-<span class="muRecipe">after</span> +editor-initialization [
-  indent:address:boolean<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">indent:offset</span>
-  *indent<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  assume-console [
-    type <span class="Constant">[0</span>
-<span class="Constant">1]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .0         .</span>
-   <span class="Constant"> .1abc      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +insert-character-special-case [
-  <span class="Delimiter">{</span>
-    newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-unless</span> newline?
-    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
-    *cursor-column<span class="Special"> &lt;- </span>copy left
-    <span class="Delimiter">{</span>
-      below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal, never greater</span>
-      <span class="muControl">break-unless</span> below-screen?
-<span class="Constant">      +scroll-down</span>
-      *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># indent if necessary</span>
-    indent?:boolean<span class="Special"> &lt;- </span>get *editor, <span class="Constant">indent:offset</span>
-    <span class="muControl">reply-unless</span> indent?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
-    d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-    end-of-previous-line:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
-    indent:number<span class="Special"> &lt;- </span>line-indent end-of-previous-line, d
-    i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-    <span class="Delimiter">{</span>
-      indent-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, indent
-      <span class="muControl">break-if</span> indent-done?
-      insert-at-cursor editor, <span class="Constant">32/space</span>, screen
-      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-      <span class="muControl">loop</span>
-    <span class="Delimiter">}</span>
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
-<span class="Comment"># the number of spaces at the start of the line containing 'curr'.</span>
-<span class="muRecipe">recipe</span> line-indent [
-  <span class="Constant">local-scope</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="muControl">reply-unless</span> curr, result
-  at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
-  <span class="muControl">reply-if</span> at-start?, result
-  <span class="Delimiter">{</span>
-    curr<span class="Special"> &lt;- </span>prev-duplex curr
-    <span class="muControl">break-unless</span> curr
-    at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
-    <span class="muControl">break-if</span> at-start?
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-newline?
-    <span class="Comment"># if c is a space, increment result</span>
-    is-space?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-unless</span> is-space?
-      result<span class="Special"> &lt;- </span>add result, <span class="Constant">1</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># if c is not a space, reset result</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> is-space?
-      result<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-    <span class="Delimiter">}</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> result
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span>
-  assume-console [
-    type <span class="Constant">[0</span>
-<span class="Constant">1]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> . 0        .</span>
-   <span class="Constant"> . 1abc     .</span>
-   <span class="Constant"> . ┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># press just a 'newline'</span>
-  assume-console [
-    type [
-]
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .e         .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># line should be fully cleared</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .e         .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-inserts-indent-after-newline [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
-<span class="Constant">  cd</span>
-<span class="Constant">ef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># position cursor after 'cd' and hit 'newline'</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">8</span>
-    type [
-]
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor should be below start of previous line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column (indented)</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-skips-indent-around-paste [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
-<span class="Constant">  cd</span>
-<span class="Constant">ef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># position cursor after 'cd' and hit 'newline' surrounded by paste markers</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">8</span>
-    press <span class="Constant">65507</span>  <span class="Comment"># start paste</span>
-    type [
-]
-    press <span class="Constant">65506</span>  <span class="Comment"># end paste</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor should be below start of previous line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column (not indented)</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    paste-start?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65507/paste-start</span>
-    <span class="muControl">break-unless</span> paste-start?
-    indent:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent:offset</span>
-    *indent<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    paste-end?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65506/paste-end</span>
-    <span class="muControl">break-unless</span> paste-end?
-    indent:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent:offset</span>
-    *indent<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="SalientComment">## special shortcuts for manipulating the editor</span>
-<span class="Comment"># Some keys on the keyboard generate unicode characters, others generate</span>
-<span class="Comment"># terminfo key codes. We need to modify different places in the two cases.</span>
-
-<span class="Comment"># tab - insert two spaces</span>
-
-<span class="muScenario">scenario</span> editor-inserts-two-spaces-on-tab [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># just one character in final line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
-<span class="Constant">cd]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  assume-console [
-    type <span class="Constant">[»]</span>
-  ]
-  <span class="Constant">3</span>:event/tab<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">9/tab</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">187/»</span>, <span class="Constant">3</span>:event/tab
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .  ab      .</span>
-   <span class="Constant"> .cd        .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    tab?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">9/tab</span>
-    <span class="muControl">break-unless</span> tab?
-    insert-at-cursor editor, <span class="Constant">32/space</span>, screen
-    insert-at-cursor editor, <span class="Constant">32/space</span>, screen
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># backspace - delete character before cursor</span>
-
-<span class="muScenario">scenario</span> editor-handles-backspace-key [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    type <span class="Constant">[«]</span>
-  ]
-  <span class="Constant">3</span>:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">8/backspace</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">171/«</span>, <span class="Constant">3</span>:event/backspace
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .bc        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of original line to overwrite</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    backspace?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">8/backspace</span>
-    <span class="muControl">break-unless</span> backspace?
-    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>delete-before-cursor editor, screen
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> delete-before-cursor [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  <span class="Comment"># if at start of text (before-cursor at § sentinel), return</span>
-  prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
-  <span class="muControl">reply-unless</span> prev, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-<span class="CommentedCode">#?   trace 10, [app], [delete-before-cursor] #? 1</span>
-  original-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
-  editor, scroll?:boolean<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor
-  remove-duplex *before-cursor
-  *before-cursor<span class="Special"> &lt;- </span>copy prev
-  <span class="muControl">reply-if</span> scroll?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>
-  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
-  cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
-  cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span>
-  <span class="Comment"># did we just backspace over a newline?</span>
-  same-row?:boolean<span class="Special"> &lt;- </span>equal cursor-row, original-row
-  <span class="muControl">reply-unless</span> same-row?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-  screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
-  curr-column:number<span class="Special"> &lt;- </span>copy cursor-column
-  <span class="Delimiter">{</span>
-    <span class="Comment"># hit right margin? give up and let caller render</span>
-    at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width
-    <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="muControl">break-unless</span> curr
-    <span class="Comment"># newline? done.</span>
-    currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-newline?
-    screen<span class="Special"> &lt;- </span>print-character screen, currc
-    curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># we're guaranteed not to be at the right margin</span>
-  screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-]
-
-<span class="muRecipe">recipe</span> move-cursor-coordinates-left [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  before-cursor:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span>
-  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  <span class="Comment"># if not at left margin, move one character left</span>
-  <span class="Delimiter">{</span>
-    at-left-margin?:boolean<span class="Special"> &lt;- </span>equal *cursor-column, left
-    <span class="muControl">break-if</span> at-left-margin?
-<span class="CommentedCode">#?     trace 10, [app], [decrementing cursor column] #? 1</span>
-    *cursor-column<span class="Special"> &lt;- </span>subtract *cursor-column, <span class="Constant">1</span>
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if at left margin, we must move to previous row:</span>
-  top-of-screen?:boolean<span class="Special"> &lt;- </span>equal *cursor-row, <span class="Constant">1</span>  <span class="Comment"># exclude menu bar</span>
-  go-render?:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> top-of-screen?
-    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> top-of-screen?
-<span class="Constant">    +scroll-up</span>
-    go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># case 1: if previous character was newline, figure out how long the previous line is</span>
-    previous-character:character<span class="Special"> &lt;- </span>get *before-cursor, <span class="Constant">value:offset</span>
-    previous-character-is-newline?:boolean<span class="Special"> &lt;- </span>equal previous-character, <span class="Constant">10/newline</span>
-    <span class="muControl">break-unless</span> previous-character-is-newline?
-    <span class="Comment"># compute length of previous line</span>
-<span class="CommentedCode">#?     trace 10, [app], [switching to previous line] #? 1</span>
-    d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-    end-of-line:number<span class="Special"> &lt;- </span>previous-line-length before-cursor, d
-    *cursor-column<span class="Special"> &lt;- </span>add left, end-of-line
-    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render?
-  <span class="Delimiter">}</span>
-  <span class="Comment"># case 2: if previous-character was not newline, we're just at a wrapped line</span>
-<span class="CommentedCode">#?   trace 10, [app], [wrapping to previous line] #? 1</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  *cursor-column<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>  <span class="Comment"># leave room for wrap icon</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render?
-]
-
-<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
-<span class="Comment"># the length of the previous line before the 'curr' pointer.</span>
-<span class="muRecipe">recipe</span> previous-line-length [
-  <span class="Constant">local-scope</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="muControl">reply-unless</span> curr, result
-  at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
-  <span class="muControl">reply-if</span> at-start?, result
-  <span class="Delimiter">{</span>
-    curr<span class="Special"> &lt;- </span>prev-duplex curr
-    <span class="muControl">break-unless</span> curr
-    at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
-    <span class="muControl">break-if</span> at-start?
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-newline?
-    result<span class="Special"> &lt;- </span>add result, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> result
-]
-
-<span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># just one character in final line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
-<span class="Constant">cd]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">0</span>  <span class="Comment"># cursor at only character in final line</span>
-    type <span class="Constant">[«]</span>
-  ]
-  <span class="Constant">3</span>:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">8/backspace</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">171/«</span>, <span class="Constant">3</span>:event/backspace
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-  ]
-]
-
-<span class="Comment"># delete - delete character at cursor</span>
-
-<span class="muScenario">scenario</span> editor-handles-delete-key [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    press <span class="Constant">65522</span>  <span class="Comment"># delete</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .bc        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of original line to overwrite</span>
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    press <span class="Constant">65522</span>  <span class="Comment"># delete</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># new length to overwrite</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    delete?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65522/delete</span>
-    <span class="muControl">break-unless</span> delete?
-    curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-    <span class="muControl">reply-unless</span> curr, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-    currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    remove-duplex curr
-    deleted-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-    <span class="muControl">reply-if</span> deleted-newline?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="Comment"># wasn't a newline? render rest of line</span>
-    curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor  <span class="Comment"># refresh after remove-duplex above</span>
-    screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
-    curr-column:number<span class="Special"> &lt;- </span>copy *cursor-column
-    <span class="Delimiter">{</span>
-      <span class="Comment"># hit right margin? give up and let caller render</span>
-      at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width
-      <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-      <span class="muControl">break-unless</span> curr
-      <span class="Comment"># newline? done.</span>
-      currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-      at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-      <span class="muControl">break-if</span> at-newline?
-      screen<span class="Special"> &lt;- </span>print-character screen, currc
-      curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
-      curr<span class="Special"> &lt;- </span>next-duplex curr
-      <span class="muControl">loop</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># we're guaranteed not to be at the right margin</span>
-    screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span>
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># right arrow</span>
-
-<span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a0bc      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># 0 and following characters</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    move-to-next-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65514/right-arrow</span>
-    <span class="muControl">break-unless</span> move-to-next-character?
-    <span class="Comment"># if not at end of text</span>
-    old-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-    <span class="muControl">break-unless</span> old-cursor
-    <span class="Comment"># scan to next character</span>
-    *before-cursor<span class="Special"> &lt;- </span>copy old-cursor
-    <span class="Comment"># if crossed a newline, move cursor to start of next row</span>
-    <span class="Delimiter">{</span>
-      old-cursor-character:character<span class="Special"> &lt;- </span>get **before-cursor, <span class="Constant">value:offset</span>
-      was-at-newline?:boolean<span class="Special"> &lt;- </span>equal old-cursor-character, <span class="Constant">10/newline</span>
-      <span class="muControl">break-unless</span> was-at-newline?
-      *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
-      *cursor-column<span class="Special"> &lt;- </span>copy left
-      below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal</span>
-      screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
-      <span class="muControl">reply-unless</span> below-screen?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-<span class="Constant">      +scroll-down</span>
-      *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># if the line wraps, move cursor to start of next row</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># if we're at the column just before the wrap indicator</span>
-      wrap-column:number<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
-      at-wrap?:boolean<span class="Special"> &lt;- </span>equal *cursor-column, wrap-column
-      <span class="muControl">break-unless</span> at-wrap?
-      <span class="Comment"># and if next character isn't newline</span>
-      new-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex old-cursor
-      <span class="muControl">break-unless</span> new-cursor
-      next-character:character<span class="Special"> &lt;- </span>get *new-cursor, <span class="Constant">value:offset</span>
-      newline?:boolean<span class="Special"> &lt;- </span>equal next-character, <span class="Constant">10/newline</span>
-      <span class="muControl">break-if</span> newline?
-      *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
-      *cursor-column<span class="Special"> &lt;- </span>copy left
-      below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal</span>
-      screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
-      <span class="muControl">reply-unless</span> below-screen?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-<span class="Constant">      +scroll-down</span>
-      *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># otherwise move cursor one character right</span>
-    *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
-    screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># type right-arrow a few times to get to start of second line</span>
-  assume-console [
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow - next line</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  <span class="Comment"># type something and ensure it goes where it should</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .0d        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># new length of second line</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-  assume-console [
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow - next line</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> . abc      .</span>
-   <span class="Constant"> . 0d       .</span>
-   <span class="Constant"> . ┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># line just barely wrapping</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># position cursor at last character before wrap and hit right-arrow</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  <span class="Comment"># now hit right arrow again</span>
-  assume-console [
-    press <span class="Constant">65514</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">6/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">4</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> . abcd↩    .</span>
-   <span class="Constant"> . ef       .</span>
-   <span class="Constant"> . ┈┈┈┈┈    .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow - next line</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .0d        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="Comment"># left arrow</span>
-
-<span class="muScenario">scenario</span> editor-moves-cursor-left-with-key [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a0bc      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    move-to-previous-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65515/left-arrow</span>
-    <span class="muControl">break-unless</span> move-to-previous-character?
-<span class="CommentedCode">#?     trace 10, [app], [left arrow] #? 1</span>
-    <span class="Comment"># if not at start of text (before-cursor at § sentinel)</span>
-    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
-    <span class="muControl">reply-unless</span> prev, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-    editor, go-render?<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor
-    *before-cursor<span class="Special"> &lt;- </span>copy prev
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize editor with two lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># position cursor at start of second line (so there's no previous newline)</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize editor with three lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def</span>
-<span class="Constant">g]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># position cursor further down (so there's a newline before the character at</span>
-  <span class="Comment"># the cursor)</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .def0      .</span>
-   <span class="Constant"> .g         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># just the '0'</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def</span>
-<span class="Constant">g]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># position cursor at start of text</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">0</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow should have no effect</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .0abc      .</span>
-   <span class="Constant"> .def       .</span>
-   <span class="Constant"> .g         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-  check-trace-count-for-label <span class="Constant">4</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of first line</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize editor with text containing an empty line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-
-d]
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># position cursor right after empty line</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .0         .</span>
-   <span class="Constant"> .d         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># just the '0'</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-across-screen-lines-across-wrap-with-left-arrow [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize editor with text containing an empty line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-   <span class="Constant"> .          .</span>
-  ]
-  <span class="Comment"># position cursor right after empty line</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># previous row</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># end of wrapped line</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="Comment"># up arrow</span>
-
-<span class="muScenario">scenario</span> editor-moves-to-previous-line-with-up-arrow [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
-    press <span class="Constant">65517</span>  <span class="Comment"># up arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a0bc      .</span>
-   <span class="Constant"> .def       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    move-to-previous-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65517/up-arrow</span>
-    <span class="muControl">break-unless</span> move-to-previous-line?
-    already-at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *cursor-row, <span class="Constant">1/top</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># if cursor not at top, move it</span>
-      <span class="muControl">break-if</span> already-at-top?
-      *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>
-      <span class="Comment"># scan back two newlines, then ahead to right column or until end of line</span>
-      prev:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line *before-cursor, editor
-      no-motion?:boolean<span class="Special"> &lt;- </span>equal prev, *before-cursor
-      <span class="muControl">reply-if</span> no-motion?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-      tmp:address:duplex-list<span class="Special"> &lt;- </span>copy prev
-      prev:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line tmp, editor
-      no-motion?:boolean<span class="Special"> &lt;- </span>equal prev, *before-cursor
-      <span class="muControl">reply-if</span> no-motion?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-      *before-cursor<span class="Special"> &lt;- </span>copy prev
-      target-column:number<span class="Special"> &lt;- </span>copy *cursor-column
-      *cursor-column<span class="Special"> &lt;- </span>copy left
-      <span class="Delimiter">{</span>
-        done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column
-        <span class="muControl">break-if</span> done?
-        curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-        <span class="muControl">break-unless</span> curr
-        currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-        at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-        not-at-start?:boolean<span class="Special"> &lt;- </span>greater-than *cursor-column, left
-        line-done?:boolean<span class="Special"> &lt;- </span>and at-newline?, not-at-start?
-        <span class="muControl">break-if</span> line-done?
-        <span class="Comment">#</span>
-        *before-cursor<span class="Special"> &lt;- </span>copy curr
-        *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
-        <span class="muControl">loop</span>
-      <span class="Delimiter">}</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># if cursor already at top, scroll up</span>
-      <span class="muControl">break-unless</span> already-at-top?
-<span class="Constant">      +scroll-up</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="Delimiter">}</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-adjusts-column-at-previous-line [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
-<span class="Constant">def]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
-    press <span class="Constant">65517</span>  <span class="Comment"># up arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .ab0       .</span>
-   <span class="Constant"> .def       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="Comment"># down arrow</span>
-
-<span class="muScenario">scenario</span> editor-moves-to-next-line-with-down-arrow [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># cursor starts out at (1, 0)</span>
-  assume-console [
-    press <span class="Constant">65516</span>  <span class="Comment"># down arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># ..and ends at (2, 0)</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .0def      .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    move-to-next-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65516/down-arrow</span>
-    <span class="muControl">break-unless</span> move-to-next-line?
-    last-line:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1</span>
-    already-at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, last-line
-    <span class="Delimiter">{</span>
-      <span class="Comment"># if cursor not at top, move it</span>
-      <span class="muControl">break-if</span> already-at-bottom?
-      *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
-      <span class="Comment"># scan to start of next line, then to right column or until end of line</span>
-      max:number<span class="Special"> &lt;- </span>subtract right, left
-      next-line:address:duplex-list<span class="Special"> &lt;- </span>before-start-of-next-line *before-cursor, max
-      no-motion?:boolean<span class="Special"> &lt;- </span>equal next-line, *before-cursor
-      <span class="muControl">reply-if</span> no-motion?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-      *before-cursor<span class="Special"> &lt;- </span>copy next-line
-      target-column:number<span class="Special"> &lt;- </span>copy *cursor-column
-      *cursor-column<span class="Special"> &lt;- </span>copy left
-      <span class="Delimiter">{</span>
-        done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column
-        <span class="muControl">break-if</span> done?
-        curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-        <span class="muControl">break-unless</span> curr
-        currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-        at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
-        not-at-start?:boolean<span class="Special"> &lt;- </span>greater-than *cursor-column, left
-        line-done?:boolean<span class="Special"> &lt;- </span>and at-newline?, not-at-start?
-        <span class="muControl">break-if</span> line-done?
-        <span class="Comment">#</span>
-        *before-cursor<span class="Special"> &lt;- </span>copy curr
-        *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
-        <span class="muControl">loop</span>
-      <span class="Delimiter">}</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># if cursor already at top, scroll up</span>
-      <span class="muControl">break-unless</span> already-at-bottom?
-<span class="Constant">      +scroll-down</span>
-      <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-    <span class="Delimiter">}</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-adjusts-column-at-next-line [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">de]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  assume-console [
-    type <span class="Constant">[0]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abc       .</span>
-   <span class="Constant"> .de0       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="Comment"># ctrl-a/home - move cursor to start of line</span>
-
-<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on second line, press ctrl-a</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
-    type <span class="Constant">[a]</span>  <span class="Comment"># ctrl-a</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">1/ctrl-a</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">97/a</span>, <span class="Constant">3</span>:event/ctrl-a
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to start of line</span>
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-a?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">1/ctrl-a</span>
-    <span class="muControl">break-unless</span> ctrl-a?
-    move-to-start-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    home?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65521/home</span>
-    <span class="muControl">break-unless</span> home?
-    move-to-start-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> move-to-start-of-line [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># update cursor column</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  *cursor-column<span class="Special"> &lt;- </span>copy left
-  <span class="Comment"># update before-cursor</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  <span class="Comment"># while not at start of line, move </span>
-  <span class="Delimiter">{</span>
-    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal *before-cursor, init
-    <span class="muControl">break-if</span> at-start-of-text?
-    prev:character<span class="Special"> &lt;- </span>get **before-cursor, <span class="Constant">value:offset</span>
-    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal prev, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-start-of-line?
-    *before-cursor<span class="Special"> &lt;- </span>prev-duplex *before-cursor
-    assert *before-cursor, <span class="Constant">[move-to-start-of-line tried to move before start of text]</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on first line (no newline before), press ctrl-a</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    type <span class="Constant">[a]</span>  <span class="Comment"># ctrl-a</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">1/ctrl-a</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">97/a</span>, <span class="Constant">3</span>:event/ctrl-a
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to start of line</span>
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on second line, press 'home'</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
-    press <span class="Constant">65521</span>  <span class="Comment"># 'home'</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to start of line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on first line (no newline before), press 'home'</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    press <span class="Constant">65521</span>  <span class="Comment"># 'home'</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to start of line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="Comment"># ctrl-e/end - move cursor to end of line</span>
-
-<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on first line, press ctrl-e</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    type <span class="Constant">[e]</span>  <span class="Comment"># ctrl-e</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-e<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">5/ctrl-e</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">101/e</span>, <span class="Constant">3</span>:event/ctrl-e
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to end of line</span>
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-  <span class="Comment"># editor inserts future characters at cursor</span>
-  assume-console [
-    type <span class="Constant">[z]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123z      .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-e?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">5/ctrl-e</span>
-    <span class="muControl">break-unless</span> ctrl-e?
-    move-to-end-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    end?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65520/end</span>
-    <span class="muControl">break-unless</span> end?
-    move-to-end-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> move-to-end-of-line [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  <span class="Comment"># while not at start of line, move </span>
-  <span class="Delimiter">{</span>
-    next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-    <span class="muControl">break-unless</span> next  <span class="Comment"># end of text</span>
-    nextc:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span>
-    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal nextc, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-end-of-line?
-    *before-cursor<span class="Special"> &lt;- </span>copy next
-    *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on second line (no newline after), press ctrl-e</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
-    type <span class="Constant">[e]</span>  <span class="Comment"># ctrl-e</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-e<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">5/ctrl-e</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">101/e</span>, <span class="Constant">3</span>:event/ctrl-e
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to end of line</span>
-  memory-should-contain [
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on first line, press 'end'</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    press <span class="Constant">65520</span>  <span class="Comment"># 'end'</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to end of line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-<span class="Constant">  $clear-trace</span>
-  <span class="Comment"># start on second line (no newline after), press 'end'</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
-    press <span class="Constant">65520</span>  <span class="Comment"># 'end'</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># cursor moves to end of line</span>
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-  ]
-  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
-]
-
-<span class="Comment"># ctrl-u - delete text from start of line until (but not at) cursor</span>
-
-<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start on second line, press ctrl-u</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">2</span>
-    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-a<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">21/ctrl-u</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">117/u</span>, <span class="Constant">3</span>:event/ctrl-u
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to start of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .6         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-u?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">21/ctrl-u</span>
-    <span class="muControl">break-unless</span> ctrl-u?
-    delete-to-start-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> delete-to-start-of-line [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># compute range to delete</span>
-  init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  start:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
-  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
-  <span class="Delimiter">{</span>
-    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal start, init
-    <span class="muControl">break-if</span> at-start-of-text?
-    curr:character<span class="Special"> &lt;- </span>get *start, <span class="Constant">value:offset</span>
-    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal curr, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-start-of-line?
-    start<span class="Special"> &lt;- </span>prev-duplex start
-    assert start, <span class="Constant">[delete-to-start-of-line tried to move before start of text]</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># snip it out</span>
-  start-next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">next:offset</span>
-  *start-next<span class="Special"> &lt;- </span>copy end
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> end
-    end-prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">prev:offset</span>
-    *end-prev<span class="Special"> &lt;- </span>copy start
-  <span class="Delimiter">}</span>
-  <span class="Comment"># adjust cursor</span>
-  *before-cursor<span class="Special"> &lt;- </span>prev-duplex end
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
-  *cursor-column<span class="Special"> &lt;- </span>copy left
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start on first line (no newline before), press ctrl-u</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
-    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-u<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">21/ctrl-u</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">117/u</span>, <span class="Constant">3</span>:event/ctrl-u
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to start of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .3         .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start past end of line, press ctrl-u</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-u<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">21/ctrl-u</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">117/u</span>, <span class="Constant">3</span>:event/ctrl-u
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to start of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-start-of-final-line-with-ctrl-u [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start past end of final line, press ctrl-u</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
-    type <span class="Constant">[u]</span>  <span class="Comment"># ctrl-u</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-u<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">21/ctrl-u</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">117/u</span>, <span class="Constant">3</span>:event/ctrl-u
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to start of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .          .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="Comment"># ctrl-k - delete text from cursor to end of line (but not the newline)</span>
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start on first line, press ctrl-k</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .1         .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-k?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">11/ctrl-k</span>
-    <span class="muControl">break-unless</span> ctrl-k?
-    delete-to-end-of-line editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> delete-to-end-of-line [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># compute range to delete</span>
-  start:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span>
-  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start
-  <span class="Delimiter">{</span>
-    at-end-of-text?:boolean<span class="Special"> &lt;- </span>equal end, <span class="Constant">0/null</span>
-    <span class="muControl">break-if</span> at-end-of-text?
-    curr:character<span class="Special"> &lt;- </span>get *end, <span class="Constant">value:offset</span>
-    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal curr, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-end-of-line?
-    end<span class="Special"> &lt;- </span>next-duplex end
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># snip it out</span>
-  start-next:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *start, <span class="Constant">next:offset</span>
-  *start-next<span class="Special"> &lt;- </span>copy end
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> end
-    end-prev:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *end, <span class="Constant">prev:offset</span>
-    *end-prev<span class="Special"> &lt;- </span>copy start
-  <span class="Delimiter">}</span>
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-2 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start on second line (no newline after), press ctrl-k</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .4         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-3 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start at end of line</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .12        .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-4 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start past end of line</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-5 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start at end of text</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">2</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .45        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-6 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
-<span class="Constant">456]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  <span class="Comment"># start past end of text</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
-    type <span class="Constant">[k]</span>  <span class="Comment"># ctrl-k</span>
-  ]
-  <span class="Constant">3</span>:event/ctrl-k<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">11/ctrl-k</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">107/k</span>, <span class="Constant">3</span>:event/ctrl-k
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># cursor deletes to end of line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .123       .</span>
-   <span class="Constant"> .456       .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .          .</span>
-  ]
-]
-
-<span class="Comment"># cursor-down can scroll if necessary</span>
-
-<span class="muScenario">scenario</span> editor-can-scroll-down-using-arrow-keys [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with &gt;3 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># position cursor at last line, then try to move further down</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen slides by one line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +scroll-down [
-<span class="CommentedCode">#?   $print [scroll down], 10/newline #? 2</span>
-  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  max:number<span class="Special"> &lt;- </span>subtract right, left
-  *top-of-screen<span class="Special"> &lt;- </span>before-start-of-next-line *top-of-screen, max
-]
-
-<span class="Comment"># takes a pointer into the doubly-linked list, scans ahead at most 'max'</span>
-<span class="Comment"># positions until the next newline</span>
-<span class="Comment"># beware: never return null pointer.</span>
-<span class="muRecipe">recipe</span> before-start-of-next-line [
-  <span class="Constant">local-scope</span>
-  original:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  max:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>copy original
-  <span class="Comment"># skip the initial newline if it exists</span>
-  <span class="Delimiter">{</span>
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-unless</span> at-newline?
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">reply-unless</span> curr, original
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
-    <span class="muControl">break-if</span> done?
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
-    <span class="muControl">break-if</span> at-newline?
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply-unless</span> curr, original
-  <span class="muControl">reply</span> curr
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-past-wrapped-line-using-arrow-keys [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
-  <span class="Comment"># other lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
-<span class="Constant">g</span>
-<span class="Constant">h</span>
-<span class="Constant">i]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .g         .</span>
-  ]
-  <span class="Comment"># position cursor at last line, then try to move further down</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .g         .</span>
-   <span class="Constant"> .h         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-past-wrapped-line-using-arrow-keys-2 [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor starts with a long line wrapping twice</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdefghij</span>
-<span class="Constant">k</span>
-<span class="Constant">l</span>
-<span class="Constant">m]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at last line, then try to move further down</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line containing a wrap icon</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .efgh↩     .</span>
-   <span class="Constant"> .ij        .</span>
-   <span class="Constant"> .k         .</span>
-  ]
-  <span class="Comment"># scroll down again</span>
-  assume-console [
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .ij        .</span>
-   <span class="Constant"> .k         .</span>
-   <span class="Constant"> .l         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-when-line-wraps [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains a long line in the third line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">cdef]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at end, type a character</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">4</span>
-    type <span class="Constant">[g]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># screen scrolls</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .b    .</span>
-<span class="Constant">    .cdef↩.</span>
-   <span class="Constant"> .g    .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-on-newline [
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># position cursor after last line and type newline</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">4</span>
-    type [
-]
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># screen scrolls</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .b    .</span>
-   <span class="Constant"> .c    .</span>
-   <span class="Constant"> .     .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-on-right-arrow [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains a wrapped line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">cdefgh]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at end of screen and try to move right</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">3</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># screen scrolls</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .b    .</span>
-<span class="Constant">    .cdef↩.</span>
-   <span class="Constant"> .gh   .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-down-on-right-arrow-2 [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains more lines than can fit on screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at end of screen and try to move right</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">3</span>
-    press <span class="Constant">65514</span>  <span class="Comment"># right arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># screen scrolls</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .b    .</span>
-   <span class="Constant"> .c    .</span>
-   <span class="Constant"> .d    .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-combines-page-and-line-scroll [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with a few pages of lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d</span>
-<span class="Constant">e</span>
-<span class="Constant">f</span>
-<span class="Constant">g]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># scroll down one page and one line</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen scrolls down 3 lines</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .d         .</span>
-   <span class="Constant"> .e         .</span>
-   <span class="Constant"> .f         .</span>
-  ]
-]
-
-<span class="Comment"># cursor-up can scroll if necessary</span>
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-using-arrow-keys [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with &gt;3 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># position cursor at top of second page, then try to move up</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen slides by one line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +scroll-up [
-<span class="CommentedCode">#?   $print [scroll up], 10/newline #? 1</span>
-  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
-  *top-of-screen<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor
-]
-
-<span class="Comment"># takes a pointer into the doubly-linked list, scans back to before start of</span>
-<span class="Comment"># previous *wrapped* line</span>
-<span class="Comment"># beware: never return null pointer</span>
-<span class="muRecipe">recipe</span> before-previous-line [
-  <span class="Constant">local-scope</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-<span class="CommentedCode">#?   $print [curr at ], c, 10/newline #? 1</span>
-  <span class="Comment"># compute max, number of characters to skip</span>
-  <span class="Comment">#   1 + len%(width-1)</span>
-  <span class="Comment">#   except rotate second term to vary from 1 to width-1 rather than 0 to width-2</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
-  max-line-length:number<span class="Special"> &lt;- </span>subtract right, left, <span class="Constant">-1/exclusive-right</span>, <span class="Constant">1/wrap-icon</span>
-  sentinel:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  len:number<span class="Special"> &lt;- </span>previous-line-length curr, sentinel
-<span class="CommentedCode">#?   $print [previous line: ], len, 10/newline #? 1</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> len
-    <span class="Comment"># empty line; just skip this newline</span>
-    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr
-    <span class="muControl">reply-unless</span> prev, curr
-    <span class="muControl">reply</span> prev
-  <span class="Delimiter">}</span>
-  _, max:number<span class="Special"> &lt;- </span>divide-with-remainder len, max-line-length
-  <span class="Comment"># remainder 0 =&gt; scan one width-worth</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> max
-<span class="CommentedCode">#?     $print [remainder 0; scan one width], 10/newline #? 1</span>
-    max<span class="Special"> &lt;- </span>copy max-line-length
-  <span class="Delimiter">}</span>
-  max<span class="Special"> &lt;- </span>add max, <span class="Constant">1</span>
-<span class="CommentedCode">#?   $print [skipping ], max, [ characters], 10/newline #? 1</span>
-  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="Comment"># skip 'max' characters</span>
-  <span class="Delimiter">{</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
-    <span class="muControl">break-if</span> done?
-    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr
-    <span class="muControl">break-unless</span> prev
-    curr<span class="Special"> &lt;- </span>copy prev
-    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> curr
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
-  <span class="Comment"># other lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
-<span class="Constant">g</span>
-<span class="Constant">h</span>
-<span class="Constant">i]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .g         .</span>
-  ]
-  <span class="Comment"># position cursor at top of second page, just below wrapped line</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .g         .</span>
-   <span class="Constant"> .h         .</span>
-   <span class="Constant"> .i         .</span>
-  ]
-  <span class="Comment"># now move up one line</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .ef        .</span>
-   <span class="Constant"> .g         .</span>
-   <span class="Constant"> .h         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-2 [
-  <span class="Comment"># screen has 1 line for menu + 4 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># editor starts with a long line wrapping twice, occupying 3 of the 4 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdefghij</span>
-<span class="Constant">k</span>
-<span class="Constant">l</span>
-<span class="Constant">m]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at top of second page</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .k         .</span>
-   <span class="Constant"> .l         .</span>
-   <span class="Constant"> .m         .</span>
-   <span class="Constant"> .┈┈┈┈┈     .</span>
-  ]
-  <span class="Comment"># move up one line</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .ij        .</span>
-   <span class="Constant"> .k         .</span>
-   <span class="Constant"> .l         .</span>
-   <span class="Constant"> .m         .</span>
-  ]
-  <span class="Comment"># move up a second line</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .efgh↩     .</span>
-   <span class="Constant"> .ij        .</span>
-   <span class="Constant"> .k         .</span>
-   <span class="Constant"> .l         .</span>
-  ]
-  <span class="Comment"># move up a third line</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .efgh↩     .</span>
-   <span class="Constant"> .ij        .</span>
-   <span class="Constant"> .k         .</span>
-  ]
-]
-
-<span class="Comment"># same as editor-scrolls-up-past-wrapped-line-using-arrow-keys but length</span>
-<span class="Comment"># slightly off, just to prevent over-training</span>
-<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-3 [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
-  <span class="Comment"># other lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
-<span class="Constant">g</span>
-<span class="Constant">h</span>
-<span class="Constant">i]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcde↩    .</span>
-   <span class="Constant"> .f         .</span>
-   <span class="Constant"> .g         .</span>
-  ]
-  <span class="Comment"># position cursor at top of second page, just below wrapped line</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .g         .</span>
-   <span class="Constant"> .h         .</span>
-   <span class="Constant"> .i         .</span>
-  ]
-  <span class="Comment"># now move up one line</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows partial wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .f         .</span>
-   <span class="Constant"> .g         .</span>
-   <span class="Constant"> .h         .</span>
-  ]
-]
-
-<span class="Comment"># check empty lines</span>
-<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with some lines around an empty line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-
-c
-d
-e]
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .d         .</span>
-   <span class="Constant"> .e         .</span>
-   <span class="Constant"> .┈┈┈┈┈┈    .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-scrolls-up-on-left-arrow [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains &gt;3 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d</span>
-<span class="Constant">e]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
-  <span class="Comment"># position cursor at top of second page</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .c    .</span>
-   <span class="Constant"> .d    .</span>
-   <span class="Constant"> .e    .</span>
-  ]
-  <span class="Comment"># now try to move left</span>
-  assume-console [
-    press <span class="Constant">65515</span>  <span class="Comment"># left arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
-    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  <span class="Comment"># screen scrolls</span>
-  screen-should-contain [
-   <span class="Constant"> .     .</span>
-   <span class="Constant"> .b    .</span>
-   <span class="Constant"> .c    .</span>
-   <span class="Constant"> .d    .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-to-start-of-file [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with &gt;3 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># position cursor at top of second page, then try to move up to start of</span>
-  <span class="Comment"># text</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen slides by one line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># try to move up again</span>
-  assume-console [
-    press <span class="Constant">65517</span>  <span class="Comment"># up-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen remains unchanged</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-]
-
-<span class="Comment"># ctrl-f/page-down - render next page if it exists</span>
-
-<span class="muScenario">scenario</span> editor-can-scroll [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows next page</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-f?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">6/ctrl-f</span>
-    <span class="muControl">break-unless</span> ctrl-f?
-    page-down editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    page-down?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65518/page-down</span>
-    <span class="muControl">break-unless</span> page-down?
-    page-down editor
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># page-down skips entire wrapped lines, so it can't scroll past lines</span>
-<span class="Comment"># taking up the entire screen</span>
-<span class="muRecipe">recipe</span> page-down [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># if editor contents don't overflow screen, do nothing</span>
-  bottom-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span>
-  <span class="muControl">reply-unless</span> bottom-of-screen, editor/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Comment"># if not, position cursor at final character</span>
-  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
-  *before-cursor<span class="Special"> &lt;- </span>prev-duplex bottom-of-screen
-  <span class="Comment"># keep one line in common with previous page</span>
-  <span class="Delimiter">{</span>
-    last:character<span class="Special"> &lt;- </span>get **before-cursor, <span class="Constant">value:offset</span>
-    newline?:boolean<span class="Special"> &lt;- </span>equal last, <span class="Constant">10/newline</span>
-    <span class="muControl">break-unless</span> newline?:boolean
-    *before-cursor<span class="Special"> &lt;- </span>prev-duplex *before-cursor
-  <span class="Delimiter">}</span>
-  <span class="Comment"># move cursor and top-of-screen to start of that line</span>
-  move-to-start-of-line editor
-  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
-  *top-of-screen<span class="Special"> &lt;- </span>copy *before-cursor
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muScenario">scenario</span> editor-does-not-scroll-past-end [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  editor-render screen, <span class="Constant">2</span>:address:editor-data
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen remains unmodified</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-starts-next-page-at-start-of-wrapped-line [
-  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains a long last line</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">cdefgh]</span>
-  <span class="Comment"># editor screen triggers wrap of last line</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  <span class="Comment"># some part of last line is not displayed</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .cde↩      .</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows entire wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .cde↩      .</span>
-   <span class="Constant"> .fgh       .</span>
-   <span class="Constant"> .┈┈┈┈      .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-starts-next-page-at-start-of-wrapped-line-2 [
-  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span>
-  <span class="Comment"># and still has something left over</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">bcdefgh]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  <span class="Comment"># some part of last line is not displayed</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .bcd↩      .</span>
-   <span class="Constant"> .efg↩      .</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows entire wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .bcd↩      .</span>
-   <span class="Constant"> .efg↩      .</span>
-   <span class="Constant"> .h         .</span>
-  ]
-]
-
-<span class="Comment"># ctrl-b/page-up - render previous page if it exists</span>
-
-<span class="muScenario">scenario</span> editor-can-scroll-up [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows next page</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
-  ]
-  <span class="Comment"># scroll back up</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows original page again</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +handle-special-character [
-  <span class="Delimiter">{</span>
-    ctrl-b?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">2/ctrl-f</span>
-    <span class="muControl">break-unless</span> ctrl-b?
-    editor<span class="Special"> &lt;- </span>page-up editor, screen-height
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">after</span> +handle-special-key [
-  <span class="Delimiter">{</span>
-    page-up?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65519/page-up</span>
-    <span class="muControl">break-unless</span> page-up?
-    editor<span class="Special"> &lt;- </span>page-up editor, screen-height
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> page-up [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  max:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1/menu-bar</span>, <span class="Constant">1/overlapping-line</span>
-  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
-  <span class="Delimiter">{</span>
-<span class="CommentedCode">#?     $print [- ], count, [ vs ], max, 10/newline #? 1</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
-    <span class="muControl">break-if</span> done?
-    prev:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor
-    <span class="muControl">break-unless</span> prev
-    *top-of-screen<span class="Special"> &lt;- </span>copy prev
-    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-multiple-pages [
-  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># initialize editor with 8 lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">c</span>
-<span class="Constant">d</span>
-<span class="Constant">e</span>
-<span class="Constant">f</span>
-<span class="Constant">g</span>
-<span class="Constant">h]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-  <span class="Comment"># scroll down two pages</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows third page</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .e         .</span>
-   <span class="Constant"> .f         .</span>
-   <span class="Constant"> .g         .</span>
-  ]
-  <span class="Comment"># scroll up</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows second page</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .c         .</span>
-   <span class="Constant"> .d         .</span>
-   <span class="Constant"> .e         .</span>
-  ]
-  <span class="Comment"># scroll up again</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows original page again</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .c         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-wrapped-lines [
-  <span class="Comment"># screen has 1 line for menu + 5 lines for text</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">6/height</span>
-  <span class="Comment"># editor contains a long line in the first page</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">b</span>
-<span class="Constant">cdefgh</span>
-<span class="Constant">i</span>
-<span class="Constant">j</span>
-<span class="Constant">k</span>
-<span class="Constant">l</span>
-<span class="Constant">m</span>
-<span class="Constant">n</span>
-<span class="Constant">o]</span>
-  <span class="Comment"># editor screen triggers wrap of last line</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  <span class="Comment"># some part of last line is not displayed</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .cde↩      .</span>
-   <span class="Constant"> .fgh       .</span>
-   <span class="Constant"> .i         .</span>
-  ]
-  <span class="Comment"># scroll down a page and a line</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-    left-click <span class="Constant">5</span>, <span class="Constant">0</span>
-    press <span class="Constant">65516</span>  <span class="Comment"># down-arrow</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows entire wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .j         .</span>
-   <span class="Constant"> .k         .</span>
-   <span class="Constant"> .l         .</span>
-   <span class="Constant"> .m         .</span>
-   <span class="Constant"> .n         .</span>
-  ]
-  <span class="Comment"># now scroll up one page</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen resets</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .b         .</span>
-   <span class="Constant"> .cde↩      .</span>
-   <span class="Constant"> .fgh       .</span>
-   <span class="Constant"> .i         .</span>
-   <span class="Constant"> .j         .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-wrapped-lines-2 [
-  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span>
-  <span class="Comment"># and still has something left over</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
-<span class="Constant">bcdefgh]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  <span class="Comment"># some part of last line is not displayed</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .bcd↩      .</span>
-   <span class="Constant"> .efg↩      .</span>
-  ]
-  <span class="Comment"># scroll down</span>
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen shows entire wrapped line</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .bcd↩      .</span>
-   <span class="Constant"> .efg↩      .</span>
-   <span class="Constant"> .h         .</span>
-  ]
-  <span class="Comment"># scroll back up</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  <span class="Comment"># screen resets</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .a         .</span>
-   <span class="Constant"> .bcd↩      .</span>
-   <span class="Constant"> .efg↩      .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-past-nonempty-lines [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># text with empty line in second screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[axx</span>
-<span class="Constant">bxx</span>
-<span class="Constant">cxx</span>
-<span class="Constant">dxx</span>
-<span class="Constant">exx</span>
-<span class="Constant">fxx</span>
-<span class="Constant">gxx</span>
-<span class="Constant">hxx</span>
-<span class="Constant">]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .axx       .</span>
-   <span class="Constant"> .bxx       .</span>
-   <span class="Constant"> .cxx       .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .cxx       .</span>
-   <span class="Constant"> .dxx       .</span>
-   <span class="Constant"> .exx       .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .exx       .</span>
-   <span class="Constant"> .fxx       .</span>
-   <span class="Constant"> .gxx       .</span>
-  ]
-  <span class="Comment"># scroll back up past empty line</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .cxx       .</span>
-   <span class="Constant"> .dxx       .</span>
-   <span class="Constant"> .exx       .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-can-scroll-up-past-empty-lines [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
-  <span class="Comment"># text with empty line in second screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[axy</span>
-<span class="Constant">bxy</span>
-<span class="Constant">cxy</span>
-
-dxy
-exy
-fxy
-gxy
-]
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .axy       .</span>
-   <span class="Constant"> .bxy       .</span>
-   <span class="Constant"> .cxy       .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .cxy       .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .dxy       .</span>
-  ]
-  assume-console [
-    press <span class="Constant">65518</span>  <span class="Comment"># page-down</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .dxy       .</span>
-   <span class="Constant"> .exy       .</span>
-   <span class="Constant"> .fxy       .</span>
-  ]
-  <span class="Comment"># scroll back up past empty line</span>
-  assume-console [
-    press <span class="Constant">65519</span>  <span class="Comment"># page-up</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .cxy       .</span>
-   <span class="Constant"> .          .</span>
-   <span class="Constant"> .dxy       .</span>
-  ]
-]
-
-<span class="SalientComment">## putting the environment together out of editors</span>
-
-container programming-environment-data [
-  recipes:address:editor-data
-  recipe-warnings:address:array:character
-  current-sandbox:address:editor-data
-  sandbox:address:sandbox-data  <span class="Comment"># list of sandboxes, from top to bottom</span>
-  sandbox-in-focus?:boolean  <span class="Comment"># false =&gt; cursor in recipes; true =&gt; cursor in current-sandbox</span>
-]
-
-<span class="muRecipe">recipe</span> new-programming-environment [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  initial-recipe-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  initial-sandbox-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  width:number<span class="Special"> &lt;- </span>screen-width screen
-  height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Comment"># top menu</span>
-  result:address:programming-environment-data<span class="Special"> &lt;- </span>new <span class="Constant">programming-environment-data:type</span>
-  draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span>
-  button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span>
-  button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span>
-  assert button-on-screen?, <span class="Constant">[screen too narrow for menu]</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0/row</span>, button-start
-  run-button:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ run (F4) ]</span>
-  print-string screen, run-button, <span class="Constant">255/white</span>, <span class="Constant">161/reddish</span>
-  <span class="Comment"># dotted line down the middle</span>
-  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
-  draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span>
-  <span class="Comment"># recipe editor on the left</span>
-  recipes:address:address:editor-data<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">recipes:offset</span>
-  *recipes<span class="Special"> &lt;- </span>new-editor initial-recipe-contents, screen, <span class="Constant">0/left</span>, divider/right
-  <span class="Comment"># sandbox editor on the right</span>
-  new-left:number<span class="Special"> &lt;- </span>add divider, <span class="Constant">1</span>
-  current-sandbox:address:address:editor-data<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">current-sandbox:offset</span>
-  *current-sandbox<span class="Special"> &lt;- </span>new-editor initial-sandbox-contents, screen, new-left, width/right
-<span class="Constant">  +programming-environment-initialization</span>
-  <span class="muControl">reply</span> result
-]
-
-<span class="muRecipe">recipe</span> event-loop [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span>
-<span class="Constant">    +next-event</span>
-    e:event, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console
-    <span class="muControl">loop-unless</span> found?
-    <span class="muControl">break-if</span> quit?  <span class="Comment"># only in tests</span>
-    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
-<span class="Constant">    +handle-event</span>
-    <span class="Comment"># check for global events that will trigger regardless of which editor has focus</span>
-    <span class="Delimiter">{</span>
-      k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span>
-      <span class="muControl">break-unless</span> k
-<span class="Constant">      +global-keypress</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      c:address:character<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">text:variant</span>
-      <span class="muControl">break-unless</span> c
-<span class="Constant">      +global-type</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># 'touch' event - send to both sides, see what picks it up</span>
-    <span class="Delimiter">{</span>
-      t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">touch:variant</span>
-      <span class="muControl">break-unless</span> t
-      <span class="Comment"># ignore all but 'left-click' events for now</span>
-      <span class="Comment"># todo: test this</span>
-      touch-type:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">type:offset</span>
-      is-left-click?:boolean<span class="Special"> &lt;- </span>equal touch-type, <span class="Constant">65513/mouse-left</span>
-      <span class="muControl">loop-unless</span> is-left-click?, <span class="Constant">+next-event:label</span>
-      <span class="Comment"># later exceptions for non-editor touches will go here</span>
-<span class="Constant">      +global-touch</span>
-      <span class="Comment"># send to both editors</span>
-      _<span class="Special"> &lt;- </span>move-cursor-in-editor screen, recipes, *t
-      *sandbox-in-focus?<span class="Special"> &lt;- </span>move-cursor-in-editor screen, current-sandbox, *t
-      screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># 'resize' event - redraw editor</span>
-    <span class="Comment"># todo: test this after supporting resize in assume-console</span>
-    <span class="Delimiter">{</span>
-      r:address:resize-event<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">resize:variant</span>
-      <span class="muControl">break-unless</span> r
-      <span class="Comment"># if more events, we're still resizing; wait until we stop</span>
-      more-events?:boolean<span class="Special"> &lt;- </span>has-more-events? console
-      <span class="muControl">break-if</span> more-events?
-      env<span class="Special"> &lt;- </span>resize screen, env
-      screen<span class="Special"> &lt;- </span>render-all screen, env
-      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># if it's not global and not a touch event, send to appropriate editor</span>
-    <span class="Delimiter">{</span>
-      hide-screen screen
-      <span class="Delimiter">{</span>
-        <span class="muControl">break-if</span> *sandbox-in-focus?
-        screen, recipes, render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, recipes, e:event
-        <span class="Delimiter">{</span>
-          <span class="muControl">break-unless</span> render?
-          screen<span class="Special"> &lt;- </span>render-recipes screen, env
-        <span class="Delimiter">}</span>
-      <span class="Delimiter">}</span>
-      <span class="Delimiter">{</span>
-        <span class="muControl">break-unless</span> *sandbox-in-focus?
-        screen, current-sandbox, render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, current-sandbox, e:event
-        <span class="Delimiter">{</span>
-          <span class="muControl">break-unless</span> render?:boolean
-          screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-        <span class="Delimiter">}</span>
-      <span class="Delimiter">}</span>
-      screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-      show-screen screen
-    <span class="Delimiter">}</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> resize [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># hack: clear screen to update screen dimensions</span>
-  clear-screen screen
-  width:number<span class="Special"> &lt;- </span>screen-width screen
-  height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Comment"># top menu</span>
-  draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span>
-  button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span>
-  button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span>
-  assert button-on-screen?, <span class="Constant">[screen too narrow for menu]</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0/row</span>, button-start
-  run-button:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ run (F4) ]</span>
-  print-string screen, run-button, <span class="Constant">255/white</span>, <span class="Constant">161/reddish</span>
-  <span class="Comment"># dotted line down the middle</span>
-  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
-  draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span>
-  <span class="Comment"># update recipe editor</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  right:address:number<span class="Special"> &lt;- </span>get-address *recipes, <span class="Constant">right:offset</span>
-  *right<span class="Special"> &lt;- </span>subtract divider, <span class="Constant">1</span>
-  <span class="Comment"># update sandbox editor</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  left:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">left:offset</span>
-  right:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">right:offset</span>
-  *left<span class="Special"> &lt;- </span>add divider, <span class="Constant">1</span>
-  *right<span class="Special"> &lt;- </span>subtract width, <span class="Constant">1</span>
-  <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">1</span>
-]
-
-<span class="muScenario">scenario</span> point-at-multiple-editors [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize both halves of screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># focus on both sides</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    left-click <span class="Constant">1</span>, <span class="Constant">17</span>
-  ]
-  <span class="Comment"># check cursor column in each</span>
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-    <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-    <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span>
-    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">17</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> edit-multiple-editors [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize both halves of screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
-  <span class="Comment"># type one letter in each of them</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
-    type <span class="Constant">[0]</span>
-    left-click <span class="Constant">1</span>, <span class="Constant">17</span>
-    type <span class="Constant">[1]</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-    <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span>
-    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-    <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span>
-    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .  # this line has a different background, but we don't test that yet</span>
-   <span class="Constant"> .a0bc           ┊d1ef          .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-  memory-should-contain [
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column of recipe editor</span>
-    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">18</span>  <span class="Comment"># cursor column of sandbox editor</span>
-  ]
-  <span class="Comment"># show the cursor at the right window</span>
-  run [
-    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
-  ]
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .a0bc           ┊d1␣f          .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> multiple-editors-cover-only-their-own-areas [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">60/width</span>, <span class="Constant">10/height</span>
-  run [
-    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
-    <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-    render-all screen, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># divider isn't messed up</span>
-  screen-should-contain [
-   <span class="Constant"> .                                         run (F4)           .</span>
-   <span class="Constant"> .abc                           ┊def                          .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                              ┊                             .</span>
-   <span class="Constant"> .                              ┊                             .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
-  <span class="Comment"># initialize programming environment and highlight cursor</span>
-  assume-console <span class="Constant">[]</span>
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-    print-character screen:address, <span class="Constant">9251/␣</span>
-  ]
-  <span class="Comment"># is cursor at the right place?</span>
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .␣bc            ┊def           .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-  <span class="Comment"># now try typing a letter</span>
-  assume-console [
-    type <span class="Constant">[z]</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-    print-character screen:address, <span class="Constant">9251/␣</span>
-  ]
-  <span class="Comment"># cursor should still be right</span>
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .z␣bc           ┊def           .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> backspace-in-sandbox-editor-joins-lines [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize sandbox side with two lines</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
-<span class="Constant">def]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .               ┊abc           .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊def           .</span>
-   <span class="Constant"> .               ┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-  <span class="Comment"># position cursor at start of second line and hit backspace</span>
-  assume-console [
-    left-click <span class="Constant">2</span>, <span class="Constant">16</span>
-    type <span class="Constant">[«]</span>
-  ]
-  <span class="Constant">4</span>:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">8/backspace</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">171/«</span>, <span class="Constant">4</span>:event/backspace
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-    print-character screen:address, <span class="Constant">9251/␣</span>
-  ]
-  <span class="Comment"># cursor moves to end of old line</span>
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .               ┊abc␣ef        .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-]
-
-<span class="muRecipe">recipe</span> render-all [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  hide-screen screen
-  <span class="Comment"># top menu</span>
-  width:number<span class="Special"> &lt;- </span>screen-width screen
-  draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span>
-  button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span>
-  button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span>
-  assert button-on-screen?, <span class="Constant">[screen too narrow for menu]</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0/row</span>, button-start
-  run-button:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ run (F4) ]</span>
-  print-string screen, run-button, <span class="Constant">255/white</span>, <span class="Constant">161/reddish</span>
-  <span class="Comment"># error message</span>
-  recipe-warnings:address:array:character<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-warnings:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> recipe-warnings
-    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[errors found]</span>
-    update-status screen, status, <span class="Constant">1/red</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># dotted line down the middle</span>
-  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
-  height:number<span class="Special"> &lt;- </span>screen-height screen
-  draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span>
-  <span class="Comment">#</span>
-  screen<span class="Special"> &lt;- </span>render-recipes screen, env
-  screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-  <span class="Comment">#</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span>
-  screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?
-  <span class="Comment">#</span>
-  show-screen screen
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> render-minimal [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  hide-screen screen
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> sandbox-in-focus?
-    screen<span class="Special"> &lt;- </span>render-recipes screen, env
-    cursor-row:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-row:offset</span>
-    cursor-column:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-column:offset</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> sandbox-in-focus?
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-    cursor-row:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-row:offset</span>
-    cursor-column:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-column:offset</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
-  show-screen screen
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> render-recipes [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  <span class="Comment"># render recipes</span>
-  left:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">right:offset</span>
-  row:number, column:number, screen<span class="Special"> &lt;- </span>render screen, recipes
-  clear-line-delimited screen, column, right
-  recipe-warnings:address:array:character<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-warnings:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># print any warnings</span>
-    <span class="muControl">break-unless</span> recipe-warnings
-    row, screen<span class="Special"> &lt;- </span>render-string screen, recipe-warnings, left, right, <span class="Constant">1/red</span>, row
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># no warnings? move to next line</span>
-    <span class="muControl">break-if</span> recipe-warnings
-    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># draw dotted line after recipes</span>
-  draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  clear-screen-from screen, row, left, left, right
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> update-cursor [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> sandbox-in-focus?
-<span class="CommentedCode">#?     $print [recipes in focus</span>
-<span class="CommentedCode">#? ] #? 1</span>
-    cursor-row:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-row:offset</span>
-    cursor-column:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-column:offset</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> sandbox-in-focus?
-<span class="CommentedCode">#?     $print [sandboxes in focus</span>
-<span class="CommentedCode">#? ] #? 1</span>
-    cursor-row:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-row:offset</span>
-    cursor-column:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-column:offset</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="Comment"># ctrl-l - redraw screen (just in case it printed junk somehow)</span>
-
-<span class="muRecipe">after</span> +global-type [
-  <span class="Delimiter">{</span>
-    ctrl-l?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">12/ctrl-l</span>
-    <span class="muControl">break-unless</span> ctrl-l?
-    screen<span class="Special"> &lt;- </span>render-all screen, env:address:programming-environment-data
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># ctrl-n - switch focus</span>
-<span class="Comment"># todo: test this</span>
-
-<span class="muRecipe">after</span> +global-type [
-  <span class="Delimiter">{</span>
-    ctrl-n?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">14/ctrl-n</span>
-    <span class="muControl">break-unless</span> ctrl-n?
-    *sandbox-in-focus?<span class="Special"> &lt;- </span>not *sandbox-in-focus?
-    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># ctrl-x - maximize/unmaximize the side with focus</span>
-
-<span class="muScenario">scenario</span> maximize-side [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
-  <span class="Comment"># initialize both halves of screen</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  screen<span class="Special"> &lt;- </span>render-all screen, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .abc            ┊def           .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-  <span class="Comment"># hit ctrl-x</span>
-  assume-console [
-    type <span class="Constant">[x]</span>
-  ]
-  <span class="Constant">4</span>:event/ctrl-x<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">24/ctrl-x</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">120/x</span>, <span class="Constant">4</span>:event/ctrl-x
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># only left side visible</span>
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .abc                           .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈.</span>
-   <span class="Constant"> .                              .</span>
-  ]
-  <span class="Comment"># hit any key to toggle back</span>
-  assume-console [
-    press <span class="Constant">24</span>  <span class="Comment"># ctrl-x</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .           run (F4)           .</span>
-   <span class="Constant"> .abc            ┊def           .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .               ┊              .</span>
-  ]
-]
-
-container programming-environment-data [
-  maximized?:boolean
-]
-
-<span class="muRecipe">after</span> +global-type [
-  <span class="Delimiter">{</span>
-    ctrl-x?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">24/ctrl-x</span>
-    <span class="muControl">break-unless</span> ctrl-x?
-    screen, console<span class="Special"> &lt;- </span>maximize screen, console, env:address:programming-environment-data
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> maximize [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  hide-screen screen
-  <span class="Comment"># maximize one of the sides</span>
-  maximized?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">maximized?:offset</span>
-  *maximized?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
-  <span class="Comment">#</span>
-  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> sandbox-in-focus?
-    editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-    right:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">right:offset</span>
-    *right<span class="Special"> &lt;- </span>screen-width screen
-    *right<span class="Special"> &lt;- </span>subtract *right, <span class="Constant">1</span>
-    screen<span class="Special"> &lt;- </span>render-recipes screen, env
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> sandbox-in-focus?
-    editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-    left:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">left:offset</span>
-    *left<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-  <span class="Delimiter">}</span>
-  show-screen screen
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">1</span>
-]
-
-<span class="Comment"># when maximized, wait for any event and simply unmaximize</span>
-<span class="muRecipe">after</span> +handle-event [
-  <span class="Delimiter">{</span>
-    maximized?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">maximized?:offset</span>
-    <span class="muControl">break-unless</span> *maximized?
-    *maximized?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
-    <span class="Comment"># undo maximize</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> *sandbox-in-focus?
-      editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-      right:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">right:offset</span>
-      *right<span class="Special"> &lt;- </span>screen-width screen
-      *right<span class="Special"> &lt;- </span>divide *right, <span class="Constant">2</span>
-      *right<span class="Special"> &lt;- </span>subtract *right, <span class="Constant">1</span>
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-unless</span> *sandbox-in-focus?
-      editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-      left:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">left:offset</span>
-      *left<span class="Special"> &lt;- </span>screen-width screen
-      *left<span class="Special"> &lt;- </span>divide *left, <span class="Constant">2</span>
-      *left<span class="Special"> &lt;- </span>add *left, <span class="Constant">1</span>
-    <span class="Delimiter">}</span>
-    render-all screen, env
-    show-screen screen
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="SalientComment">## running code from the editor and creating sandboxes</span>
-
-container sandbox-data [
-  data:address:array:character
-  response:address:array:character
-  warnings:address:array:character
-  trace:address:array:character
-  expected-response:address:array:character
-  <span class="Comment"># coordinates to track clicks</span>
-  starting-row-on-screen:number
-  code-ending-row-on-screen:number
-  response-starting-row-on-screen:number
-  display-trace?:boolean
-  screen:address:screen  <span class="Comment"># prints in the sandbox go here</span>
-  next-sandbox:address:sandbox-data
-]
-
-<span class="muScenario">scenario</span> run-and-show-results [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Comment"># recipe editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[divide-with-remainder 11, 3]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the code in the editors</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen prints the results</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
-   <span class="Constant"> .                                                  ┊3                                                .</span>
-   <span class="Constant"> .                                                  ┊2                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">7/white</span>, [
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                   divide-with-remainder 11, 3                      .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊3                                                .</span>
-   <span class="Constant"> .                                                  ┊2                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># run another command</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">80</span>
-    type <span class="Constant">[add 2, 2]</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen prints the results</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
-   <span class="Constant"> .                                                  ┊4                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
-   <span class="Constant"> .                                                  ┊3                                                .</span>
-   <span class="Constant"> .                                                  ┊2                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="Comment"># hook into event-loop recipe: read non-unicode keypress from k, process it if</span>
-<span class="Comment"># necessary, then go to next level</span>
-<span class="muRecipe">after</span> +global-keypress [
-  <span class="Comment"># F4? load all code and run all sandboxes.</span>
-  <span class="Delimiter">{</span>
-    do-run?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65532/F4</span>
-    <span class="muControl">break-unless</span> do-run?
-    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[running...  ]</span>
-    screen<span class="Special"> &lt;- </span>update-status screen, status, <span class="Constant">245/grey</span>
-    screen, error?:boolean<span class="Special"> &lt;- </span>run-sandboxes env, screen
-    <span class="Comment"># F4 might update warnings and results on both sides</span>
-    screen<span class="Special"> &lt;- </span>render-all screen, env
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> error?
-      status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[            ]</span>
-      screen<span class="Special"> &lt;- </span>update-status screen, status, <span class="Constant">245/grey</span>
-    <span class="Delimiter">}</span>
-    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> run-sandboxes [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
-  <span class="Comment"># copy code from recipe editor, persist, load into mu, save any warnings</span>
-  in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes
-  save <span class="Constant">[recipes.mu]</span>, in
-  recipe-warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">recipe-warnings:offset</span>
-  *recipe-warnings<span class="Special"> &lt;- </span>reload in
-  <span class="Comment"># if recipe editor has errors, stop</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> *recipe-warnings
-    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[errors found]</span>
-    update-status screen, status, <span class="Constant">1/red</span>
-    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/errors-found</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># check contents of right editor (sandbox)</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  <span class="Delimiter">{</span>
-    sandbox-contents:address:array:character<span class="Special"> &lt;- </span>editor-contents current-sandbox
-    <span class="muControl">break-unless</span> sandbox-contents
-    <span class="Comment"># if contents exist, first save them</span>
-    <span class="Comment"># run them and turn them into a new sandbox-data</span>
-    new-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>new <span class="Constant">sandbox-data:type</span>
-    data:address:address:array:character<span class="Special"> &lt;- </span>get-address *new-sandbox, <span class="Constant">data:offset</span>
-    *data<span class="Special"> &lt;- </span>copy sandbox-contents
-    <span class="Comment"># push to head of sandbox list</span>
-    dest:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
-    next:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *new-sandbox, <span class="Constant">next-sandbox:offset</span>
-    *next<span class="Special"> &lt;- </span>copy *dest
-    *dest<span class="Special"> &lt;- </span>copy new-sandbox
-    <span class="Comment"># clear sandbox editor</span>
-    init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">data:offset</span>
-    *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span>
-    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">top-of-screen:offset</span>
-    *top-of-screen<span class="Special"> &lt;- </span>copy *init
-  <span class="Delimiter">}</span>
-  <span class="Comment"># save all sandboxes before running, just in case we die when running</span>
-  save-sandboxes env
-  <span class="Comment"># run all sandboxes</span>
-  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> curr
-    data<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">data:offset</span>
-    response:address:address:array:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">response:offset</span>
-    warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">warnings:offset</span>
-    trace:address:address:array:character<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">trace:offset</span>
-    fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">screen:offset</span>
-    *response, *warnings, *fake-screen, *trace, completed?:boolean<span class="Special"> &lt;- </span>run-interactive *data
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> *warnings
-      <span class="muControl">break-if</span> completed?:boolean
-      *warnings<span class="Special"> &lt;- </span>new <span class="Constant">[took too long!</span>
-<span class="Constant">]</span>
-    <span class="Delimiter">}</span>
-    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-errors-found</span>
-]
-
-<span class="muRecipe">recipe</span> update-status [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  msg:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0</span>, <span class="Constant">2</span>
-  screen<span class="Special"> &lt;- </span>print-string screen, msg, color, <span class="Constant">238/grey/background</span>
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> save-sandboxes [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  <span class="Comment"># first clear previous versions, in case we deleted some sandbox</span>
-  $system <span class="Constant">[rm lesson/[0-9]</span>* &gt;/dev/null <span class="Constant">2</span>&gt;/dev/null]  <span class="Comment"># some shells can't handle '&gt;&amp;'</span>
-  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  suffix:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[.out]</span>
-  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> curr
-    data:address:array:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">data:offset</span>
-    filename:address:array:character<span class="Special"> &lt;- </span>integer-to-decimal-string idx
-    save filename, data
-    <span class="Delimiter">{</span>
-      expected-response:address:array:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">expected-response:offset</span>
-      <span class="muControl">break-unless</span> expected-response
-      filename<span class="Special"> &lt;- </span>string-append filename, suffix
-      save filename, expected-response
-    <span class="Delimiter">}</span>
-    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
-    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> render-sandbox-side [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-<span class="CommentedCode">#?   trace 10, [app], [render sandbox side] #? 1</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  left:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span>
-  row:number, column:number, screen, current-sandbox<span class="Special"> &lt;- </span>render screen, current-sandbox
-  clear-screen-from screen, row, column, left, right
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span>
-  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, sandbox, left, right, row
-  clear-rest-of-screen screen, row, left, left, right
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muRecipe">recipe</span> render-sandboxes [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="muControl">reply-unless</span> sandbox, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-  <span class="muControl">reply-if</span> at-bottom?:boolean, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Comment"># render sandbox menu</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
-  clear-line-delimited screen, left, right
-  print-character screen, <span class="Constant">120/x</span>, <span class="Constant">245/grey</span>
-  <span class="Comment"># save menu row so we can detect clicks to it later</span>
-  starting-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-  *starting-row<span class="Special"> &lt;- </span>copy row
-  <span class="Comment"># render sandbox contents</span>
-  sandbox-data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
-  row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-data, left, right, <span class="Constant">7/white</span>, row
-  code-ending-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>
-  *code-ending-row<span class="Special"> &lt;- </span>copy row
-  <span class="Comment"># render sandbox warnings, screen or response, in that order</span>
-  response-starting-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>
-  sandbox-response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span>
-  sandbox-warnings:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">warnings:offset</span>
-  sandbox-screen:address<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">screen:offset</span>
-<span class="Constant">  +render-sandbox-results</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> sandbox-warnings
-    *response-starting-row<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># no response</span>
-    row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-warnings, left, right, <span class="Constant">1/red</span>, row
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> sandbox-warnings
-    empty-screen?:boolean<span class="Special"> &lt;- </span>fake-screen-is-empty? sandbox-screen
-    <span class="muControl">break-if</span> empty-screen?
-    row, screen<span class="Special"> &lt;- </span>render-screen screen, sandbox-screen, left, right, row
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> sandbox-warnings
-    <span class="muControl">break-unless</span> empty-screen?
-<span class="CommentedCode">#?     $print [display response from ], row, 10/newline #? 1</span>
-    *response-starting-row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-<span class="Constant">    +render-sandbox-response</span>
-    row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">245/grey</span>, row
-  <span class="Delimiter">}</span>
-<span class="Constant">  +render-sandbox-end</span>
-  at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-  <span class="muControl">reply-if</span> at-bottom?, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Comment"># draw solid line after sandbox</span>
-  draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span>
-  <span class="Comment"># draw next sandbox</span>
-  next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
-  row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, next-sandbox, left, right, row
-  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span>
-<span class="muRecipe">recipe</span> restore-sandboxes [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># read all scenarios, pushing them to end of a list of scenarios</span>
-  suffix:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[.out]</span>
-  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  curr:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
-  <span class="Delimiter">{</span>
-    filename:address:array:character<span class="Special"> &lt;- </span>integer-to-decimal-string idx
-    contents:address:array:character<span class="Special"> &lt;- </span>restore filename
-    <span class="muControl">break-unless</span> contents  <span class="Comment"># stop at first error; assuming file didn't exist</span>
-    <span class="Comment"># create new sandbox for file</span>
-    *curr<span class="Special"> &lt;- </span>new <span class="Constant">sandbox-data:type</span>
-    data:address:address:array:character<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">data:offset</span>
-    *data<span class="Special"> &lt;- </span>copy contents
-    <span class="Comment"># restore expected output for sandbox if it exists</span>
-    <span class="Delimiter">{</span>
-      filename<span class="Special"> &lt;- </span>string-append filename, suffix
-      contents<span class="Special"> &lt;- </span>restore filename
-      <span class="muControl">break-unless</span> contents
-      expected-response:address:address:array:character<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">expected-response:offset</span>
-      *expected-response<span class="Special"> &lt;- </span>copy contents
-    <span class="Delimiter">}</span>
-<span class="Constant">    +continue</span>
-    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
-    curr<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="Comment"># row, screen &lt;- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number</span>
-<span class="Comment"># print the fake sandbox screen to 'screen' with appropriate delimiters</span>
-<span class="Comment"># leave cursor at start of next line</span>
-<span class="muRecipe">recipe</span> render-screen [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  s:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Comment"># print 'screen:'</span>
-  header:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[screen:]</span>
-  row<span class="Special"> &lt;- </span>subtract row, <span class="Constant">1</span>  <span class="Comment"># compensate for render-string below</span>
-  row<span class="Special"> &lt;- </span>render-string screen, header, left, right, <span class="Constant">245/grey</span>, row
-  <span class="Comment"># newline</span>
-  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
-  <span class="Comment"># start printing s</span>
-  column:number<span class="Special"> &lt;- </span>copy left
-  s-width:number<span class="Special"> &lt;- </span>screen-width s
-  s-height:number<span class="Special"> &lt;- </span>screen-height s
-  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *s, <span class="Constant">data:offset</span>
-  stop-printing:number<span class="Special"> &lt;- </span>add left, s-width, <span class="Constant">3</span>
-  max-column:number<span class="Special"> &lt;- </span>min stop-printing, right
-  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  len:number<span class="Special"> &lt;- </span>length *buf
-  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
-  <span class="Delimiter">{</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    <span class="muControl">break-if</span> done?
-    done?<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
-    <span class="muControl">break-if</span> done?
-    column<span class="Special"> &lt;- </span>copy left
-    screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
-    <span class="Comment"># initial leader for each row: two spaces and a '.'</span>
-    print-character screen, <span class="Constant">32/space</span>, <span class="Constant">245/grey</span>
-    print-character screen, <span class="Constant">32/space</span>, <span class="Constant">245/grey</span>
-    print-character screen, <span class="Constant">46/full-stop</span>, <span class="Constant">245/grey</span>
-    column<span class="Special"> &lt;- </span>add left, <span class="Constant">3</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># print row</span>
-      row-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal column, max-column
-      <span class="muControl">break-if</span> row-done?
-      curr:screen-cell<span class="Special"> &lt;- </span>index *buf, i
-      c:character<span class="Special"> &lt;- </span>get curr, <span class="Constant">contents:offset</span>
-      print-character screen, c, <span class="Constant">245/grey</span>
-      column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-      <span class="muControl">loop</span>
-    <span class="Delimiter">}</span>
-    <span class="Comment"># print final '.'</span>
-    print-character screen, <span class="Constant">46/full-stop</span>, <span class="Constant">245/grey</span>
-    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-    <span class="Delimiter">{</span>
-      <span class="Comment"># clear rest of current line</span>
-      line-done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
-      <span class="muControl">break-if</span> line-done?
-      print-character screen, <span class="Constant">32/space</span>
-      column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
-      <span class="muControl">loop</span>
-    <span class="Delimiter">}</span>
-    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="muScenario">scenario</span> run-updates-results [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">12/height</span>
-  <span class="Comment"># define a recipe (no indent for the 'add' line below so column numbers are more obvious)</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">z:number &lt;- add 2, 2</span>
-<span class="Constant">]</span>]
-  <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the code in the editors</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen prints the results</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .z:number &lt;- add 2, 2                              ┊                                                x.</span>
-   <span class="Constant"> .]                                                 ┊foo                                              .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># make a change (incrementing one of the args to 'add'), then rerun</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">28</span>  <span class="Comment"># one past the value of the second arg</span>
-    type <span class="Constant">[«3]</span>  <span class="Comment"># replace</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">4</span>:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">8/backspace</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">171/«</span>, <span class="Constant">4</span>:event/backspace
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen updates the result on the right</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .z:number &lt;- add 2, 3                              ┊                                                x.</span>
-   <span class="Constant"> .]                                                 ┊foo                                              .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊5                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-instruction-and-print-warnings [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># left editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Comment"># right editor contains an illegal instruction</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the code in the editors</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen prints error message in red</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
-   <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">7/white</span>, [
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                   get 1234:number, foo:offset                      .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">1/red</span>, [
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                   unknown element foo in container number          .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-instruction-and-print-warnings-only-once [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># left editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Comment"># right editor contains an illegal instruction</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the code in the editors multiple times</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that screen prints error message just once</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
-   <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-instruction-manages-screen-per-sandbox [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
-  <span class="Comment"># left editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Comment"># right editor contains an instruction</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the code in the editor</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># check that it prints a little toy screen</span>
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
-   <span class="Constant"> .                                                  ┊screen:                                          .</span>
-   <span class="Constant"> .                                                  ┊  .4                             .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> sandbox-with-print-can-be-edited [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
-  <span class="Comment"># left editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Comment"># right editor contains an instruction</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the sandbox</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
-   <span class="Constant"> .                                                  ┊screen:                                          .</span>
-   <span class="Constant"> .                                                  ┊  .4                             .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊  .                              .               .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># edit the sandbox</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">70</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> sandbox-can-handle-infinite-loop [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
-  <span class="Comment"># left editor is empty</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[recipe foo [</span>
-<span class="Constant">  {</span>
-<span class="Constant">    loop</span>
-<span class="Constant">  }</span>
-<span class="Constant">]</span>]
-  <span class="Comment"># right editor contains an instruction</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run the sandbox</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .recipe foo [                                      ┊                                                 .</span>
-   <span class="Constant"> .  {                                               ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .    loop                                          ┊                                                x.</span>
-   <span class="Constant"> .  }                                               ┊foo                                              .</span>
-   <span class="Constant"> .]                                                 ┊took too long!                                   .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muRecipe">recipe</span> editor-contents [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">80</span>
-  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  <span class="Comment"># skip § sentinel</span>
-  assert curr, <span class="Constant">[editor without data is illegal; must have at least a sentinel]</span>
-  curr<span class="Special"> &lt;- </span>next-duplex curr
-  <span class="muControl">reply-unless</span> curr, <span class="Constant">0</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> curr
-    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
-    buffer-append buf, c
-    curr<span class="Special"> &lt;- </span>next-duplex curr
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  result:address:array:character<span class="Special"> &lt;- </span>buffer-to-array buf
-  <span class="muControl">reply</span> result
-]
-
-<span class="muScenario">scenario</span> editor-provides-edited-contents [
-  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
-    type <span class="Constant">[def]</span>
-  ]
-  run [
-    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>editor-contents <span class="Constant">2</span>:address:editor-data
-    <span class="Constant">4</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:character
-  ]
-  memory-should-contain [
-    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abdefc]</span>
-  ]
-]
-
-<span class="SalientComment">## editing sandboxes after they've been created</span>
-
-<span class="muScenario">scenario</span> clicking-on-a-sandbox-moves-it-to-editor [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># basic recipe</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  add 2, 2</span>
-<span class="Constant">]</span>]
-  <span class="Comment"># run it</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  add 2, 2          ┊                  x.</span>
-   <span class="Constant"> .]                   ┊foo                .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  <span class="Comment"># click somewhere on the sandbox</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">30</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># it pops back into editor</span>
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊foo                .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  add 2, 2          ┊                   .</span>
-   <span class="Constant"> .]                   ┊                   .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                   .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +global-touch [
-  <span class="Comment"># right side of screen and below sandbox editor? pop appropriate sandbox</span>
-  <span class="Comment"># contents back into sandbox editor provided it's empty</span>
-  <span class="Delimiter">{</span>
-    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
-    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
-    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
-    <span class="muControl">break-unless</span> on-sandbox-side?
-    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-    <span class="muControl">break-unless</span> first-sandbox
-    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
-    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
-    <span class="muControl">break-unless</span> below-sandbox-editor?
-    empty-sandbox-editor?:boolean<span class="Special"> &lt;- </span>empty-editor? current-sandbox
-    <span class="muControl">break-unless</span> empty-sandbox-editor?  <span class="Comment"># make the user hit F4 before editing a new sandbox</span>
-    <span class="Comment"># identify the sandbox to edit and remove it from the sandbox list</span>
-    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>extract-sandbox env, click-row
-    text:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
-    current-sandbox<span class="Special"> &lt;- </span>insert-text current-sandbox, text
-    hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-    show-screen screen
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> empty-editor? [
-  <span class="Constant">local-scope</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  head:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
-  first:address:duplex-list<span class="Special"> &lt;- </span>next-duplex head
-  result:boolean<span class="Special"> &lt;- </span>not first
-  <span class="muControl">reply</span> result
-]
-
-<span class="muRecipe">recipe</span> extract-sandbox [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
-  sandbox:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
-  start:number<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
-  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
-  <span class="Delimiter">{</span>
-    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">break-unless</span> next-sandbox
-    <span class="Comment"># if click-row &lt; sandbox.next-sandbox.starting-row-on-screen, break</span>
-    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
-    <span class="muControl">break-if</span> found?
-    sandbox<span class="Special"> &lt;- </span>get-address **sandbox, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># snip sandbox out of its list</span>
-  result:address:sandbox-data<span class="Special"> &lt;- </span>copy *sandbox
-  *sandbox<span class="Special"> &lt;- </span>copy next-sandbox
-  <span class="muControl">reply</span> result
-]
-
-<span class="SalientComment">## deleting sandboxes</span>
-
-<span class="muScenario">scenario</span> deleting-sandboxes [
-  $close-trace  <span class="Comment"># trace too long for github</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  <span class="Comment"># run a few commands</span>
-  assume-console [
-    left-click <span class="Constant">1</span>, <span class="Constant">80</span>
-    type <span class="Constant">[divide-with-remainder 11, 3]</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-    type <span class="Constant">[add 2, 2]</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
-   <span class="Constant"> .                                                  ┊4                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
-   <span class="Constant"> .                                                  ┊3                                                .</span>
-   <span class="Constant"> .                                                  ┊2                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># delete second sandbox</span>
-  assume-console [
-    left-click <span class="Constant">7</span>, <span class="Constant">99</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                x.</span>
-   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
-   <span class="Constant"> .                                                  ┊4                                                .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># delete first sandbox</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">99</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muRecipe">after</span> +global-touch [
-  <span class="Comment"># on a sandbox delete icon? process delete</span>
-  <span class="Delimiter">{</span>
-    was-delete?:boolean<span class="Special"> &lt;- </span>delete-sandbox *t, env
-    <span class="muControl">break-unless</span> was-delete?
-<span class="CommentedCode">#?     trace 10, [app], [delete clicked] #? 1</span>
-    hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
-    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
-    show-screen screen
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="Comment"># was-deleted?:boolean &lt;- delete-sandbox t:touch-event, env:address:programming-environment-data</span>
-<span class="muRecipe">recipe</span> delete-sandbox [
-  <span class="Constant">local-scope</span>
-  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span>
-  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
-  right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span>
-  at-right?:boolean<span class="Special"> &lt;- </span>equal click-column, right
-  <span class="muControl">reply-unless</span> at-right?, <span class="Constant">0/false</span>
-  click-row:number<span class="Special"> &lt;- </span>get t, <span class="Constant">row:offset</span>
-  prev:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
-  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> curr
-    <span class="Comment"># more sandboxes to check</span>
-    <span class="Delimiter">{</span>
-      target-row:number<span class="Special"> &lt;- </span>get *curr, <span class="Constant">starting-row-on-screen:offset</span>
-      delete-curr?:boolean<span class="Special"> &lt;- </span>equal target-row, click-row
-      <span class="muControl">break-unless</span> delete-curr?
-      <span class="Comment"># delete this sandbox, rerender and stop</span>
-      *prev<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
-      <span class="muControl">reply</span> <span class="Constant">1/true</span>
-    <span class="Delimiter">}</span>
-    prev<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">next-sandbox:offset</span>
-    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> <span class="Constant">0/false</span>
-]
-
-<span class="SalientComment">## clicking on sandbox results to 'fix' them and turn sandboxes into tests</span>
-
-<span class="muScenario">scenario</span> sandbox-click-on-result-toggles-color-to-green [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># basic recipe</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  add 2, 2</span>
-<span class="Constant">]</span>]
-  <span class="Comment"># run it</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  add 2, 2          ┊                  x.</span>
-   <span class="Constant"> .]                   ┊foo                .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  <span class="Comment"># click on the '4' in the result</span>
-  assume-console [
-    left-click <span class="Constant">5</span>, <span class="Constant">21</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># color toggles to green</span>
-  screen-should-contain-in-color <span class="Constant">2/green</span>, [
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                     4                  .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-  ]
-  <span class="Comment"># now change the second arg of the 'add'</span>
-  <span class="Comment"># then rerun</span>
-  assume-console [
-    left-click <span class="Constant">3</span>, <span class="Constant">11</span>  <span class="Comment"># cursor to end of line</span>
-    type <span class="Constant">[«3]</span>  <span class="Comment"># turn '2' into '3'</span>
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">4</span>:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0/text</span>, <span class="Constant">8/backspace</span>, <span class="Constant">0/dummy</span>, <span class="Constant">0/dummy</span>
-  replace-in-console <span class="Constant">171/«</span>, <span class="Constant">4</span>:event/backspace
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># result turns red</span>
-  screen-should-contain-in-color <span class="Constant">1/red</span>, [
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                     5                  .</span>
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                                        .</span>
-  ]
-]
-
-<span class="Comment"># clicks on sandbox responses save it as 'expected'</span>
-<span class="muRecipe">after</span> +global-touch [
-  <span class="Comment"># right side of screen? check if it's inside the output of any sandbox</span>
-  <span class="Delimiter">{</span>
-    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
-    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
-    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
-    <span class="muControl">break-unless</span> on-sandbox-side?
-    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-    <span class="muControl">break-unless</span> first-sandbox
-    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
-    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
-    <span class="muControl">break-unless</span> below-sandbox-editor?
-    <span class="Comment"># identify the sandbox whose output is being clicked on</span>
-    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>find-click-in-sandbox-output env, click-row
-    <span class="muControl">break-unless</span> sandbox
-    <span class="Comment"># toggle its expected-response, and save session</span>
-    sandbox<span class="Special"> &lt;- </span>toggle-expected-response sandbox
-    save-sandboxes env
-    hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span>
-    <span class="Comment"># no change in cursor</span>
-    show-screen screen
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> find-click-in-sandbox-output [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
-  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
-  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
-  <span class="Comment"># while click-row &lt; sandbox.next-sandbox.starting-row-on-screen</span>
-  <span class="Delimiter">{</span>
-    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">break-unless</span> next-sandbox
-    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
-    <span class="muControl">break-if</span> found?
-    sandbox<span class="Special"> &lt;- </span>copy next-sandbox
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># return sandbox if click is in its output region</span>
-  response-starting-row:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>
-  <span class="muControl">reply-unless</span> response-starting-row, <span class="Constant">0/no-click-in-sandbox-output</span>
-  click-in-response?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, response-starting-row
-  <span class="muControl">reply-unless</span> click-in-response?, <span class="Constant">0/no-click-in-sandbox-output</span>
-  <span class="muControl">reply</span> sandbox
-]
-
-<span class="muRecipe">recipe</span> toggle-expected-response [
-  <span class="Constant">local-scope</span>
-  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  expected-response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">expected-response:offset</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># if expected-response is set, reset</span>
-    <span class="muControl">break-unless</span> *expected-response
-    *expected-response<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-    <span class="muControl">reply</span> sandbox/same-as-ingredient:<span class="Constant">0</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># if not, current response is the expected response</span>
-  response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span>
-  *expected-response<span class="Special"> &lt;- </span>copy response
-  <span class="muControl">reply</span> sandbox/same-as-ingredient:<span class="Constant">0</span>
-]
-
-<span class="Comment"># when rendering a sandbox, color it in red/green if expected response exists</span>
-<span class="muRecipe">after</span> +render-sandbox-response [
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-unless</span> sandbox-response
-    expected-response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">expected-response:offset</span>
-    <span class="muControl">break-unless</span> expected-response  <span class="Comment"># fall-through to print in grey</span>
-    response-is-expected?:boolean<span class="Special"> &lt;- </span>string-equal expected-response, sandbox-response
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-if</span> response-is-expected?:boolean
-      row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">1/red</span>, row
-    <span class="Delimiter">}</span>
-    <span class="Delimiter">{</span>
-      <span class="muControl">break-unless</span> response-is-expected?:boolean
-      row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">2/green</span>, row
-    <span class="Delimiter">}</span>
-    <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="SalientComment">## clicking on the code typed into a sandbox toggles its trace</span>
-
-<span class="muScenario">scenario</span> sandbox-click-on-code-toggles-app-trace [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># basic recipe</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  stash [abc]</span>
-]]
-  <span class="Comment"># run it</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
-   <span class="Constant"> .]                   ┊foo                .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  <span class="Comment"># click on the 'foo' line in the sandbox</span>
-  assume-console [
-    left-click <span class="Constant">4</span>, <span class="Constant">21</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># trace now printed</span>
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
-   <span class="Constant"> .]                   ┊foo                .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
-   <span class="Constant"> .                                        .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                  x.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  <span class="Comment"># click again on the same region</span>
-  assume-console [
-    left-click <span class="Constant">4</span>, <span class="Constant">25</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># trace hidden again</span>
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
-   <span class="Constant"> .]                   ┊foo                .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> sandbox-shows-app-trace-and-result [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
-  <span class="Comment"># basic recipe</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  stash [abc]</span>
-  add <span class="Constant">2</span>, <span class="Constant">2</span>
-]]
-  <span class="Comment"># run it</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
-   <span class="Constant"> .  add 2, 2          ┊foo                .</span>
-   <span class="Constant"> .]                   ┊4                  .</span>
-<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-  <span class="Comment"># click on the 'foo' line in the sandbox</span>
-  assume-console [
-    left-click <span class="Constant">4</span>, <span class="Constant">21</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  <span class="Comment"># trace now printed</span>
-  screen-should-contain [
-   <span class="Constant"> .                     run (F4)           .</span>
-   <span class="Constant"> .                    ┊                   .</span>
-   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
-   <span class="Constant"> .  add 2, 2          ┊foo                .</span>
-   <span class="Constant"> .]                   ┊abc                .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
-   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                    ┊                   .</span>
-  ]
-]
-
-<span class="Comment"># clicks on sandbox code toggle its display-trace? flag</span>
-<span class="muRecipe">after</span> +global-touch [
-  <span class="Comment"># right side of screen? check if it's inside the code of any sandbox</span>
-  <span class="Delimiter">{</span>
-    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
-    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
-    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
-    <span class="muControl">break-unless</span> on-sandbox-side?
-    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-    <span class="muControl">break-unless</span> first-sandbox
-    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
-    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
-    <span class="muControl">break-unless</span> below-sandbox-editor?
-    <span class="Comment"># identify the sandbox whose code is being clicked on</span>
-    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>find-click-in-sandbox-code env, click-row
-    <span class="muControl">break-unless</span> sandbox
-    <span class="Comment"># toggle its display-trace? property</span>
-    x:address:boolean<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">display-trace?:offset</span>
-    *x<span class="Special"> &lt;- </span>not *x
-    hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span>
-    <span class="Comment"># no change in cursor</span>
-    show-screen screen
-    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> find-click-in-sandbox-code [
-  <span class="Constant">local-scope</span>
-  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
-  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
-  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
-  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
-  <span class="Comment"># while click-row &lt; sandbox.next-sandbox.starting-row-on-screen</span>
-  <span class="Delimiter">{</span>
-    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
-    <span class="muControl">break-unless</span> next-sandbox
-    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
-    <span class="muControl">break-if</span> found?
-    sandbox<span class="Special"> &lt;- </span>copy next-sandbox
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># return sandbox if click is in its code region</span>
-  code-ending-row:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>
-  click-above-response?:boolean<span class="Special"> &lt;- </span>lesser-or-equal click-row, code-ending-row
-  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
-  click-below-menu?:boolean<span class="Special"> &lt;- </span>greater-than click-row, start
-  click-on-sandbox-code?:boolean<span class="Special"> &lt;- </span>and click-above-response?, click-below-menu?
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> click-on-sandbox-code?
-    <span class="muControl">reply</span> <span class="Constant">0/no-click-in-sandbox-output</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> sandbox
-]
-
-<span class="Comment"># when rendering a sandbox, dump its trace before response/warning if display-trace? property is set</span>
-<span class="muRecipe">after</span> +render-sandbox-results [
-  <span class="Delimiter">{</span>
-    display-trace?:boolean<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">display-trace?:offset</span>
-    <span class="muControl">break-unless</span> display-trace?
-    sandbox-trace:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">trace:offset</span>
-    <span class="muControl">break-unless</span> sandbox-trace  <span class="Comment"># nothing to print; move on</span>
-<span class="CommentedCode">#?     $print [display trace from ], row, 10/newline #? 1</span>
-    row, screen<span class="Special"> &lt;- </span>render-string, screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row
-    row<span class="Special"> &lt;- </span>subtract row, <span class="Constant">1</span>  <span class="Comment"># trim the trailing newline that's always present</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="SalientComment">## handling malformed programs</span>
-
-<span class="muScenario">scenario</span> run-shows-warnings-in-get [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  get 123:number, foo:offset</span>
-<span class="Constant">]</span>]
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  get 123:number, foo:offset                      ┊                                                 .</span>
-   <span class="Constant"> .]                                                 ┊                                                 .</span>
-   <span class="Constant"> .unknown element foo in container number           ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  screen-should-contain-in-color <span class="Constant">1/red</span>, [
-   <span class="Constant"> .  errors found                                                                                      .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-   <span class="Constant"> .unknown element foo in container number                                                             .</span>
-   <span class="Constant"> .                                                                                                    .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-shows-missing-type-warnings [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  x &lt;- copy 0</span>
-<span class="Constant">]</span>]
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x &lt;- copy 0                                     ┊                                                 .</span>
-   <span class="Constant"> .]                                                 ┊                                                 .</span>
-   <span class="Constant"> .missing type in 'x &lt;- copy 0'                     ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-shows-unbalanced-bracket-warnings [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Comment"># recipe is incomplete (unbalanced '[')</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo «</span>
-<span class="Constant">  x &lt;- copy 0</span>
-<span class="Constant">]</span>
-  string-replace <span class="Constant">1</span>:address:array:character, <span class="Constant">171/«</span>, <span class="Constant">91</span>  <span class="Comment"># '['</span>
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo \\\[                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x &lt;- copy 0                                     ┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .9: unbalanced '\\\[' for recipe                      ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-shows-get-on-non-container-warnings [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  x:address:point &lt;- new point:type</span>
-<span class="Constant">  get x:address:point, 1:offset</span>
-<span class="Constant">]</span>]
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .                                                                                 run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x:address:point &lt;- new point:type               ┊                                                x.</span>
-   <span class="Constant"> .  get x:address:point, 1:offset                   ┊foo                                              .</span>
-   <span class="Constant"> .]                                                 ┊foo: first ingredient of 'get' should be a conta↩.</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊iner, but got x:address:point                    .</span>
-   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-shows-non-literal-get-argument-warnings [
-<span class="Constant">  $close-trace</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  x:number &lt;- copy 0</span>
-<span class="Constant">  y:address:point &lt;- new point:type</span>
-<span class="Constant">  get *y:address:point, x:number</span>
-<span class="Constant">]</span>]
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x:number &lt;- copy 0                              ┊                                                 .</span>
-   <span class="Constant"> .  y:address:point &lt;- new point:type               ┊                                                 .</span>
-   <span class="Constant"> .  get *y:address:point, x:number                  ┊                                                 .</span>
-   <span class="Constant"> .]                                                 ┊                                                 .</span>
-   <span class="Constant"> .foo: expected ingredient 1 of 'get' to have type ↩┊                                                 .</span>
-   <span class="Constant"> .'offset'; got x:number                            ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="muScenario">scenario</span> run-shows-warnings-everytime [
-<span class="Constant">  $close-trace</span>
-  <span class="Comment"># try to run a file with an error</span>
-  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
-  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
-<span class="Constant">recipe foo [</span>
-<span class="Constant">  x:number &lt;- copy y:number</span>
-<span class="Constant">]</span>]
-  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
-  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x:number &lt;- copy y:number                       ┊                                                 .</span>
-   <span class="Constant"> .]                                                 ┊                                                 .</span>
-   <span class="Constant"> .use before set: y in foo                          ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-  <span class="Comment"># rerun the file, check for the same error</span>
-  assume-console [
-    press <span class="Constant">65532</span>  <span class="Comment"># F4</span>
-  ]
-  run [
-    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
-  ]
-  screen-should-contain [
-   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
-   <span class="Constant"> .                                                  ┊foo                                              .</span>
-   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
-   <span class="Constant"> .  x:number &lt;- copy y:number                       ┊                                                 .</span>
-   <span class="Constant"> .]                                                 ┊                                                 .</span>
-   <span class="Constant"> .use before set: y in foo                          ┊                                                 .</span>
-   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
-   <span class="Constant"> .                                                  ┊                                                 .</span>
-  ]
-]
-
-<span class="SalientComment">## helpers for drawing editor borders</span>
-
-<span class="muRecipe">recipe</span> draw-box [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment"># top border</span>
-  draw-horizontal screen, top, left, right, color
-  draw-horizontal screen, bottom, left, right, color
-  draw-vertical screen, left, top, bottom, color
-  draw-vertical screen, right, top, bottom, color
-  draw-top-left screen, top, left, color
-  draw-top-right screen, top, right, color
-  draw-bottom-left screen, bottom, left, color
-  draw-bottom-right screen, bottom, right, color
-  <span class="Comment"># position cursor inside box</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, top, left
-  cursor-down screen
-  cursor-right screen
-]
-
-<span class="muRecipe">recipe</span> draw-horizontal [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> style-found?
-    style<span class="Special"> &lt;- </span>copy <span class="Constant">9472/horizontal</span>
-  <span class="Delimiter">}</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> bg-color-found?
-    bg-color<span class="Special"> &lt;- </span>copy <span class="Constant">0/black</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, row, x
-  <span class="Delimiter">{</span>
-    continue?:boolean<span class="Special"> &lt;- </span>lesser-or-equal x, right  <span class="Comment"># right is inclusive, to match editor-data semantics</span>
-    <span class="muControl">break-unless</span> continue?
-    print-character screen, style, color, bg-color
-    x<span class="Special"> &lt;- </span>add x, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> draw-vertical [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  col:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="muControl">break-if</span> style-found?
-    style<span class="Special"> &lt;- </span>copy <span class="Constant">9474/vertical</span>
-  <span class="Delimiter">}</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  <span class="Delimiter">{</span>
-    continue?:boolean<span class="Special"> &lt;- </span>lesser-than y, bottom
-    <span class="muControl">break-unless</span> continue?
-    screen<span class="Special"> &lt;- </span>move-cursor screen, y, col
-    print-character screen, style, color
-    y<span class="Special"> &lt;- </span>add y, <span class="Constant">1</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-]
-
-<span class="muRecipe">recipe</span> draw-top-left [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, top, left
-  print-character screen, <span class="Constant">9484/down-right</span>, color
-]
-
-<span class="muRecipe">recipe</span> draw-top-right [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, top, right
-  print-character screen, <span class="Constant">9488/down-left</span>, color
-]
-
-<span class="muRecipe">recipe</span> draw-bottom-left [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, bottom, left
-  print-character screen, <span class="Constant">9492/up-right</span>, color
-]
-
-<span class="muRecipe">recipe</span> draw-bottom-right [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  <span class="Delimiter">{</span>
-    <span class="Comment"># default color to white</span>
-    <span class="muControl">break-if</span> color-found?
-    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
-  <span class="Delimiter">}</span>
-  screen<span class="Special"> &lt;- </span>move-cursor screen, bottom, right
-  print-character screen, <span class="Constant">9496/up-left</span>, color
-]
-
-<span class="muRecipe">recipe</span> print-string-with-gradient-background [
-  <span class="Constant">local-scope</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bg-color1:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  bg-color2:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  len:number<span class="Special"> &lt;- </span>length *s
-  color-range:number<span class="Special"> &lt;- </span>subtract bg-color2, bg-color1
-  color-quantum:number<span class="Special"> &lt;- </span>divide color-range, len
-  bg-color:number<span class="Special"> &lt;- </span>copy bg-color1
-  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
-  <span class="Delimiter">{</span>
-    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
-    <span class="muControl">break-if</span> done?
-    c:character<span class="Special"> &lt;- </span>index *s, i
-    print-character screen, c, color, bg-color
-    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
-    bg-color<span class="Special"> &lt;- </span>add bg-color, color-quantum
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
-]
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/001-editor.mu.html b/html/edit/001-editor.mu.html
new file mode 100644
index 00000000..be568c9d
--- /dev/null
+++ b/html/edit/001-editor.mu.html
@@ -0,0 +1,539 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/001-editor.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muScenario { color: #00af00; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## the basic editor data structure, and how it displays text to the screen</span>
+
+<span class="Comment"># temporary main for this layer: just render the given string at the given</span>
+<span class="Comment"># screen dimensions, then stop</span>
+<span class="muRecipe">recipe!</span> main [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  open-console
+  hide-screen <span class="Constant">0/screen</span>
+  new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  show-screen <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  close-console
+]
+
+<span class="muScenario">scenario</span> editor-initially-prints-string-to-screen [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  run [
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  ]
+  screen-should-contain [
+    <span class="Comment"># top line of screen reserved for menu</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muData">container</span> editor-data [
+  <span class="Comment"># editable text: doubly linked list of characters (head contains a special sentinel)</span>
+  data:address:duplex-list:character
+  top-of-screen:address:duplex-list:character
+  bottom-of-screen:address:duplex-list:character
+  <span class="Comment"># location before cursor inside data</span>
+  before-cursor:address:duplex-list:character
+
+  <span class="Comment"># raw bounds of display area on screen</span>
+  <span class="Comment"># always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen</span>
+  left:number
+  right:number
+  <span class="Comment"># raw screen coordinates of cursor</span>
+  cursor-row:number
+  cursor-column:number
+]
+
+<span class="Comment"># editor:address, screen &lt;- new-editor s:address:array:character, screen:address, left:number, right:number</span>
+<span class="Comment"># creates a new editor widget and renders its initial appearance to screen.</span>
+<span class="Comment">#   top/left/right constrain the screen area available to the new editor.</span>
+<span class="Comment">#   right is exclusive.</span>
+<span class="muRecipe">recipe</span> new-editor [
+  <span class="Constant">local-scope</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># no clipping of bounds</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
+  result:address:editor-data<span class="Special"> &lt;- </span>new <span class="Constant">editor-data:type</span>
+  <span class="Comment"># initialize screen-related fields</span>
+  x:address:number<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">left:offset</span>
+  *x<span class="Special"> &lt;- </span>copy left
+  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">right:offset</span>
+  *x<span class="Special"> &lt;- </span>copy right
+  <span class="Comment"># initialize cursor</span>
+  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-row:offset</span>
+  *x<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
+  x<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">cursor-column:offset</span>
+  *x<span class="Special"> &lt;- </span>copy left
+  init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">data:offset</span>
+  *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span>
+  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">top-of-screen:offset</span>
+  *top-of-screen<span class="Special"> &lt;- </span>copy *init
+  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span>
+  *y<span class="Special"> &lt;- </span>copy *init
+  result<span class="Special"> &lt;- </span>insert-text result, s
+  <span class="Comment"># initialize cursor to top of screen</span>
+  y<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">before-cursor:offset</span>
+  *y<span class="Special"> &lt;- </span>copy *init
+  <span class="Comment"># initial render to screen, just for some old tests</span>
+  _, _, screen, result<span class="Special"> &lt;- </span>render screen, result
+<span class="Constant">  &lt;editor-initialization&gt;</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muRecipe">recipe</span> insert-text [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># early exit if text is empty</span>
+  <span class="muControl">reply-unless</span> text, editor/same-as-ingredient:<span class="Constant">0</span>
+  len:number<span class="Special"> &lt;- </span>length *text
+  <span class="muControl">reply-unless</span> len, editor/same-as-ingredient:<span class="Constant">0</span>
+  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Comment"># now we can start appending the rest, character by character</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx, len
+    <span class="muControl">break-if</span> done?
+    c:character<span class="Special"> &lt;- </span>index *text, idx
+    insert-duplex c, curr
+    <span class="Comment"># next iter</span>
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muScenario">scenario</span> editor-initializes-without-data [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">3/height</span>
+  run [
+    <span class="Constant">1</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">0/data</span>, screen:address, <span class="Constant">2/left</span>, <span class="Constant">5/right</span>
+    <span class="Constant">2</span>:editor-data<span class="Special"> &lt;- </span>copy *<span class="Constant">1</span>:address:editor-data
+  ]
+  memory-should-contain [
+    <span class="Comment"># 2 (data) &lt;- just the § sentinel</span>
+    <span class="Comment"># 3 (top of screen) &lt;- the § sentinel</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># bottom-of-screen; null since text fits on screen</span>
+    <span class="Comment"># 5 (before cursor) &lt;- the § sentinel</span>
+    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># left</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">4</span>  <span class="Comment"># right  (inclusive)</span>
+    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">9</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="Comment"># last-row:number, last-column:number, screen, editor &lt;- render screen:address, editor:address:editor-data</span>
+<span class="Comment">#</span>
+<span class="Comment"># Assumes cursor should be at coordinates (cursor-row, cursor-column) and</span>
+<span class="Comment"># updates before-cursor to match. Might also move coordinates if they're</span>
+<span class="Comment"># outside text.</span>
+<span class="muRecipe">recipe</span> render [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, <span class="Constant">0/left</span>, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  <span class="Comment"># traversing editor</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span>
+  curr<span class="Special"> &lt;- </span>next-duplex curr
+  <span class="Comment"># traversing screen</span>
+<span class="Constant">  +render-loop-initialization</span>
+  color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
+  column:number<span class="Special"> &lt;- </span>copy left
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+  <span class="Delimiter">{</span>
+<span class="Constant">    +next-character</span>
+    <span class="muControl">break-unless</span> curr
+    off-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> off-screen?
+    <span class="Comment"># update editor-data.before-cursor</span>
+    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
+    <span class="Comment"># the current character.</span>
+    <span class="Delimiter">{</span>
+      at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+      <span class="muControl">break-unless</span> at-cursor-row?
+      at-cursor?:boolean<span class="Special"> &lt;- </span>equal column, *cursor-column
+      <span class="muControl">break-unless</span> at-cursor?
+      *before-cursor<span class="Special"> &lt;- </span>copy prev
+    <span class="Delimiter">}</span>
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+<span class="Constant">    &lt;character-c-received&gt;</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># newline? move to left rather than 0</span>
+      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> newline?
+      <span class="Comment"># adjust cursor if necessary</span>
+      <span class="Delimiter">{</span>
+        at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+        <span class="muControl">break-unless</span> at-cursor-row?
+        left-of-cursor?:boolean<span class="Special"> &lt;- </span>lesser-than column, *cursor-column
+        <span class="muControl">break-unless</span> left-of-cursor?
+        *cursor-column<span class="Special"> &lt;- </span>copy column
+        *before-cursor<span class="Special"> &lt;- </span>prev-duplex curr
+      <span class="Delimiter">}</span>
+      <span class="Comment"># clear rest of line in this window</span>
+      clear-line-delimited screen, column, right
+      <span class="Comment"># skip to next line</span>
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      column<span class="Special"> &lt;- </span>copy left
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      curr<span class="Special"> &lt;- </span>next-duplex curr
+      prev<span class="Special"> &lt;- </span>next-duplex prev
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
+      <span class="Comment"># room for clicking on the cursor after it.</span>
+      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
+      <span class="muControl">break-unless</span> at-right?
+      <span class="Comment"># print wrap icon</span>
+      print-character screen, <span class="Constant">8617/loop-back-to-left</span>, <span class="Constant">245/grey</span>
+      column<span class="Special"> &lt;- </span>copy left
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      <span class="Comment"># don't increment curr</span>
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    print-character screen, c, color
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    prev<span class="Special"> &lt;- </span>next-duplex prev
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># save first character off-screen</span>
+  bottom-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">bottom-of-screen:offset</span>
+  *bottom-of-screen<span class="Special"> &lt;- </span>copy curr
+  <span class="Comment"># is cursor to the right of the last line? move to end</span>
+  <span class="Delimiter">{</span>
+    at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+    cursor-outside-line?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column, *cursor-column
+    before-cursor-on-same-line?:boolean<span class="Special"> &lt;- </span>and at-cursor-row?, cursor-outside-line?
+    above-cursor-row?:boolean<span class="Special"> &lt;- </span>lesser-than row, *cursor-row
+    before-cursor?:boolean<span class="Special"> &lt;- </span>or before-cursor-on-same-line?, above-cursor-row?
+    <span class="muControl">break-unless</span> before-cursor?
+    *cursor-row<span class="Special"> &lt;- </span>copy row
+    *cursor-column<span class="Special"> &lt;- </span>copy column
+    *before-cursor<span class="Special"> &lt;- </span>copy prev
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="muRecipe">recipe</span> clear-line-delimited [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
+    <span class="muControl">break-if</span> done?
+    print-character screen, <span class="Constant">32/space</span>
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> clear-screen-from [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if it's the real screen, use the optimized primitive</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> screen
+    clear-display-from row, column, left, right
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if not, go the slower route</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+  clear-line-delimited screen, column, right
+  clear-rest-of-screen screen, row, left, right
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">recipe</span> clear-rest-of-screen [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Delimiter">{</span>
+    at-bottom-of-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> at-bottom-of-screen?
+    screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
+    clear-line-delimited screen, left, right
+    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-initially-prints-multiple-lines [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc  .</span>
+   <span class="Constant"> .def  .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-initially-handles-offsets [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> . abc .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-initially-prints-multiple-lines-at-offset [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">5/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> . abc .</span>
+   <span class="Constant"> . def .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-initially-wraps-long-lines [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc def]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc ↩.</span>
+   <span class="Constant"> .def  .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">245/grey</span> [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .    ↩.</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-initially-wraps-barely-long-lines [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  ]
+  <span class="Comment"># still wrap, even though the line would fit. We need room to click on the</span>
+  <span class="Comment"># end of the line</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+<span class="Constant">    .abcd↩.</span>
+   <span class="Constant"> .e    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">245/grey</span> [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .    ↩.</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-initializes-empty-text [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="Comment"># just a little color for mu code</span>
+
+<span class="muScenario">scenario</span> render-colors-comments [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant"># de</span>
+<span class="Constant">f]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc  .</span>
+   <span class="Constant"> .# de .</span>
+   <span class="Constant"> .f    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">12/lightblue</span>, [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .# de .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">7/white</span>, [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .abc  .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .f    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;character-c-received&gt;</span> [
+  color<span class="Special"> &lt;- </span>get-color color, c
+]
+
+<span class="Comment"># color &lt;- get-color color:number, c:character</span>
+<span class="Comment"># so far the previous color is all the information we need; that may change</span>
+<span class="muRecipe">recipe</span> get-color [
+  <span class="Constant">local-scope</span>
+  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color-is-white?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">7/white</span>
+  <span class="Comment"># if color is white and next character is '#', switch color to blue</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> color-is-white?
+    starting-comment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">35/#</span>
+    <span class="muControl">break-unless</span> starting-comment?
+    trace <span class="Constant">90</span>, <span class="Constant">[app]</span>, <span class="Constant">[switch color back to blue]</span>
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">12/lightblue</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is blue and next character is newline, switch color to white</span>
+  <span class="Delimiter">{</span>
+    color-is-blue?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">12/lightblue</span>
+    <span class="muControl">break-unless</span> color-is-blue?
+    ending-comment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> ending-comment?
+    trace <span class="Constant">90</span>, <span class="Constant">[app]</span>, <span class="Constant">[switch color back to white]</span>
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is white (no comments) and next character is '&lt;', switch color to red</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> color-is-white?
+    starting-assignment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">60/&lt;</span>
+    <span class="muControl">break-unless</span> starting-assignment?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">1/red</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if color is red and next character is space, switch color to white</span>
+  <span class="Delimiter">{</span>
+    color-is-red?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">1/red</span>
+    <span class="muControl">break-unless</span> color-is-red?
+    ending-assignment?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span>
+    <span class="muControl">break-unless</span> ending-assignment?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+    <span class="muControl">jump</span> <span class="Constant">+exit:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise no change</span>
+<span class="Constant">  +exit</span>
+  <span class="muControl">reply</span> color
+]
+
+<span class="muScenario">scenario</span> render-colors-assignment [
+  assume-screen <span class="Constant">8/width</span>, <span class="Constant">5/height</span>
+  run [
+    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d &lt;- e</span>
+<span class="Constant">f]</span>
+    new-editor s:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">8/right</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .abc     .</span>
+   <span class="Constant"> .d &lt;- e  .</span>
+   <span class="Constant"> .f       .</span>
+   <span class="Constant"> .        .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">1/red</span>, [
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .  &lt;-    .</span>
+   <span class="Constant"> .        .</span>
+   <span class="Constant"> .        .</span>
+  ]
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html
new file mode 100644
index 00000000..787e3a4e
--- /dev/null
+++ b/html/edit/002-typing.mu.html
@@ -0,0 +1,1092 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/002-typing.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muScenario { color: #00af00; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span>
+
+<span class="Comment"># temporary main: interactive editor</span>
+<span class="Comment"># hit ctrl-c to exit</span>
+<span class="muRecipe">recipe!</span> main [
+  <span class="Constant">local-scope</span>
+  text:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  open-console
+  editor:address:editor-data<span class="Special"> &lt;- </span>new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">5/left</span>, <span class="Constant">45/right</span>
+  editor-event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, editor
+  close-console
+]
+
+<span class="muRecipe">recipe</span> editor-event-loop [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span>
+<span class="Constant">    +next-event</span>
+    cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
+    cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span>
+    screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
+    e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console
+    <span class="muControl">loop-unless</span> found?
+    <span class="muControl">break-if</span> quit?  <span class="Comment"># only in tests</span>
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
+    <span class="Comment"># 'touch' event</span>
+    t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e, <span class="Constant">touch:variant</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> t
+      move-cursor-in-editor screen, editor, *t
+      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># keyboard events</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> t
+      screen, editor, go-render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, editor, e
+      <span class="Delimiter">{</span>
+        <span class="muControl">break-unless</span> go-render?
+        screen<span class="Special"> &lt;- </span>editor-render screen, editor
+      <span class="Delimiter">}</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># process click, return if it was on current editor</span>
+<span class="muRecipe">recipe</span> move-cursor-in-editor [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> editor, <span class="Constant">0/false</span>
+  click-row:number<span class="Special"> &lt;- </span>get t, <span class="Constant">row:offset</span>
+  <span class="muControl">reply-unless</span> click-row, <span class="Constant">0/false</span>  <span class="Comment"># ignore clicks on 'menu'</span>
+  click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  too-far-left?:boolean<span class="Special"> &lt;- </span>lesser-than click-column, left
+  <span class="muControl">reply-if</span> too-far-left?, <span class="Constant">0/false</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  too-far-right?:boolean<span class="Special"> &lt;- </span>greater-than click-column, right
+  <span class="muControl">reply-if</span> too-far-right?, <span class="Constant">0/false</span>
+  <span class="Comment"># position cursor</span>
+<span class="Constant">  &lt;move-cursor-begin&gt;</span>
+  editor<span class="Special"> &lt;- </span>snap-cursor screen, editor, click-row, click-column
+  undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">  &lt;move-cursor-end&gt;</span>
+  <span class="Comment"># gain focus</span>
+  <span class="muControl">reply</span> <span class="Constant">1/true</span>
+]
+
+<span class="Comment"># editor &lt;- snap-cursor screen:address, editor:address:editor-data, target-row:number, target-column:number</span>
+<span class="Comment">#</span>
+<span class="Comment"># Variant of 'render' that only moves the cursor (coordinates and</span>
+<span class="Comment"># before-cursor). If it's past the end of a line, it 'slides' it left. If it's</span>
+<span class="Comment"># past the last line it positions at end of last line.</span>
+<span class="muRecipe">recipe</span> snap-cursor [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  target-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  target-column:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, editor/same-as-ingredient:<span class="Constant">1</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Comment"># count newlines until screen row</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span>
+  curr<span class="Special"> &lt;- </span>next-duplex curr
+  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/top</span>
+  column:number<span class="Special"> &lt;- </span>copy left
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  *cursor-row<span class="Special"> &lt;- </span>copy target-row
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy target-column
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  <span class="Delimiter">{</span>
+<span class="Constant">    +next-character</span>
+    <span class="muControl">break-unless</span> curr
+    off-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> off-screen?
+    <span class="Comment"># update editor-data.before-cursor</span>
+    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
+    <span class="Comment"># the current character.</span>
+    <span class="Delimiter">{</span>
+      at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+      <span class="muControl">break-unless</span> at-cursor-row?
+      at-cursor?:boolean<span class="Special"> &lt;- </span>equal column, *cursor-column
+      <span class="muControl">break-unless</span> at-cursor?
+      *before-cursor<span class="Special"> &lt;- </span>copy prev
+    <span class="Delimiter">}</span>
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># newline? move to left rather than 0</span>
+      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> newline?
+      <span class="Comment"># adjust cursor if necessary</span>
+      <span class="Delimiter">{</span>
+        at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+        <span class="muControl">break-unless</span> at-cursor-row?
+        left-of-cursor?:boolean<span class="Special"> &lt;- </span>lesser-than column, *cursor-column
+        <span class="muControl">break-unless</span> left-of-cursor?
+        *cursor-column<span class="Special"> &lt;- </span>copy column
+        *before-cursor<span class="Special"> &lt;- </span>copy prev
+      <span class="Delimiter">}</span>
+      <span class="Comment"># skip to next line</span>
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      column<span class="Special"> &lt;- </span>copy left
+      curr<span class="Special"> &lt;- </span>next-duplex curr
+      prev<span class="Special"> &lt;- </span>next-duplex prev
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
+      <span class="Comment"># room for clicking on the cursor after it.</span>
+      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
+      <span class="muControl">break-unless</span> at-right?
+      column<span class="Special"> &lt;- </span>copy left
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      <span class="Comment"># don't increment curr/prev</span>
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    prev<span class="Special"> &lt;- </span>next-duplex prev
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># is cursor to the right of the last line? move to end</span>
+  <span class="Delimiter">{</span>
+    at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row, *cursor-row
+    cursor-outside-line?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column, *cursor-column
+    before-cursor-on-same-line?:boolean<span class="Special"> &lt;- </span>and at-cursor-row?, cursor-outside-line?
+    above-cursor-row?:boolean<span class="Special"> &lt;- </span>lesser-than row, *cursor-row
+    before-cursor?:boolean<span class="Special"> &lt;- </span>or before-cursor-on-same-line?, above-cursor-row?
+    <span class="muControl">break-unless</span> before-cursor?
+    *cursor-row<span class="Special"> &lt;- </span>copy row
+    *cursor-column<span class="Special"> &lt;- </span>copy column
+    *before-cursor<span class="Special"> &lt;- </span>copy prev
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="Comment"># screen, editor, go-render?:boolean &lt;- handle-keyboard-event screen:address, editor:address:editor-data, e:event</span>
+<span class="Comment"># Process an event 'e' and try to minimally update the screen.</span>
+<span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span>
+<span class="muRecipe">recipe</span> handle-keyboard-event [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  e:event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> editor, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  save-row:number<span class="Special"> &lt;- </span>copy *cursor-row
+  save-column:number<span class="Special"> &lt;- </span>copy *cursor-column
+  <span class="Comment"># character</span>
+  <span class="Delimiter">{</span>
+    c:address:character<span class="Special"> &lt;- </span>maybe-convert e, <span class="Constant">text:variant</span>
+    <span class="muControl">break-unless</span> c
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[handle-keyboard-event: special character]</span>
+    <span class="Comment"># exceptions for special characters go here</span>
+<span class="Constant">    &lt;handle-special-character&gt;</span>
+    <span class="Comment"># ignore any other special characters</span>
+    regular-character?:boolean<span class="Special"> &lt;- </span>greater-or-equal *c, <span class="Constant">32/space</span>
+    <span class="muControl">reply-unless</span> regular-character?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+    <span class="Comment"># otherwise type it in</span>
+<span class="Constant">    &lt;insert-character-begin&gt;</span>
+    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, *c, screen
+<span class="Constant">    &lt;insert-character-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+  <span class="Comment"># special key to modify the text or move the cursor</span>
+  k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span>
+  assert k, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
+  <span class="Comment"># handlers for each special key will go here</span>
+<span class="Constant">  &lt;handle-special-key&gt;</span>
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+]
+
+<span class="muRecipe">recipe</span> insert-at-cursor [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  insert-duplex c, *before-cursor
+  *before-cursor<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  save-row:number<span class="Special"> &lt;- </span>copy *cursor-row
+  save-column:number<span class="Special"> &lt;- </span>copy *cursor-column
+  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Comment"># occasionally we'll need to mess with the cursor</span>
+<span class="Constant">  &lt;insert-character-special-case&gt;</span>
+  <span class="Comment"># but mostly we'll just move the cursor right</span>
+  *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
+  next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  <span class="Delimiter">{</span>
+    <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span>
+    at-end?:boolean<span class="Special"> &lt;- </span>equal next, <span class="Constant">0/null</span>
+    <span class="muControl">break-unless</span> at-end?
+    bottom:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1</span>
+    at-bottom?:boolean<span class="Special"> &lt;- </span>equal save-row, bottom
+    at-right?:boolean<span class="Special"> &lt;- </span>equal save-column, right
+    overflow?:boolean<span class="Special"> &lt;- </span>and at-bottom?, at-right?
+    <span class="muControl">break-if</span> overflow?
+    move-cursor screen, save-row, save-column
+    print-character screen, c
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># not at right margin? print the character and rest of line</span>
+    <span class="muControl">break-unless</span> next
+    at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, screen-width
+    <span class="muControl">break-if</span> at-right?
+    curr:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+    move-cursor screen, save-row, save-column
+    curr-column:number<span class="Special"> &lt;- </span>copy save-column
+    <span class="Delimiter">{</span>
+      <span class="Comment"># hit right margin? give up and let caller render</span>
+      at-right?:boolean<span class="Special"> &lt;- </span>greater-than curr-column, right
+      <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
+      <span class="muControl">break-unless</span> curr
+      <span class="Comment"># newline? done.</span>
+      currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+      at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> at-newline?
+      print-character screen, currc
+      curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
+      curr<span class="Special"> &lt;- </span>next-duplex curr
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
+]
+
+<span class="Comment"># helper for tests</span>
+<span class="muRecipe">recipe</span> editor-render [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  row:number, column:number<span class="Special"> &lt;- </span>render screen, editor
+  clear-line-delimited screen, column, right
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  clear-screen-from screen, row, left, left, right
+]
+
+<span class="muScenario">scenario</span> editor-handles-empty-event-queue [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console <span class="Constant">[]</span>
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>  <span class="Comment"># on the 'b'</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor is at row 0..</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># ..and column 1</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">7</span>  <span class="Comment"># last line, to the right of text</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">7</span>  <span class="Comment"># interior line, to the right of text</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">7</span>  <span class="Comment"># below text</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Comment"># editor occupies only left half of screen</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    <span class="Comment"># click on right half of screen</span>
+    left-click <span class="Constant">3</span>, <span class="Constant">8</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># no change to cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># ..or column</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-in-menu-area [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    <span class="Comment"># click on first, 'menu' row</span>
+    left-click <span class="Constant">0</span>, <span class="Constant">3</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># no change to cursor</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    type <span class="Constant">[abc]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># type two letters at different places</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    type <span class="Constant">[d]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0adbc     .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">7</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># 4 for first letter, 3 for second</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">5</span>  <span class="Comment"># right of last line</span>
+    type <span class="Constant">[d]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">5</span>  <span class="Comment"># right of non-last line</span>
+    type <span class="Constant">[e]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abce      .</span>
+   <span class="Constant"> .d         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
+    type <span class="Constant">[d]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
+    type <span class="Constant">[e]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .de        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">5</span>  <span class="Comment"># below all text</span>
+    type <span class="Constant">[ef]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[01]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .01ab      .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># if the cursor reaches the right margin, wrap the line</span>
+
+<span class="muScenario">scenario</span> editor-wraps-line-on-insert [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># type a letter</span>
+  assume-console [
+    type <span class="Constant">[e]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># no wrap yet</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .eabc .</span>
+<span class="Constant">    .┈┈┈┈┈.</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  <span class="Comment"># type a second letter</span>
+  assume-console [
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># now wrap</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+<span class="Constant">    .efab↩.</span>
+   <span class="Constant"> .c    .</span>
+<span class="Constant">    .┈┈┈┈┈.</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-line-on-insert-2 [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdefg</span>
+<span class="Constant">defg]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># type more text at the start</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    type <span class="Constant">[abc]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor is not wrapped</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># but line is wrapped</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .efg       .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .efg       .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;insert-character-special-case&gt;</span> [
+  <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if we're at the column just before the wrap indicator</span>
+    wrap-column:number<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
+    at-wrap?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, wrap-column
+    <span class="muControl">break-unless</span> at-wrap?
+    *cursor-column<span class="Special"> &lt;- </span>subtract *cursor-column, wrap-column
+    *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, left
+    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
+    <span class="Comment"># if we're out of the screen, scroll down</span>
+    <span class="Delimiter">{</span>
+      below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height
+      <span class="muControl">break-unless</span> below-screen?
+<span class="Constant">      &lt;scroll-down&gt;</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">4</span>  <span class="Comment"># line is full; no wrap icon yet</span>
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .fe        .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>  <span class="Comment"># right before the wrap icon</span>
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcf↩     .</span>
+   <span class="Constant"> .de        .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-cursor-to-left-margin [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">2/left</span>, <span class="Constant">7/right</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">5</span>  <span class="Comment"># line is full; no wrap icon yet</span>
+    type <span class="Constant">[01]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  abc0↩   .</span>
+   <span class="Constant"> .  1de     .</span>
+   <span class="Constant"> .  ┈┈┈┈┈   .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="Comment"># if newline, move cursor to start of next line, and maybe align indent with previous line</span>
+
+<span class="muData">container</span> editor-data [
+  indent?:boolean
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;editor-initialization&gt;</span> [
+  indent?:address:boolean<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">indent?:offset</span>
+  *indent?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  assume-console [
+    type <span class="Constant">[0</span>
+<span class="Constant">1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0         .</span>
+   <span class="Constant"> .1abc      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> newline?
+<span class="Constant">    &lt;insert-enter-begin&gt;</span>
+    editor<span class="Special"> &lt;- </span>insert-new-line-and-indent editor, screen
+<span class="Constant">    &lt;insert-enter-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> insert-new-line-and-indent [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Comment"># insert newline</span>
+  insert-duplex <span class="Constant">10/newline</span>, *before-cursor
+  *before-cursor<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy left
+  <span class="Comment"># maybe scroll</span>
+  <span class="Delimiter">{</span>
+    below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal, never greater</span>
+    <span class="muControl">break-unless</span> below-screen?
+<span class="Constant">    &lt;scroll-down&gt;</span>
+    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># indent if necessary</span>
+  indent?:boolean<span class="Special"> &lt;- </span>get *editor, <span class="Constant">indent?:offset</span>
+  <span class="muControl">reply-unless</span> indent?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+  d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  end-of-previous-line:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
+  indent:number<span class="Special"> &lt;- </span>line-indent end-of-previous-line, d
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    indent-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, indent
+    <span class="muControl">break-if</span> indent-done?
+    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
+<span class="Comment"># the number of spaces at the start of the line containing 'curr'.</span>
+<span class="muRecipe">recipe</span> line-indent [
+  <span class="Constant">local-scope</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="muControl">reply-unless</span> curr, result
+  at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
+  <span class="muControl">reply-if</span> at-start?, result
+  <span class="Delimiter">{</span>
+    curr<span class="Special"> &lt;- </span>prev-duplex curr
+    <span class="muControl">break-unless</span> curr
+    at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
+    <span class="muControl">break-if</span> at-start?
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-newline?
+    <span class="Comment"># if c is a space, increment result</span>
+    is-space?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> is-space?
+      result<span class="Special"> &lt;- </span>add result, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if c is not a space, reset result</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> is-space?
+      result<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span>
+  assume-console [
+    type <span class="Constant">[0</span>
+<span class="Constant">1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> . 0        .</span>
+   <span class="Constant"> . 1abc     .</span>
+   <span class="Constant"> . ┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  assume-console [
+    press enter
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># line should be fully cleared</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-indent-after-newline [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">  cd</span>
+<span class="Constant">ef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># position cursor after 'cd' and hit 'newline'</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">8</span>
+    type [
+]
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor should be below start of previous line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column (indented)</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-skips-indent-around-paste [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">  cd</span>
+<span class="Constant">ef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># position cursor after 'cd' and hit 'newline' surrounded by paste markers</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">8</span>
+    press <span class="Constant">65507</span>  <span class="Comment"># start paste</span>
+    press enter
+    press <span class="Constant">65506</span>  <span class="Comment"># end paste</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor should be below start of previous line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># cursor row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># cursor column (not indented)</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    paste-start?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65507/paste-start</span>
+    <span class="muControl">break-unless</span> paste-start?
+    indent?:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent?:offset</span>
+    *indent?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    paste-end?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65506/paste-end</span>
+    <span class="muControl">break-unless</span> paste-end?
+    indent?:address:boolean<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">indent?:offset</span>
+    *indent?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="SalientComment">## helpers</span>
+
+<span class="muRecipe">recipe</span> draw-horizontal [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  x:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> style-found?
+    style<span class="Special"> &lt;- </span>copy <span class="Constant">9472/horizontal</span>
+  <span class="Delimiter">}</span>
+  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># default color to white</span>
+    <span class="muControl">break-if</span> color-found?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
+  <span class="Delimiter">}</span>
+  bg-color:number, bg-color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> bg-color-found?
+    bg-color<span class="Special"> &lt;- </span>copy <span class="Constant">0/black</span>
+  <span class="Delimiter">}</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, x
+  <span class="Delimiter">{</span>
+    continue?:boolean<span class="Special"> &lt;- </span>lesser-or-equal x, right  <span class="Comment"># right is inclusive, to match editor-data semantics</span>
+    <span class="muControl">break-unless</span> continue?
+    print-character screen, style, color, bg-color
+    x<span class="Special"> &lt;- </span>add x, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html
new file mode 100644
index 00000000..82273ba7
--- /dev/null
+++ b/html/edit/003-shortcuts.mu.html
@@ -0,0 +1,3107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/003-shortcuts.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## special shortcuts for manipulating the editor</span>
+<span class="Comment"># Some keys on the keyboard generate unicode characters, others generate</span>
+<span class="Comment"># terminfo key codes. We need to modify different places in the two cases.</span>
+
+<span class="Comment"># tab - insert two spaces</span>
+
+<span class="muScenario">scenario</span> editor-inserts-two-spaces-on-tab [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># just one character in final line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">cd]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  assume-console [
+    press tab
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab      .</span>
+   <span class="Constant"> .cd        .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    tab?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">9/tab</span>
+    <span class="muControl">break-unless</span> tab?
+<span class="Constant">    &lt;insert-character-begin&gt;</span>
+    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen
+    editor, screen, go-render?:boolean<span class="Special"> &lt;- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen
+<span class="Constant">    &lt;insert-character-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># backspace - delete character before cursor</span>
+
+<span class="muScenario">scenario</span> editor-handles-backspace-key [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    press backspace
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .bc        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of original line to overwrite</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    delete-previous-character?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">8/backspace</span>
+    <span class="muControl">break-unless</span> delete-previous-character?
+<span class="Constant">    &lt;backspace-character-begin&gt;</span>
+    editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list<span class="Special"> &lt;- </span>delete-before-cursor editor, screen
+<span class="Constant">    &lt;backspace-character-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># editor, screen, go-render?:boolean, backspaced-cell:address:duplex-list &lt;- delete-before-cursor editor:address:editor-data, screen</span>
+<span class="Comment"># return values:</span>
+<span class="Comment">#   go-render? - whether caller needs to update the screen</span>
+<span class="Comment">#   backspaced-cell - value deleted (or 0 if nothing was deleted) so we can save it for undo, etc.</span>
+<span class="muRecipe">recipe</span> delete-before-cursor [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  <span class="Comment"># if at start of text (before-cursor at § sentinel), return</span>
+  prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
+  <span class="muControl">reply-unless</span> prev, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span>
+  trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[delete-before-cursor]</span>
+  original-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
+  editor, scroll?:boolean<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor
+  backspaced-cell:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+  remove-duplex *before-cursor  <span class="Comment"># will also neatly trim next/prev pointers in backspaced-cell/*before-cursor</span>
+  *before-cursor<span class="Special"> &lt;- </span>copy prev
+  <span class="muControl">reply-if</span> scroll?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>, backspaced-cell
+  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
+  cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span>
+  <span class="Comment"># did we just backspace over a newline?</span>
+  same-row?:boolean<span class="Special"> &lt;- </span>equal cursor-row, original-row
+  <span class="muControl">reply-unless</span> same-row?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, backspaced-cell
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
+  curr-column:number<span class="Special"> &lt;- </span>copy cursor-column
+  <span class="Delimiter">{</span>
+    <span class="Comment"># hit right margin? give up and let caller render</span>
+    at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width
+    <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, backspaced-cell
+    <span class="muControl">break-unless</span> curr
+    <span class="Comment"># newline? done.</span>
+    currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-newline?
+    screen<span class="Special"> &lt;- </span>print-character screen, currc
+    curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># we're guaranteed not to be at the right margin</span>
+  screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, backspaced-cell
+]
+
+<span class="muRecipe">recipe</span> move-cursor-coordinates-left [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  <span class="Comment"># if not at left margin, move one character left</span>
+  <span class="Delimiter">{</span>
+    at-left-margin?:boolean<span class="Special"> &lt;- </span>equal *cursor-column, left
+    <span class="muControl">break-if</span> at-left-margin?
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[decrementing cursor column]</span>
+    *cursor-column<span class="Special"> &lt;- </span>subtract *cursor-column, <span class="Constant">1</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if at left margin, we must move to previous row:</span>
+  top-of-screen?:boolean<span class="Special"> &lt;- </span>equal *cursor-row, <span class="Constant">1</span>  <span class="Comment"># exclude menu bar</span>
+  go-render?:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> top-of-screen?
+    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> top-of-screen?
+<span class="Constant">    &lt;scroll-up&gt;</span>
+    go-render?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># case 1: if previous character was newline, figure out how long the previous line is</span>
+    previous-character:character<span class="Special"> &lt;- </span>get *before-cursor, <span class="Constant">value:offset</span>
+    previous-character-is-newline?:boolean<span class="Special"> &lt;- </span>equal previous-character, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> previous-character-is-newline?
+    <span class="Comment"># compute length of previous line</span>
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[switching to previous line]</span>
+    d:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+    end-of-line:number<span class="Special"> &lt;- </span>previous-line-length before-cursor, d
+    *cursor-column<span class="Special"> &lt;- </span>add left, end-of-line
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render?
+  <span class="Delimiter">}</span>
+  <span class="Comment"># case 2: if previous-character was not newline, we're just at a wrapped line</span>
+  trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[wrapping to previous line]</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>  <span class="Comment"># leave room for wrap icon</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, go-render?
+]
+
+<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
+<span class="Comment"># the length of the previous line before the 'curr' pointer.</span>
+<span class="muRecipe">recipe</span> previous-line-length [
+  <span class="Constant">local-scope</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="muControl">reply-unless</span> curr, result
+  at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
+  <span class="muControl">reply-if</span> at-start?, result
+  <span class="Delimiter">{</span>
+    curr<span class="Special"> &lt;- </span>prev-duplex curr
+    <span class="muControl">break-unless</span> curr
+    at-start?:boolean<span class="Special"> &lt;- </span>equal curr, start
+    <span class="muControl">break-if</span> at-start?
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-newline?
+    result<span class="Special"> &lt;- </span>add result, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># just one character in final line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">cd]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">0</span>  <span class="Comment"># cursor at only character in final line</span>
+    press backspace
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+]
+
+<span class="Comment"># delete - delete character at cursor</span>
+
+<span class="muScenario">scenario</span> editor-handles-delete-key [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    press delete
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .bc        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of original line to overwrite</span>
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    press delete
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># new length to overwrite</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    delete-next-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65522/delete</span>
+    <span class="muControl">break-unless</span> delete-next-character?
+<span class="Constant">    &lt;delete-character-begin&gt;</span>
+    editor, screen, go-render?:boolean, deleted-cell:address:duplex-list<span class="Special"> &lt;- </span>delete-at-cursor editor, screen
+<span class="Constant">    &lt;delete-character-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> delete-at-cursor [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  candidate:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  <span class="muControl">reply-unless</span> candidate, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, <span class="Constant">0/nothing-deleted</span>
+  currc:character<span class="Special"> &lt;- </span>get *candidate, <span class="Constant">value:offset</span>
+  remove-duplex candidate
+  deleted-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+  <span class="muControl">reply-if</span> deleted-newline?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, candidate/deleted-cell
+  <span class="Comment"># wasn't a newline? render rest of line</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor  <span class="Comment"># refresh after remove-duplex above</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
+  curr-column:number<span class="Special"> &lt;- </span>copy *cursor-column
+  screen-width:number<span class="Special"> &lt;- </span>screen-width screen
+  <span class="Delimiter">{</span>
+    <span class="Comment"># hit right margin? give up and let caller render</span>
+    at-right?:boolean<span class="Special"> &lt;- </span>greater-or-equal curr-column, screen-width
+    <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>, candidate/deleted-cell
+    <span class="muControl">break-unless</span> curr
+    <span class="Comment"># newline? done.</span>
+    currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-newline?
+    screen<span class="Special"> &lt;- </span>print-character screen, currc
+    curr-column<span class="Special"> &lt;- </span>add curr-column, <span class="Constant">1</span>
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># we're guaranteed not to be at the right margin</span>
+  screen<span class="Special"> &lt;- </span>print-character screen, <span class="Constant">32/space</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>, candidate/deleted-cell
+]
+
+<span class="Comment"># right arrow</span>
+
+<span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    press right-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a0bc      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># 0 and following characters</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-next-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65514/right-arrow</span>
+    <span class="muControl">break-unless</span> move-to-next-character?
+    <span class="Comment"># if not at end of text</span>
+    next-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    <span class="muControl">break-unless</span> next-cursor
+    <span class="Comment"># scan to next character</span>
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    *before-cursor<span class="Special"> &lt;- </span>copy next-cursor
+    editor, go-render?:boolean<span class="Special"> &lt;- </span>move-cursor-coordinates-right editor, screen-height
+    screen<span class="Special"> &lt;- </span>move-cursor screen, *cursor-row, *cursor-column
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">2/right-arrow</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-cursor-coordinates-right [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:duplex-list<span class="Special"> &lt;- </span>get *editor <span class="Constant">before-cursor:offset</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  <span class="Comment"># if crossed a newline, move cursor to start of next row</span>
+  <span class="Delimiter">{</span>
+    old-cursor-character:character<span class="Special"> &lt;- </span>get *before-cursor, <span class="Constant">value:offset</span>
+    was-at-newline?:boolean<span class="Special"> &lt;- </span>equal old-cursor-character, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> was-at-newline?
+    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
+    *cursor-column<span class="Special"> &lt;- </span>copy left
+    below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal</span>
+    <span class="muControl">reply-unless</span> below-screen?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+<span class="Constant">    &lt;scroll-down&gt;</span>
+    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if the line wraps, move cursor to start of next row</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if we're at the column just before the wrap indicator</span>
+    wrap-column:number<span class="Special"> &lt;- </span>subtract right, <span class="Constant">1</span>
+    at-wrap?:boolean<span class="Special"> &lt;- </span>equal *cursor-column, wrap-column
+    <span class="muControl">break-unless</span> at-wrap?
+    <span class="Comment"># and if next character isn't newline</span>
+    next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex before-cursor
+    <span class="muControl">break-unless</span> next
+    next-character:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal next-character, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> newline?
+    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
+    *cursor-column<span class="Special"> &lt;- </span>copy left
+    below-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, screen-height  <span class="Comment"># must be equal</span>
+    <span class="muControl">reply-unless</span> below-screen?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+<span class="Constant">    &lt;scroll-down&gt;</span>
+    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>  <span class="Comment"># bring back into screen range</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise move cursor one character right</span>
+  *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># type right-arrow a few times to get to start of second line</span>
+  assume-console [
+    press right-arrow
+    press right-arrow
+    press right-arrow
+    press right-arrow  <span class="Comment"># next line</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  <span class="Comment"># type something and ensure it goes where it should</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0d        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># new length of second line</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    press right-arrow
+    press right-arrow
+    press right-arrow
+    press right-arrow  <span class="Comment"># next line</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> . abc      .</span>
+   <span class="Constant"> . 0d       .</span>
+   <span class="Constant"> . ┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># line just barely wrapping</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># position cursor at last character before wrap and hit right-arrow</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># now hit right arrow again</span>
+  assume-console [
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">6/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">4</span>
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> . abcd↩    .</span>
+   <span class="Constant"> . ef       .</span>
+   <span class="Constant"> . ┈┈┈┈┈    .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># move to end of line, press right-arrow, type a character</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press right-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># new character should be in next line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0d        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="Comment"># todo: ctrl-right: next word-end</span>
+
+<span class="Comment"># left arrow</span>
+
+<span class="muScenario">scenario</span> editor-moves-cursor-left-with-key [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    press left-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a0bc      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-previous-character?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65515/left-arrow</span>
+    <span class="muControl">break-unless</span> move-to-previous-character?
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[left arrow]</span>
+    <span class="Comment"># if not at start of text (before-cursor at § sentinel)</span>
+    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex *before-cursor
+    <span class="muControl">reply-unless</span> prev, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    editor, go-render?<span class="Special"> &lt;- </span>move-cursor-coordinates-left editor
+    *before-cursor<span class="Special"> &lt;- </span>copy prev
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">1/left-arrow</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize editor with two lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># position cursor at start of second line (so there's no previous newline)</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
+    press left-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize editor with three lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">g]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># position cursor further down (so there's a newline before the character at</span>
+  <span class="Comment"># the cursor)</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press left-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def0      .</span>
+   <span class="Constant"> .g         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># just the '0'</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">g]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># position cursor at start of text, press left-arrow, then type a character</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">0</span>
+    press left-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># left-arrow should have had no effect</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0abc      .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .g         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  check-trace-count-for-label <span class="Constant">4</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># length of first line</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize editor with text containing an empty line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+
+d]
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># position cursor right after empty line</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press left-arrow
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0         .</span>
+   <span class="Constant"> .d         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># just the '0'</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-across-screen-lines-across-wrap-with-left-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize editor with text containing an empty line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># position cursor right after empty line</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
+    press left-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>  <span class="Comment"># previous row</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>  <span class="Comment"># end of wrapped line</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="Comment"># todo: ctrl-left: previous word-start</span>
+
+<span class="Comment"># up arrow</span>
+
+<span class="muScenario">scenario</span> editor-moves-to-previous-line-with-up-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a0bc      .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-previous-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65517/up-arrow</span>
+    <span class="muControl">break-unless</span> move-to-previous-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    editor, go-render?<span class="Special"> &lt;- </span>move-to-previous-line editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">3/up-arrow</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-to-previous-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  already-at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal *cursor-row, <span class="Constant">1/top</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if cursor not at top, move it</span>
+    <span class="muControl">break-if</span> already-at-top?
+    <span class="Comment"># if not at newline, move to start of line (previous newline)</span>
+    <span class="Comment"># then scan back another line</span>
+    <span class="Comment"># if either step fails, give up without modifying cursor or coordinates</span>
+    curr:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+    <span class="Delimiter">{</span>
+      old:address:duplex-list<span class="Special"> &lt;- </span>copy curr
+      c2:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+      at-newline?:boolean<span class="Special"> &lt;- </span>equal c2, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> at-newline?
+      curr:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line curr, editor
+      no-motion?:boolean<span class="Special"> &lt;- </span>equal curr, old
+      <span class="muControl">reply-if</span> no-motion?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      old<span class="Special"> &lt;- </span>copy curr
+      curr<span class="Special"> &lt;- </span>before-previous-line curr, editor
+      no-motion?:boolean<span class="Special"> &lt;- </span>equal curr, old
+      <span class="muControl">reply-if</span> no-motion?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+    <span class="Delimiter">}</span>
+    *before-cursor<span class="Special"> &lt;- </span>copy curr
+    *cursor-row<span class="Special"> &lt;- </span>subtract *cursor-row, <span class="Constant">1</span>
+    <span class="Comment"># scan ahead to right column or until end of line</span>
+    target-column:number<span class="Special"> &lt;- </span>copy *cursor-column
+    *cursor-column<span class="Special"> &lt;- </span>copy left
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column
+      <span class="muControl">break-if</span> done?
+      curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+      <span class="muControl">break-unless</span> curr
+      currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+      at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> at-newline?
+      <span class="Comment">#</span>
+      *before-cursor<span class="Special"> &lt;- </span>copy curr
+      *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if cursor already at top, scroll up</span>
+    <span class="muControl">break-unless</span> already-at-top?
+<span class="Constant">    &lt;scroll-up&gt;</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-adjusts-column-at-previous-line [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .ab0       .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-adjusts-column-at-empty-line [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [
+def]
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0         .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-previous-line-from-left-margin [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># start out with three lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># click on the third line and hit up-arrow, so you end up just after a newline</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0def      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="Comment"># down arrow</span>
+
+<span class="muScenario">scenario</span> editor-moves-to-next-line-with-down-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># cursor starts out at (1, 0)</span>
+  assume-console [
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># ..and ends at (2, 0)</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0def      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-next-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65516/down-arrow</span>
+    <span class="muControl">break-unless</span> move-to-next-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    editor, go-render?<span class="Special"> &lt;- </span>move-to-next-line editor, screen-height
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">4/down-arrow</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render?
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-to-next-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-row:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  last-line:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1</span>
+  already-at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-row, last-line
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if cursor not at bottom, move it</span>
+    <span class="muControl">break-if</span> already-at-bottom?
+    <span class="Comment"># scan to start of next line, then to right column or until end of line</span>
+    max:number<span class="Special"> &lt;- </span>subtract right, left
+    next-line:address:duplex-list<span class="Special"> &lt;- </span>before-start-of-next-line *before-cursor, max
+    <span class="Delimiter">{</span>
+      <span class="Comment"># already at end of buffer? try to scroll up (so we can see more</span>
+      <span class="Comment"># warnings or sandboxes below)</span>
+      no-motion?:boolean<span class="Special"> &lt;- </span>equal next-line, *before-cursor
+      <span class="muControl">break-unless</span> no-motion?
+      scroll?:boolean<span class="Special"> &lt;- </span>greater-than *cursor-row, <span class="Constant">1</span>
+      <span class="muControl">break-if</span> scroll?, <span class="Constant">+try-to-scroll:label</span>
+      <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+    <span class="Delimiter">}</span>
+    *cursor-row<span class="Special"> &lt;- </span>add *cursor-row, <span class="Constant">1</span>
+    *before-cursor<span class="Special"> &lt;- </span>copy next-line
+    target-column:number<span class="Special"> &lt;- </span>copy *cursor-column
+    *cursor-column<span class="Special"> &lt;- </span>copy left
+    <span class="Delimiter">{</span>
+      done?:boolean<span class="Special"> &lt;- </span>greater-or-equal *cursor-column, target-column
+      <span class="muControl">break-if</span> done?
+      curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+      <span class="muControl">break-unless</span> curr
+      currc:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+      at-newline?:boolean<span class="Special"> &lt;- </span>equal currc, <span class="Constant">10/newline</span>
+      <span class="muControl">break-if</span> at-newline?
+      <span class="Comment">#</span>
+      *before-cursor<span class="Special"> &lt;- </span>copy curr
+      *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+<span class="Constant">  +try-to-scroll</span>
+<span class="Constant">  &lt;scroll-down&gt;</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">1/go-render</span>
+]
+
+<span class="muScenario">scenario</span> editor-adjusts-column-at-next-line [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">de]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .de0       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-at-end-on-down-arrow [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">de]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># try to move down past end of text</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen should scroll, moving cursor to end of text</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .de0       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># try to move down again</span>
+<span class="Constant">  $clear-trace</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen stops scrolling because cursor is already at top</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .de01      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># ctrl-a/home - move cursor to start of line</span>
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on second line, press ctrl-a</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press ctrl-a
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-start-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">1/ctrl-a</span>
+    <span class="muControl">break-unless</span> move-to-start-of-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    move-to-start-of-line editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-start-of-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65521/home</span>
+    <span class="muControl">break-unless</span> move-to-start-of-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    move-to-start-of-line editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-to-start-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># update cursor column</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy left
+  <span class="Comment"># update before-cursor</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  <span class="Comment"># while not at start of line, move </span>
+  <span class="Delimiter">{</span>
+    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal *before-cursor, init
+    <span class="muControl">break-if</span> at-start-of-text?
+    prev:character<span class="Special"> &lt;- </span>get **before-cursor, <span class="Constant">value:offset</span>
+    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal prev, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-start-of-line?
+    *before-cursor<span class="Special"> &lt;- </span>prev-duplex *before-cursor
+    assert *before-cursor, <span class="Constant">[move-to-start-of-line tried to move before start of text]</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-ctrl-a-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on first line (no newline before), press ctrl-a</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press ctrl-a
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on second line, press 'home'</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press home
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-start-of-line-with-home-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on first line (no newline before), press 'home'</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press home
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to start of line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="Comment"># ctrl-e/end - move cursor to end of line</span>
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on first line, press ctrl-e</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    press ctrl-e
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+  <span class="Comment"># editor inserts future characters at cursor</span>
+  assume-console [
+    type <span class="Constant">[z]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">4</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123z      .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-end-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">5/ctrl-e</span>
+    <span class="muControl">break-unless</span> move-to-end-of-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    move-to-end-of-line editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    move-to-end-of-line?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65520/end</span>
+    <span class="muControl">break-unless</span> move-to-end-of-line?
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    move-to-end-of-line editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> move-to-end-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  <span class="Comment"># while not at start of line, move </span>
+  <span class="Delimiter">{</span>
+    next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    <span class="muControl">break-unless</span> next  <span class="Comment"># end of text</span>
+    nextc:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span>
+    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal nextc, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-end-of-line?
+    *before-cursor<span class="Special"> &lt;- </span>copy next
+    *cursor-column<span class="Special"> &lt;- </span>add *cursor-column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-ctrl-e-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on second line (no newline after), press ctrl-e</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press ctrl-e
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on first line, press 'end'</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    press end
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-end-of-line-with-end-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+<span class="Constant">  $clear-trace</span>
+  <span class="Comment"># start on second line (no newline after), press 'end'</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press end
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to end of line</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span>
+]
+
+<span class="Comment"># ctrl-u - delete text from start of line until (but not at) cursor</span>
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start on second line, press ctrl-u</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">2</span>
+    press ctrl-u
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .6         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    delete-to-start-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">21/ctrl-u</span>
+    <span class="muControl">break-unless</span> delete-to-start-of-line?
+<span class="Constant">    &lt;delete-to-start-of-line-begin&gt;</span>
+    deleted-cells:address:duplex-list<span class="Special"> &lt;- </span>delete-to-start-of-line editor
+<span class="Constant">    &lt;delete-to-start-of-line-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> delete-to-start-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># compute range to delete</span>
+  init:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  <span class="Delimiter">{</span>
+    at-start-of-text?:boolean<span class="Special"> &lt;- </span>equal start, init
+    <span class="muControl">break-if</span> at-start-of-text?
+    curr:character<span class="Special"> &lt;- </span>get *start, <span class="Constant">value:offset</span>
+    at-start-of-line?:boolean<span class="Special"> &lt;- </span>equal curr, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-start-of-line?
+    start<span class="Special"> &lt;- </span>prev-duplex start
+    assert start, <span class="Constant">[delete-to-start-of-line tried to move before start of text]</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># snip it out</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start
+  remove-duplex-between start, end
+  <span class="Comment"># adjust cursor</span>
+  *before-cursor<span class="Special"> &lt;- </span>prev-duplex end
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">cursor-column:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy left
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start on first line (no newline before), press ctrl-u</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    press ctrl-u
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .3         .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-line-with-ctrl-u-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start past end of line, press ctrl-u</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press ctrl-u
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-start-of-final-line-with-ctrl-u [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start past end of final line, press ctrl-u</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press ctrl-u
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to start of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># ctrl-k - delete text from cursor to end of line (but not the newline)</span>
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start on first line, press ctrl-k</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .1         .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    delete-to-end-of-line?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">11/ctrl-k</span>
+    <span class="muControl">break-unless</span> delete-to-end-of-line?
+<span class="Constant">    &lt;delete-to-end-of-line-begin&gt;</span>
+    deleted-cells:address:duplex-list<span class="Special"> &lt;- </span>delete-to-end-of-line editor
+<span class="Constant">    &lt;delete-to-end-of-line-end&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> delete-to-end-of-line [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># compute range to delete</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span>
+  end:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start
+  <span class="Delimiter">{</span>
+    at-end-of-text?:boolean<span class="Special"> &lt;- </span>equal end, <span class="Constant">0/null</span>
+    <span class="muControl">break-if</span> at-end-of-text?
+    curr:character<span class="Special"> &lt;- </span>get *end, <span class="Constant">value:offset</span>
+    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal curr, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-end-of-line?
+    end<span class="Special"> &lt;- </span>next-duplex end
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># snip it out</span>
+  result:address:duplex-list<span class="Special"> &lt;- </span>next-duplex start
+  remove-duplex-between start, end
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-2 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start on second line (no newline after), press ctrl-k</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes to end of line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .4         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-3 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start at end of line</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes just last character</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .12        .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-4 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start past end of line</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">3</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes nothing</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-5 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start at end of text</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">2</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes just the final character</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .45        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-deletes-to-end-of-line-with-ctrl-k-6 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[123</span>
+<span class="Constant">456]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  <span class="Comment"># start past end of text</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">3</span>
+    press ctrl-k
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># cursor deletes nothing</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .123       .</span>
+   <span class="Constant"> .456       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># cursor-down can scroll if necessary</span>
+
+<span class="muScenario">scenario</span> editor-can-scroll-down-using-arrow-keys [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with &gt;3 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># position cursor at last line, then try to move further down</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen slides by one line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;scroll-down&gt;</span> [
+  trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll down]</span>
+  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  max:number<span class="Special"> &lt;- </span>subtract right, left
+  old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+  *top-of-screen<span class="Special"> &lt;- </span>before-start-of-next-line *top-of-screen, max
+  no-movement?:boolean<span class="Special"> &lt;- </span>equal old-top, *top-of-screen
+  <span class="Comment"># Hack: this reply doesn't match one of the locations of &lt;scroll-down&gt;,</span>
+  <span class="Comment"># directly within insert-at-cursor. However, I'm unable to trigger the</span>
+  <span class="Comment"># error.. If necessary create a duplicate copy of &lt;scroll-down&gt; with the</span>
+  <span class="Comment"># right 'reply-if'.</span>
+  <span class="muControl">reply-if</span> no-movement?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+]
+
+<span class="Comment"># takes a pointer into the doubly-linked list, scans ahead at most 'max'</span>
+<span class="Comment"># positions until the next newline</span>
+<span class="Comment"># beware: never return null pointer.</span>
+<span class="muRecipe">recipe</span> before-start-of-next-line [
+  <span class="Constant">local-scope</span>
+  original:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  max:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>copy original
+  <span class="Comment"># skip the initial newline if it exists</span>
+  <span class="Delimiter">{</span>
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> at-newline?
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">reply-unless</span> curr, original
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
+    <span class="muControl">break-if</span> done?
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+    <span class="muControl">break-if</span> at-newline?
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply-unless</span> curr, original
+  <span class="muControl">reply</span> curr
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-past-wrapped-line-using-arrow-keys [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
+  <span class="Comment"># other lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
+<span class="Constant">g</span>
+<span class="Constant">h</span>
+<span class="Constant">i]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .g         .</span>
+  ]
+  <span class="Comment"># position cursor at last line, then try to move further down</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .h         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-past-wrapped-line-using-arrow-keys-2 [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor starts with a long line wrapping twice</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdefghij</span>
+<span class="Constant">k</span>
+<span class="Constant">l</span>
+<span class="Constant">m]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at last line, then try to move further down</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line containing a wrap icon</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .efgh↩     .</span>
+   <span class="Constant"> .ij        .</span>
+   <span class="Constant"> .k         .</span>
+  ]
+  <span class="Comment"># scroll down again</span>
+  assume-console [
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .ij        .</span>
+   <span class="Constant"> .k         .</span>
+   <span class="Constant"> .l         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-when-line-wraps [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a long line in the third line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">cdef]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at end, type a character</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">4</span>
+    type <span class="Constant">[g]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+<span class="Constant">    .cdef↩.</span>
+   <span class="Constant"> .g    .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-on-newline [
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># position cursor after last line and type newline</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">4</span>
+    type [
+]
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+   <span class="Constant"> .c    .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-on-right-arrow [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a wrapped line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">cdefgh]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at end of screen and try to move right</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">3</span>
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+<span class="Constant">    .cdef↩.</span>
+   <span class="Constant"> .gh   .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-down-on-right-arrow-2 [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains more lines than can fit on screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at end of screen and try to move right</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">3</span>
+    press right-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+   <span class="Constant"> .c    .</span>
+   <span class="Constant"> .d    .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-combines-page-and-line-scroll [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with a few pages of lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f</span>
+<span class="Constant">g]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># scroll down one page and one line</span>
+  assume-console [
+    press page-down
+    left-click <span class="Constant">3</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen scrolls down 3 lines</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .f         .</span>
+  ]
+]
+
+<span class="Comment"># cursor-up can scroll if necessary</span>
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-using-arrow-keys [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with &gt;3 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># position cursor at top of second page, then try to move up</span>
+  assume-console [
+    press page-down
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen slides by one line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;scroll-up&gt;</span> [
+  trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[scroll up]</span>
+  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+  old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+  *top-of-screen<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor
+  no-movement?:boolean<span class="Special"> &lt;- </span>equal old-top, *top-of-screen
+  <span class="muControl">reply-if</span> no-movement?, editor/same-as-ingredient:<span class="Constant">0</span>, <span class="Constant">0/no-more-render</span>
+]
+
+<span class="Comment"># takes a pointer into the doubly-linked list, scans back to before start of</span>
+<span class="Comment"># previous *wrapped* line</span>
+<span class="Comment"># beware: never return null pointer</span>
+<span class="muRecipe">recipe</span> before-previous-line [
+  <span class="Constant">local-scope</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+  <span class="Comment"># compute max, number of characters to skip</span>
+  <span class="Comment">#   1 + len%(width-1)</span>
+  <span class="Comment">#   except rotate second term to vary from 1 to width-1 rather than 0 to width-2</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">right:offset</span>
+  max-line-length:number<span class="Special"> &lt;- </span>subtract right, left, <span class="Constant">-1/exclusive-right</span>, <span class="Constant">1/wrap-icon</span>
+  sentinel:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  len:number<span class="Special"> &lt;- </span>previous-line-length curr, sentinel
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> len
+    <span class="Comment"># empty line; just skip this newline</span>
+    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr
+    <span class="muControl">reply-unless</span> prev, curr
+    <span class="muControl">reply</span> prev
+  <span class="Delimiter">}</span>
+  _, max:number<span class="Special"> &lt;- </span>divide-with-remainder len, max-line-length
+  <span class="Comment"># remainder 0 =&gt; scan one width-worth</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> max
+    max<span class="Special"> &lt;- </span>copy max-line-length
+  <span class="Delimiter">}</span>
+  max<span class="Special"> &lt;- </span>add max, <span class="Constant">1</span>
+  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Comment"># skip 'max' characters</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
+    <span class="muControl">break-if</span> done?
+    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr
+    <span class="muControl">break-unless</span> prev
+    curr<span class="Special"> &lt;- </span>copy prev
+    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> curr
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
+  <span class="Comment"># other lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
+<span class="Constant">g</span>
+<span class="Constant">h</span>
+<span class="Constant">i]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .g         .</span>
+  ]
+  <span class="Comment"># position cursor at top of second page, just below wrapped line</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .h         .</span>
+   <span class="Constant"> .i         .</span>
+  ]
+  <span class="Comment"># now move up one line</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .h         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-2 [
+  <span class="Comment"># screen has 1 line for menu + 4 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># editor starts with a long line wrapping twice, occupying 3 of the 4 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdefghij</span>
+<span class="Constant">k</span>
+<span class="Constant">l</span>
+<span class="Constant">m]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at top of second page</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .k         .</span>
+   <span class="Constant"> .l         .</span>
+   <span class="Constant"> .m         .</span>
+   <span class="Constant"> .┈┈┈┈┈     .</span>
+  ]
+  <span class="Comment"># move up one line</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .ij        .</span>
+   <span class="Constant"> .k         .</span>
+   <span class="Constant"> .l         .</span>
+   <span class="Constant"> .m         .</span>
+  ]
+  <span class="Comment"># move up a second line</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .efgh↩     .</span>
+   <span class="Constant"> .ij        .</span>
+   <span class="Constant"> .k         .</span>
+   <span class="Constant"> .l         .</span>
+  ]
+  <span class="Comment"># move up a third line</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .efgh↩     .</span>
+   <span class="Constant"> .ij        .</span>
+   <span class="Constant"> .k         .</span>
+  ]
+]
+
+<span class="Comment"># same as editor-scrolls-up-past-wrapped-line-using-arrow-keys but length</span>
+<span class="Comment"># slightly off, just to prevent over-training</span>
+<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-3 [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with a long, wrapped line and more than a screen of</span>
+  <span class="Comment"># other lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
+<span class="Constant">g</span>
+<span class="Constant">h</span>
+<span class="Constant">i]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcde↩    .</span>
+   <span class="Constant"> .f         .</span>
+   <span class="Constant"> .g         .</span>
+  ]
+  <span class="Comment"># position cursor at top of second page, just below wrapped line</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .h         .</span>
+   <span class="Constant"> .i         .</span>
+  ]
+  <span class="Comment"># now move up one line</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows partial wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .f         .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .h         .</span>
+  ]
+]
+
+<span class="Comment"># check empty lines</span>
+<span class="muScenario">scenario</span> editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with some lines around an empty line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+
+c
+d
+e]
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">6/right</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .┈┈┈┈┈┈    .</span>
+  ]
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-scrolls-up-on-left-arrow [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains &gt;3 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at top of second page</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .c    .</span>
+   <span class="Constant"> .d    .</span>
+   <span class="Constant"> .e    .</span>
+  ]
+  <span class="Comment"># now try to move left</span>
+  assume-console [
+    press left-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+   <span class="Constant"> .c    .</span>
+   <span class="Constant"> .d    .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-to-start-of-file [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with &gt;3 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># position cursor at top of second page, then try to move up to start of</span>
+  <span class="Comment"># text</span>
+  assume-console [
+    press page-down
+    press up-arrow
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen slides by one line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># try to move up again</span>
+  assume-console [
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen remains unchanged</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+]
+
+<span class="Comment"># ctrl-f/page-down - render next page if it exists</span>
+
+<span class="muScenario">scenario</span> editor-can-scroll [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows next page</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    page-down?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">6/ctrl-f</span>
+    <span class="muControl">break-unless</span> page-down?
+    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+    old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    page-down editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top
+    <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    page-down?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65518/page-down</span>
+    <span class="muControl">break-unless</span> page-down?
+    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+    old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    page-down editor
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top
+    <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># page-down skips entire wrapped lines, so it can't scroll past lines</span>
+<span class="Comment"># taking up the entire screen</span>
+<span class="muRecipe">recipe</span> page-down [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if editor contents don't overflow screen, do nothing</span>
+  bottom-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">bottom-of-screen:offset</span>
+  <span class="muControl">reply-unless</span> bottom-of-screen, editor/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Comment"># if not, position cursor at final character</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">before-cursor:offset</span>
+  *before-cursor<span class="Special"> &lt;- </span>prev-duplex bottom-of-screen
+  <span class="Comment"># keep one line in common with previous page</span>
+  <span class="Delimiter">{</span>
+    last:character<span class="Special"> &lt;- </span>get **before-cursor, <span class="Constant">value:offset</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal last, <span class="Constant">10/newline</span>
+    <span class="muControl">break-unless</span> newline?:boolean
+    *before-cursor<span class="Special"> &lt;- </span>prev-duplex *before-cursor
+  <span class="Delimiter">}</span>
+  <span class="Comment"># move cursor and top-of-screen to start of that line</span>
+  move-to-start-of-line editor
+  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+  *top-of-screen<span class="Special"> &lt;- </span>copy *before-cursor
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muScenario">scenario</span> editor-does-not-scroll-past-end [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen remains unmodified</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-starts-next-page-at-start-of-wrapped-line [
+  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a long last line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">cdefgh]</span>
+  <span class="Comment"># editor screen triggers wrap of last line</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  <span class="Comment"># some part of last line is not displayed</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .cde↩      .</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows entire wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .cde↩      .</span>
+   <span class="Constant"> .fgh       .</span>
+   <span class="Constant"> .┈┈┈┈      .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-starts-next-page-at-start-of-wrapped-line-2 [
+  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span>
+  <span class="Comment"># and still has something left over</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">bcdefgh]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  <span class="Comment"># some part of last line is not displayed</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .bcd↩      .</span>
+   <span class="Constant"> .efg↩      .</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows entire wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .bcd↩      .</span>
+   <span class="Constant"> .efg↩      .</span>
+   <span class="Constant"> .h         .</span>
+  ]
+]
+
+<span class="Comment"># ctrl-b/page-up - render previous page if it exists</span>
+
+<span class="muScenario">scenario</span> editor-can-scroll-up [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows next page</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  <span class="Comment"># scroll back up</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows original page again</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    page-up?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">2/ctrl-b</span>
+    <span class="muControl">break-unless</span> page-up?
+    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+    old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    editor<span class="Special"> &lt;- </span>page-up editor, screen-height
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top
+    <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
+  <span class="Delimiter">{</span>
+    page-up?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65519/page-up</span>
+    <span class="muControl">break-unless</span> page-up?
+    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+    old-top:address:duplex-list<span class="Special"> &lt;- </span>copy *top-of-screen
+<span class="Constant">    &lt;move-cursor-begin&gt;</span>
+    editor<span class="Special"> &lt;- </span>page-up editor, screen-height
+    undo-coalesce-tag:number<span class="Special"> &lt;- </span>copy <span class="Constant">0/never</span>
+<span class="Constant">    &lt;move-cursor-end&gt;</span>
+    no-movement?:boolean<span class="Special"> &lt;- </span>equal *top-of-screen, old-top
+    <span class="Comment"># don't bother re-rendering if nothing changed. todo: test this</span>
+    <span class="muControl">reply-if</span> no-movement?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> page-up [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen-height:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  max:number<span class="Special"> &lt;- </span>subtract screen-height, <span class="Constant">1/menu-bar</span>, <span class="Constant">1/overlapping-line</span>
+  count:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal count, max
+    <span class="muControl">break-if</span> done?
+    prev:address:duplex-list<span class="Special"> &lt;- </span>before-previous-line *top-of-screen, editor
+    <span class="muControl">break-unless</span> prev
+    *top-of-screen<span class="Special"> &lt;- </span>copy prev
+    count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-multiple-pages [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># initialize editor with 8 lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f</span>
+<span class="Constant">g</span>
+<span class="Constant">h]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+  <span class="Comment"># scroll down two pages</span>
+  assume-console [
+    press page-down
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows third page</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .f         .</span>
+   <span class="Constant"> .g         .</span>
+  ]
+  <span class="Comment"># scroll up</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows second page</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .e         .</span>
+  ]
+  <span class="Comment"># scroll up again</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows original page again</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-wrapped-lines [
+  <span class="Comment"># screen has 1 line for menu + 5 lines for text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">6/height</span>
+  <span class="Comment"># editor contains a long line in the first page</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">cdefgh</span>
+<span class="Constant">i</span>
+<span class="Constant">j</span>
+<span class="Constant">k</span>
+<span class="Constant">l</span>
+<span class="Constant">m</span>
+<span class="Constant">n</span>
+<span class="Constant">o]</span>
+  <span class="Comment"># editor screen triggers wrap of last line</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  <span class="Comment"># some part of last line is not displayed</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .cde↩      .</span>
+   <span class="Constant"> .fgh       .</span>
+   <span class="Constant"> .i         .</span>
+  ]
+  <span class="Comment"># scroll down a page and a line</span>
+  assume-console [
+    press page-down
+    left-click <span class="Constant">5</span>, <span class="Constant">0</span>
+    press down-arrow
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows entire wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .j         .</span>
+   <span class="Constant"> .k         .</span>
+   <span class="Constant"> .l         .</span>
+   <span class="Constant"> .m         .</span>
+   <span class="Constant"> .n         .</span>
+  ]
+  <span class="Comment"># now scroll up one page</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen resets</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .cde↩      .</span>
+   <span class="Constant"> .fgh       .</span>
+   <span class="Constant"> .i         .</span>
+   <span class="Constant"> .j         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-wrapped-lines-2 [
+  <span class="Comment"># screen has 1 line for menu + 3 lines for text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a very long line that occupies last two lines of screen</span>
+  <span class="Comment"># and still has something left over</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">bcdefgh]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  <span class="Comment"># some part of last line is not displayed</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .bcd↩      .</span>
+   <span class="Constant"> .efg↩      .</span>
+  ]
+  <span class="Comment"># scroll down</span>
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen shows entire wrapped line</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .bcd↩      .</span>
+   <span class="Constant"> .efg↩      .</span>
+   <span class="Constant"> .h         .</span>
+  ]
+  <span class="Comment"># scroll back up</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># screen resets</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .bcd↩      .</span>
+   <span class="Constant"> .efg↩      .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-past-nonempty-lines [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># text with empty line in second screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[axx</span>
+<span class="Constant">bxx</span>
+<span class="Constant">cxx</span>
+<span class="Constant">dxx</span>
+<span class="Constant">exx</span>
+<span class="Constant">fxx</span>
+<span class="Constant">gxx</span>
+<span class="Constant">hxx</span>
+<span class="Constant">]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .axx       .</span>
+   <span class="Constant"> .bxx       .</span>
+   <span class="Constant"> .cxx       .</span>
+  ]
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .cxx       .</span>
+   <span class="Constant"> .dxx       .</span>
+   <span class="Constant"> .exx       .</span>
+  ]
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .exx       .</span>
+   <span class="Constant"> .fxx       .</span>
+   <span class="Constant"> .gxx       .</span>
+  ]
+  <span class="Comment"># scroll back up past empty line</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .cxx       .</span>
+   <span class="Constant"> .dxx       .</span>
+   <span class="Constant"> .exx       .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-scroll-up-past-empty-lines [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># text with empty line in second screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[axy</span>
+<span class="Constant">bxy</span>
+<span class="Constant">cxy</span>
+
+dxy
+exy
+fxy
+gxy
+]
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">4/right</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .axy       .</span>
+   <span class="Constant"> .bxy       .</span>
+   <span class="Constant"> .cxy       .</span>
+  ]
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .cxy       .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .dxy       .</span>
+  ]
+  assume-console [
+    press page-down
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .dxy       .</span>
+   <span class="Constant"> .exy       .</span>
+   <span class="Constant"> .fxy       .</span>
+  ]
+  <span class="Comment"># scroll back up past empty line</span>
+  assume-console [
+    press page-up
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .cxy       .</span>
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .dxy       .</span>
+  ]
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html
new file mode 100644
index 00000000..406c19a9
--- /dev/null
+++ b/html/edit/004-programming-environment.mu.html
@@ -0,0 +1,826 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/004-programming-environment.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muScenario { color: #00af00; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.CommentedCode { color: #6c6c6c; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## putting the environment together out of editors</span>
+<span class="Comment">#</span>
+<span class="Comment"># Consists of one editor on the left for recipes and one on the right for the</span>
+<span class="Comment"># sandbox.</span>
+
+<span class="muRecipe">recipe!</span> main [
+  <span class="Constant">local-scope</span>
+  open-console
+  initial-recipe:address:array:character<span class="Special"> &lt;- </span>restore <span class="Constant">[recipes.mu]</span>
+  initial-sandbox:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  hide-screen <span class="Constant">0/screen</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox
+  env<span class="Special"> &lt;- </span>restore-sandboxes env
+  render-all <span class="Constant">0/screen</span>, env
+  event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env
+  <span class="Comment"># never gets here</span>
+]
+
+<span class="muData">container</span> programming-environment-data [
+  recipes:address:editor-data
+  current-sandbox:address:editor-data
+  sandbox-in-focus?:boolean  <span class="Comment"># false =&gt; cursor in recipes; true =&gt; cursor in current-sandbox</span>
+]
+
+<span class="muRecipe">recipe</span> new-programming-environment [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  initial-recipe-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  initial-sandbox-contents:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  width:number<span class="Special"> &lt;- </span>screen-width screen
+  height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Comment"># top menu</span>
+  result:address:programming-environment-data<span class="Special"> &lt;- </span>new <span class="Constant">programming-environment-data:type</span>
+  draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span>
+  button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span>
+  button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span>
+  assert button-on-screen?, <span class="Constant">[screen too narrow for menu]</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0/row</span>, button-start
+  run-button:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ run (F4) ]</span>
+  print-string screen, run-button, <span class="Constant">255/white</span>, <span class="Constant">161/reddish</span>
+  <span class="Comment"># dotted line down the middle</span>
+  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
+  draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span>
+  <span class="Comment"># recipe editor on the left</span>
+  recipes:address:address:editor-data<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">recipes:offset</span>
+  *recipes<span class="Special"> &lt;- </span>new-editor initial-recipe-contents, screen, <span class="Constant">0/left</span>, divider/right
+  <span class="Comment"># sandbox editor on the right</span>
+  new-left:number<span class="Special"> &lt;- </span>add divider, <span class="Constant">1</span>
+  current-sandbox:address:address:editor-data<span class="Special"> &lt;- </span>get-address *result, <span class="Constant">current-sandbox:offset</span>
+  *current-sandbox<span class="Special"> &lt;- </span>new-editor initial-sandbox-contents, screen, new-left, width/right
+<span class="Constant">  +programming-environment-initialization</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muRecipe">recipe</span> event-loop [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span>
+  <span class="Comment"># if we fall behind we'll stop updating the screen, but then we have to</span>
+  <span class="Comment"># render the entire screen when we catch up.</span>
+  <span class="Comment"># todo: test this</span>
+  render-all-on-no-more-events?:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span>
+<span class="Constant">    +next-event</span>
+    e:event, console, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console
+    <span class="muControl">loop-unless</span> found?
+    <span class="muControl">break-if</span> quit?  <span class="Comment"># only in tests</span>
+    trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
+<span class="Constant">    &lt;handle-event&gt;</span>
+    <span class="Comment"># check for global events that will trigger regardless of which editor has focus</span>
+    <span class="Delimiter">{</span>
+      k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span>
+      <span class="muControl">break-unless</span> k
+<span class="Constant">      &lt;global-keypress&gt;</span>
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      c:address:character<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">text:variant</span>
+      <span class="muControl">break-unless</span> c
+<span class="Constant">      &lt;global-type&gt;</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># 'touch' event - send to both sides, see what picks it up</span>
+    <span class="Delimiter">{</span>
+      t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">touch:variant</span>
+      <span class="muControl">break-unless</span> t
+      <span class="Comment"># ignore all but 'left-click' events for now</span>
+      <span class="Comment"># todo: test this</span>
+      touch-type:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">type:offset</span>
+      is-left-click?:boolean<span class="Special"> &lt;- </span>equal touch-type, <span class="Constant">65513/mouse-left</span>
+      <span class="muControl">loop-unless</span> is-left-click?, <span class="Constant">+next-event:label</span>
+      <span class="Comment"># later exceptions for non-editor touches will go here</span>
+<span class="Constant">      &lt;global-touch&gt;</span>
+      <span class="Comment"># send to both editors</span>
+      _<span class="Special"> &lt;- </span>move-cursor-in-editor screen, recipes, *t
+      *sandbox-in-focus?<span class="Special"> &lt;- </span>move-cursor-in-editor screen, current-sandbox, *t
+      screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># 'resize' event - redraw editor</span>
+    <span class="Comment"># todo: test this after supporting resize in assume-console</span>
+    <span class="Delimiter">{</span>
+      r:address:resize-event<span class="Special"> &lt;- </span>maybe-convert e:event, <span class="Constant">resize:variant</span>
+      <span class="muControl">break-unless</span> r
+      <span class="Comment"># if more events, we're still resizing; wait until we stop</span>
+      more-events?:boolean<span class="Special"> &lt;- </span>has-more-events? console
+      <span class="Delimiter">{</span>
+        <span class="muControl">break-unless</span> more-events?
+        render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>  <span class="Comment"># no rendering now, full rendering on some future event</span>
+      <span class="Delimiter">}</span>
+      <span class="Delimiter">{</span>
+        <span class="muControl">break-if</span> more-events?
+        env<span class="Special"> &lt;- </span>resize screen, env
+        screen<span class="Special"> &lt;- </span>render-all screen, env
+        render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>  <span class="Comment"># full render done</span>
+      <span class="Delimiter">}</span>
+      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if it's not global and not a touch event, send to appropriate editor</span>
+    <span class="Delimiter">{</span>
+      hide-screen screen
+      <span class="Delimiter">{</span>
+        <span class="muControl">break-if</span> *sandbox-in-focus?
+        screen, recipes, render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, recipes, e:event
+        <span class="Comment"># refresh screen only if no more events</span>
+        <span class="Comment"># if there are more events to process, wait for them to clear up, then make sure you render-all afterward.</span>
+        more-events?:boolean<span class="Special"> &lt;- </span>has-more-events? console
+        <span class="Delimiter">{</span>
+          <span class="muControl">break-unless</span> more-events?
+          render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>  <span class="Comment"># no rendering now, full rendering on some future event</span>
+          <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+        <span class="Delimiter">}</span>
+        <span class="Delimiter">{</span>
+          <span class="muControl">break-if</span> more-events?
+          <span class="Delimiter">{</span>
+            <span class="muControl">break-unless</span> render-all-on-no-more-events?
+            <span class="Comment"># no more events, and we have to force render</span>
+            screen<span class="Special"> &lt;- </span>render-all screen, env
+            render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+            <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+          <span class="Delimiter">}</span>
+          <span class="Comment"># no more events, no force render</span>
+          <span class="Delimiter">{</span>
+            <span class="muControl">break-unless</span> render?
+            screen<span class="Special"> &lt;- </span>render-recipes screen, env
+            <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+          <span class="Delimiter">}</span>
+        <span class="Delimiter">}</span>
+      <span class="Delimiter">}</span>
+      <span class="Delimiter">{</span>
+        <span class="muControl">break-unless</span> *sandbox-in-focus?
+        screen, current-sandbox, render?:boolean<span class="Special"> &lt;- </span>handle-keyboard-event screen, current-sandbox, e:event
+        <span class="Comment"># refresh screen only if no more events</span>
+        <span class="Comment"># if there are more events to process, wait for them to clear up, then make sure you render-all afterward.</span>
+        more-events?:boolean<span class="Special"> &lt;- </span>has-more-events? console
+        <span class="Delimiter">{</span>
+          <span class="muControl">break-unless</span> more-events?
+          render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>  <span class="Comment"># no rendering now, full rendering on some future event</span>
+          <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+        <span class="Delimiter">}</span>
+        <span class="Delimiter">{</span>
+          <span class="muControl">break-if</span> more-events?
+          <span class="Delimiter">{</span>
+            <span class="muControl">break-unless</span> render-all-on-no-more-events?
+            <span class="Comment"># no more events, and we have to force render</span>
+            screen<span class="Special"> &lt;- </span>render-all screen, env
+            render-all-on-no-more-events?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+            <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+          <span class="Delimiter">}</span>
+          <span class="Comment"># no more events, no force render</span>
+          <span class="Delimiter">{</span>
+            <span class="muControl">break-unless</span> render?
+            screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+            <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
+          <span class="Delimiter">}</span>
+        <span class="Delimiter">}</span>
+      <span class="Delimiter">}</span>
+<span class="Constant">      +finish-event</span>
+      screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+      show-screen screen
+    <span class="Delimiter">}</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> resize [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  clear-screen screen  <span class="Comment"># update screen dimensions</span>
+  width:number<span class="Special"> &lt;- </span>screen-width screen
+  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
+  <span class="Comment"># update recipe editor</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  right:address:number<span class="Special"> &lt;- </span>get-address *recipes, <span class="Constant">right:offset</span>
+  *right<span class="Special"> &lt;- </span>subtract divider, <span class="Constant">1</span>
+  <span class="Comment"># reset cursor (later we'll try to preserve its position)</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *recipes, <span class="Constant">cursor-row:offset</span>
+  *cursor-row<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *recipes, <span class="Constant">cursor-column:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Comment"># update sandbox editor</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  left:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">left:offset</span>
+  right:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">right:offset</span>
+  *left<span class="Special"> &lt;- </span>add divider, <span class="Constant">1</span>
+  *right<span class="Special"> &lt;- </span>subtract width, <span class="Constant">1</span>
+  <span class="Comment"># reset cursor (later we'll try to preserve its position)</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">cursor-row:offset</span>
+  *cursor-row<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">cursor-column:offset</span>
+  *cursor-column<span class="Special"> &lt;- </span>copy *left
+  <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="muScenario">scenario</span> point-at-multiple-editors [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize both halves of screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># focus on both sides</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    left-click <span class="Constant">1</span>, <span class="Constant">17</span>
+  ]
+  <span class="Comment"># check cursor column in each</span>
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span>
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">17</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> edit-multiple-editors [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize both halves of screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
+  <span class="Comment"># type one letter in each of them</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    type <span class="Constant">[0]</span>
+    left-click <span class="Constant">1</span>, <span class="Constant">17</span>
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    <span class="Constant">4</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">recipes:offset</span>
+    <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">4</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+    <span class="Constant">6</span>:address:editor-data<span class="Special"> &lt;- </span>get *<span class="Constant">3</span>:address:programming-environment-data, <span class="Constant">current-sandbox:offset</span>
+    <span class="Constant">7</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">6</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .  # this line has a different background, but we don't test that yet</span>
+   <span class="Constant"> .a0bc           ┊d1ef          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">2</span>  <span class="Comment"># cursor column of recipe editor</span>
+    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">18</span>  <span class="Comment"># cursor column of sandbox editor</span>
+  ]
+  <span class="Comment"># show the cursor at the right window</span>
+  run [
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .a0bc           ┊d1␣f          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> multiple-editors-cover-only-their-own-areas [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">60/width</span>, <span class="Constant">10/height</span>
+  run [
+    <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+    <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+    render-all screen, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># divider isn't messed up</span>
+  screen-should-contain [
+   <span class="Constant"> .                                         run (F4)           .</span>
+   <span class="Constant"> .abc                           ┊def                          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                              ┊                             .</span>
+   <span class="Constant"> .                              ┊                             .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
+  <span class="Comment"># initialize programming environment and highlight cursor</span>
+  assume-console <span class="Constant">[]</span>
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  <span class="Comment"># is cursor at the right place?</span>
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .␣bc            ┊def           .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+  <span class="Comment"># now try typing a letter</span>
+  assume-console [
+    type <span class="Constant">[z]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  <span class="Comment"># cursor should still be right</span>
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .z␣bc           ┊def           .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> backspace-in-sandbox-editor-joins-lines [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize sandbox side with two lines</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .               ┊abc           .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊def           .</span>
+   <span class="Constant"> .               ┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+  <span class="Comment"># position cursor at start of second line and hit backspace</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">16</span>
+    press backspace
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  <span class="Comment"># cursor moves to end of old line</span>
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .               ┊abc␣ef        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+]
+
+<span class="muRecipe">recipe</span> render-all [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[render all]</span>
+  hide-screen screen
+  <span class="Comment"># top menu</span>
+  trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render top menu]</span>
+  width:number<span class="Special"> &lt;- </span>screen-width screen
+  draw-horizontal screen, <span class="Constant">0</span>, <span class="Constant">0/left</span>, width, <span class="Constant">32/space</span>, <span class="Constant">0/black</span>, <span class="Constant">238/grey</span>
+  button-start:number<span class="Special"> &lt;- </span>subtract width, <span class="Constant">20</span>
+  button-on-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-start, <span class="Constant">0</span>
+  assert button-on-screen?, <span class="Constant">[screen too narrow for menu]</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0/row</span>, button-start
+  run-button:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ run (F4) ]</span>
+  print-string screen, run-button, <span class="Constant">255/white</span>, <span class="Constant">161/reddish</span>
+  <span class="Comment"># dotted line down the middle</span>
+  trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render divider]</span>
+  divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width, <span class="Constant">2</span>
+  height:number<span class="Special"> &lt;- </span>screen-height screen
+  draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span>
+  <span class="Comment">#</span>
+  screen<span class="Special"> &lt;- </span>render-recipes screen, env
+  screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+<span class="Constant">  &lt;render-components-end&gt;</span>
+  <span class="Comment">#</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span>
+  screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?
+  <span class="Comment">#</span>
+  show-screen screen
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">recipe</span> render-recipes [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render recipes]</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  <span class="Comment"># render recipes</span>
+  left:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">right:offset</span>
+  row:number, column:number, screen<span class="Special"> &lt;- </span>render screen, recipes
+  clear-line-delimited screen, column, right
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+<span class="Constant">  &lt;render-recipe-components-end&gt;</span>
+  <span class="Comment"># draw dotted line after recipes</span>
+  draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  clear-screen-from screen, row, left, left, right
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># replaced in a later layer</span>
+<span class="muRecipe">recipe</span> render-sandbox-side [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span>
+  row:number, column:number, screen, current-sandbox<span class="Special"> &lt;- </span>render screen, current-sandbox
+  clear-line-delimited screen, column, right
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  <span class="Comment"># draw solid line after recipes (you'll see why in later layers)</span>
+  draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  clear-screen-from screen, row, left, left, right
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">recipe</span> update-cursor [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?
+    cursor-row:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-row:offset</span>
+    cursor-column:number<span class="Special"> &lt;- </span>get *recipes, <span class="Constant">cursor-column:offset</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sandbox-in-focus?
+    cursor-row:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-row:offset</span>
+    cursor-column:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">cursor-column:offset</span>
+  <span class="Delimiter">}</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># row, screen &lt;- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number</span>
+<span class="Comment"># print a string 's' to 'editor' in 'color' starting at 'row'</span>
+<span class="Comment"># clear rest of last line, move cursor to next line</span>
+<span class="muRecipe">recipe</span> render-string [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  column:number<span class="Special"> &lt;- </span>copy left
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  len:number<span class="Special"> &lt;- </span>length *s
+  <span class="Delimiter">{</span>
+<span class="Constant">    +next-character</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    done?<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> done?
+    c:character<span class="Special"> &lt;- </span>index *s, i
+    <span class="Delimiter">{</span>
+      <span class="Comment"># at right? wrap.</span>
+      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
+      <span class="muControl">break-unless</span> at-right?
+      <span class="Comment"># print wrap icon</span>
+      print-character screen, <span class="Constant">8617/loop-back-to-left</span>, <span class="Constant">245/grey</span>
+      column<span class="Special"> &lt;- </span>copy left
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>  <span class="Comment"># retry i</span>
+    <span class="Delimiter">}</span>
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># newline? move to left rather than 0</span>
+      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> newline?
+      <span class="Comment"># clear rest of line in this window</span>
+      <span class="Delimiter">{</span>
+        done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
+        <span class="muControl">break-if</span> done?
+        print-character screen, <span class="Constant">32/space</span>
+        column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+        <span class="muControl">loop</span>
+      <span class="Delimiter">}</span>
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      column<span class="Special"> &lt;- </span>copy left
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    print-character screen, c, color
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  was-at-left?:boolean<span class="Special"> &lt;- </span>equal column, left
+  clear-line-delimited screen, column, right
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> was-at-left?
+    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  <span class="Delimiter">}</span>
+  move-cursor row, left
+  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">5</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># row, screen &lt;- render-code-string screen:address, s:address:array:character, left:number, right:number, row:number</span>
+<span class="Comment"># like 'render-string' but with colorization for comments like in the editor</span>
+<span class="muRecipe">recipe</span> render-code-string [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  s:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  color:number<span class="Special"> &lt;- </span>copy <span class="Constant">7/white</span>
+  column:number<span class="Special"> &lt;- </span>copy left
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  len:number<span class="Special"> &lt;- </span>length *s
+  <span class="Delimiter">{</span>
+<span class="Constant">    +next-character</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    done?<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> done?
+    c:character<span class="Special"> &lt;- </span>index *s, i
+    <span class="Constant">&lt;character-c-received&gt;</span>  <span class="Comment"># only line different from render-string</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># at right? wrap.</span>
+      at-right?:boolean<span class="Special"> &lt;- </span>equal column, right
+      <span class="muControl">break-unless</span> at-right?
+      <span class="Comment"># print wrap icon</span>
+      print-character screen, <span class="Constant">8617/loop-back-to-left</span>, <span class="Constant">245/grey</span>
+      column<span class="Special"> &lt;- </span>copy left
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>  <span class="Comment"># retry i</span>
+    <span class="Delimiter">}</span>
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># newline? move to left rather than 0</span>
+      newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
+      <span class="muControl">break-unless</span> newline?
+      <span class="Comment"># clear rest of line in this window</span>
+      <span class="Delimiter">{</span>
+        done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
+        <span class="muControl">break-if</span> done?
+        print-character screen, <span class="Constant">32/space</span>
+        column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+        <span class="muControl">loop</span>
+      <span class="Delimiter">}</span>
+      row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+      column<span class="Special"> &lt;- </span>copy left
+      screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+      <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
+    <span class="Delimiter">}</span>
+    print-character screen, c, color
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  was-at-left?:boolean<span class="Special"> &lt;- </span>equal column, left
+  clear-line-delimited screen, column, right
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> was-at-left?
+    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  <span class="Delimiter">}</span>
+  move-cursor row, left
+  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># ctrl-l - redraw screen (just in case it printed junk somehow)</span>
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-type&gt;</span> [
+  <span class="Delimiter">{</span>
+    redraw-screen?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">12/ctrl-l</span>
+    <span class="muControl">break-unless</span> redraw-screen?
+    screen<span class="Special"> &lt;- </span>render-all screen, env:address:programming-environment-data
+    sync-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># ctrl-n - switch focus</span>
+<span class="Comment"># todo: test this</span>
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-type&gt;</span> [
+  <span class="Delimiter">{</span>
+    switch-side?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">14/ctrl-n</span>
+    <span class="muControl">break-unless</span> switch-side?
+    *sandbox-in-focus?<span class="Special"> &lt;- </span>not *sandbox-in-focus?
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># ctrl-x - maximize/unmaximize the side with focus</span>
+
+<span class="muScenario">scenario</span> maximize-side [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
+  <span class="Comment"># initialize both halves of screen</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  screen<span class="Special"> &lt;- </span>render-all screen, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .abc            ┊def           .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+  <span class="Comment"># hit ctrl-x</span>
+  assume-console [
+    press ctrl-x
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># only left side visible</span>
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .abc                           .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .                              .</span>
+  ]
+  <span class="Comment"># hit any key to toggle back</span>
+  assume-console [
+    press ctrl-x
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .           run (F4)           .</span>
+   <span class="Constant"> .abc            ┊def           .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .               ┊              .</span>
+  ]
+]
+
+<span class="CommentedCode">#? # ctrl-t - browse trace</span>
+<span class="CommentedCode">#? after &lt;global-type&gt; [</span>
+<span class="CommentedCode">#?   {</span>
+<span class="CommentedCode">#?     browse-trace?:boolean &lt;- equal *c, 20/ctrl-t</span>
+<span class="CommentedCode">#?     break-unless browse-trace?</span>
+<span class="CommentedCode">#?     $browse-trace</span>
+<span class="CommentedCode">#?     screen &lt;- render-all screen, env:address:programming-environment-data</span>
+<span class="CommentedCode">#?     loop +next-event:label</span>
+<span class="CommentedCode">#?   }</span>
+<span class="CommentedCode">#? ]</span>
+
+<span class="muData">container</span> programming-environment-data [
+  maximized?:boolean
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-type&gt;</span> [
+  <span class="Delimiter">{</span>
+    maximize?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">24/ctrl-x</span>
+    <span class="muControl">break-unless</span> maximize?
+    screen, console<span class="Special"> &lt;- </span>maximize screen, console, env:address:programming-environment-data
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> maximize [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  hide-screen screen
+  <span class="Comment"># maximize one of the sides</span>
+  maximized?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">maximized?:offset</span>
+  *maximized?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
+  <span class="Comment">#</span>
+  sandbox-in-focus?:boolean<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox-in-focus?:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?
+    editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+    right:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">right:offset</span>
+    *right<span class="Special"> &lt;- </span>screen-width screen
+    *right<span class="Special"> &lt;- </span>subtract *right, <span class="Constant">1</span>
+    screen<span class="Special"> &lt;- </span>render-recipes screen, env
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sandbox-in-focus?
+    editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+    left:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">left:offset</span>
+    *left<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+  <span class="Delimiter">}</span>
+  show-screen screen
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, console/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="Comment"># when maximized, wait for any event and simply unmaximize</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-event&gt;</span> [
+  <span class="Delimiter">{</span>
+    maximized?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">maximized?:offset</span>
+    <span class="muControl">break-unless</span> *maximized?
+    *maximized?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+    <span class="Comment"># undo maximize</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> *sandbox-in-focus?
+      editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+      right:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">right:offset</span>
+      *right<span class="Special"> &lt;- </span>screen-width screen
+      *right<span class="Special"> &lt;- </span>divide *right, <span class="Constant">2</span>
+      *right<span class="Special"> &lt;- </span>subtract *right, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> *sandbox-in-focus?
+      editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+      left:address:number<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">left:offset</span>
+      *left<span class="Special"> &lt;- </span>screen-width screen
+      *left<span class="Special"> &lt;- </span>divide *left, <span class="Constant">2</span>
+      *left<span class="Special"> &lt;- </span>add *left, <span class="Constant">1</span>
+    <span class="Delimiter">}</span>
+    render-all screen, env
+    show-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="SalientComment">## helpers</span>
+
+<span class="muRecipe">recipe</span> draw-vertical [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  col:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  y:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  bottom:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  style:character, style-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> style-found?
+    style<span class="Special"> &lt;- </span>copy <span class="Constant">9474/vertical</span>
+  <span class="Delimiter">}</span>
+  color:number, color-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># default color to white</span>
+    <span class="muControl">break-if</span> color-found?
+    color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    continue?:boolean<span class="Special"> &lt;- </span>lesser-than y, bottom
+    <span class="muControl">break-unless</span> continue?
+    screen<span class="Special"> &lt;- </span>move-cursor screen, y, col
+    print-character screen, style, color
+    y<span class="Special"> &lt;- </span>add y, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html
new file mode 100644
index 00000000..7115ca00
--- /dev/null
+++ b/html/edit/005-sandbox.mu.html
@@ -0,0 +1,555 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/005-sandbox.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## running code from the editor and creating sandboxes</span>
+<span class="Comment">#</span>
+<span class="Comment"># Running code in the sandbox editor prepends its contents to a list of</span>
+<span class="Comment"># (non-editable) sandboxes below the editor, showing the result and a maybe</span>
+<span class="Comment"># few other things.</span>
+
+<span class="muData">container</span> programming-environment-data [
+  sandbox:address:sandbox-data  <span class="Comment"># list of sandboxes, from top to bottom</span>
+]
+
+<span class="muData">container</span> sandbox-data [
+  data:address:array:character
+  response:address:array:character
+  expected-response:address:array:character
+  <span class="Comment"># coordinates to track clicks</span>
+  starting-row-on-screen:number
+  code-ending-row-on-screen:number  <span class="Comment"># past end of code</span>
+  response-starting-row-on-screen:number
+  screen:address:screen  <span class="Comment"># prints in the sandbox go here</span>
+  next-sandbox:address:sandbox-data
+]
+
+<span class="muScenario">scenario</span> run-and-show-results [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Comment"># recipe editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[divide-with-remainder 11, 3]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the code in the editors</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints the results</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
+   <span class="Constant"> .                                                  ┊3                                                .</span>
+   <span class="Constant"> .                                                  ┊2                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">7/white</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                   divide-with-remainder 11, 3                      .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊3                                                .</span>
+   <span class="Constant"> .                                                  ┊2                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># run another command</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">80</span>
+    type <span class="Constant">[add 2, 2]</span>
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints the results</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
+   <span class="Constant"> .                                                  ┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
+   <span class="Constant"> .                                                  ┊3                                                .</span>
+   <span class="Constant"> .                                                  ┊2                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="Comment"># hook into event-loop recipe: read non-unicode keypress from k, process it if</span>
+<span class="Comment"># necessary, then go to next level</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-keypress&gt;</span> [
+  <span class="Comment"># F4? load all code and run all sandboxes.</span>
+  <span class="Delimiter">{</span>
+    do-run?:boolean<span class="Special"> &lt;- </span>equal *k, <span class="Constant">65532/F4</span>
+    <span class="muControl">break-unless</span> do-run?
+    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[running...  ]</span>
+    screen<span class="Special"> &lt;- </span>update-status screen, status, <span class="Constant">245/grey</span>
+    error?:boolean, env, screen<span class="Special"> &lt;- </span>run-sandboxes env, screen
+    <span class="Comment"># F4 might update warnings and results on both sides</span>
+    screen<span class="Special"> &lt;- </span>render-all screen, env
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> error?
+      status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[            ]</span>
+      screen<span class="Special"> &lt;- </span>update-status screen, status, <span class="Constant">245/grey</span>
+    <span class="Delimiter">}</span>
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> run-sandboxes [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  stop?:boolean, env, screen<span class="Special"> &lt;- </span>update-recipes env, screen
+  <span class="muControl">reply-if</span> stop?, <span class="Constant">1/errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+  <span class="Comment"># check contents of right editor (sandbox)</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  <span class="Delimiter">{</span>
+    sandbox-contents:address:array:character<span class="Special"> &lt;- </span>editor-contents current-sandbox
+    <span class="muControl">break-unless</span> sandbox-contents
+    <span class="Comment"># if contents exist, first save them</span>
+    <span class="Comment"># run them and turn them into a new sandbox-data</span>
+    new-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>new <span class="Constant">sandbox-data:type</span>
+    data:address:address:array:character<span class="Special"> &lt;- </span>get-address *new-sandbox, <span class="Constant">data:offset</span>
+    *data<span class="Special"> &lt;- </span>copy sandbox-contents
+    <span class="Comment"># push to head of sandbox list</span>
+    dest:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
+    next:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *new-sandbox, <span class="Constant">next-sandbox:offset</span>
+    *next<span class="Special"> &lt;- </span>copy *dest
+    *dest<span class="Special"> &lt;- </span>copy new-sandbox
+    <span class="Comment"># clear sandbox editor</span>
+    init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">data:offset</span>
+    *init<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167/§</span>, <span class="Constant">0/tail</span>
+    top-of-screen:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *current-sandbox, <span class="Constant">top-of-screen:offset</span>
+    *top-of-screen<span class="Special"> &lt;- </span>copy *init
+  <span class="Delimiter">}</span>
+  <span class="Comment"># save all sandboxes before running, just in case we die when running</span>
+  save-sandboxes env
+  <span class="Comment"># run all sandboxes</span>
+  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> curr
+    update-sandbox curr
+    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="Comment"># copy code from recipe editor, persist, load into mu</span>
+<span class="Comment"># replaced in a later layer</span>
+<span class="muRecipe">recipe</span> update-recipes [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes
+  save <span class="Constant">[recipes.mu]</span>, in
+  reload in
+  <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="Comment"># replaced in a later layer</span>
+<span class="muRecipe">recipe</span> update-sandbox [
+  <span class="Constant">local-scope</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
+  response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span>
+  fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">screen:offset</span>
+  *response, _, *fake-screen<span class="Special"> &lt;- </span>run-interactive data
+]
+
+<span class="muRecipe">recipe</span> update-status [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  msg:address:array:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  color:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">0</span>, <span class="Constant">2</span>
+  screen<span class="Special"> &lt;- </span>print-string screen, msg, color, <span class="Constant">238/grey/background</span>
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">recipe</span> save-sandboxes [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  <span class="Comment"># first clear previous versions, in case we deleted some sandbox</span>
+  $system <span class="Constant">[rm lesson/[0-9]</span>* &gt;/dev/null <span class="Constant">2</span>&gt;/dev/null]  <span class="Comment"># some shells can't handle '&gt;&amp;'</span>
+  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  suffix:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[.out]</span>
+  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> curr
+    data:address:array:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">data:offset</span>
+    filename:address:array:character<span class="Special"> &lt;- </span>integer-to-decimal-string idx
+    save filename, data
+    <span class="Delimiter">{</span>
+      expected-response:address:array:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">expected-response:offset</span>
+      <span class="muControl">break-unless</span> expected-response
+      filename<span class="Special"> &lt;- </span>string-append filename, suffix
+      save filename, expected-response
+    <span class="Delimiter">}</span>
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe!</span> render-sandbox-side [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render sandbox side]</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  left:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span>
+  row:number, column:number, screen, current-sandbox<span class="Special"> &lt;- </span>render screen, current-sandbox
+  clear-screen-from screen, row, column, left, right
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, sandbox, left, right, row
+  clear-rest-of-screen screen, row, left, left, right
+  <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">recipe</span> render-sandboxes [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> sandbox, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+  <span class="muControl">reply-if</span> at-bottom?:boolean, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Comment"># render sandbox menu</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
+  clear-line-delimited screen, left, right
+  print-character screen, <span class="Constant">120/x</span>, <span class="Constant">245/grey</span>
+  <span class="Comment"># save menu row so we can detect clicks to it later</span>
+  starting-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+  *starting-row<span class="Special"> &lt;- </span>copy row
+  <span class="Comment"># render sandbox contents</span>
+  row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
+  sandbox-data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
+  row, screen<span class="Special"> &lt;- </span>render-code-string screen, sandbox-data, left, right, row
+  code-ending-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>
+  *code-ending-row<span class="Special"> &lt;- </span>copy row
+  <span class="Comment"># render sandbox warnings, screen or response, in that order</span>
+  response-starting-row:address:number<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>
+  sandbox-response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span>
+<span class="Constant">  &lt;render-sandbox-results&gt;</span>
+  <span class="Delimiter">{</span>
+    sandbox-screen:address<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">screen:offset</span>
+    empty-screen?:boolean<span class="Special"> &lt;- </span>fake-screen-is-empty? sandbox-screen
+    <span class="muControl">break-if</span> empty-screen?
+    row, screen<span class="Special"> &lt;- </span>render-screen screen, sandbox-screen, left, right, row
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> empty-screen?
+    *response-starting-row<span class="Special"> &lt;- </span>copy row
+<span class="Constant">    &lt;render-sandbox-response&gt;</span>
+    row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">245/grey</span>, row
+  <span class="Delimiter">}</span>
+<span class="Constant">  +render-sandbox-end</span>
+  at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+  <span class="muControl">reply-if</span> at-bottom?, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Comment"># draw solid line after sandbox</span>
+  draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span>
+  <span class="Comment"># draw next sandbox</span>
+  next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
+  row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, next-sandbox, left, right, row
+  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span>
+<span class="muRecipe">recipe</span> restore-sandboxes [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># read all scenarios, pushing them to end of a list of scenarios</span>
+  suffix:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[.out]</span>
+  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  curr:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
+  <span class="Delimiter">{</span>
+    filename:address:array:character<span class="Special"> &lt;- </span>integer-to-decimal-string idx
+    contents:address:array:character<span class="Special"> &lt;- </span>restore filename
+    <span class="muControl">break-unless</span> contents  <span class="Comment"># stop at first error; assuming file didn't exist</span>
+    <span class="Comment"># create new sandbox for file</span>
+    *curr<span class="Special"> &lt;- </span>new <span class="Constant">sandbox-data:type</span>
+    data:address:address:array:character<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">data:offset</span>
+    *data<span class="Special"> &lt;- </span>copy contents
+    <span class="Comment"># restore expected output for sandbox if it exists</span>
+    <span class="Delimiter">{</span>
+      filename<span class="Special"> &lt;- </span>string-append filename, suffix
+      contents<span class="Special"> &lt;- </span>restore filename
+      <span class="muControl">break-unless</span> contents
+      expected-response:address:address:array:character<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">expected-response:offset</span>
+      *expected-response<span class="Special"> &lt;- </span>copy contents
+    <span class="Delimiter">}</span>
+<span class="Constant">    +continue</span>
+    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
+    curr<span class="Special"> &lt;- </span>get-address **curr, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> env/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># row, screen &lt;- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number</span>
+<span class="Comment"># print the fake sandbox screen to 'screen' with appropriate delimiters</span>
+<span class="Comment"># leave cursor at start of next line</span>
+<span class="muRecipe">recipe</span> render-screen [
+  <span class="Constant">local-scope</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  s:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="muControl">reply-unless</span> s, row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Comment"># print 'screen:'</span>
+  header:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[screen:]</span>
+  row<span class="Special"> &lt;- </span>render-string screen, header, left, right, <span class="Constant">245/grey</span>, row
+  screen<span class="Special"> &lt;- </span>move-cursor screen, row, left
+  <span class="Comment"># start printing s</span>
+  column:number<span class="Special"> &lt;- </span>copy left
+  s-width:number<span class="Special"> &lt;- </span>screen-width s
+  s-height:number<span class="Special"> &lt;- </span>screen-height s
+  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *s, <span class="Constant">data:offset</span>
+  stop-printing:number<span class="Special"> &lt;- </span>add left, s-width, <span class="Constant">3</span>
+  max-column:number<span class="Special"> &lt;- </span>min stop-printing, right
+  i:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  len:number<span class="Special"> &lt;- </span>length *buf
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen
+  <span class="Delimiter">{</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    done?<span class="Special"> &lt;- </span>greater-or-equal row, screen-height
+    <span class="muControl">break-if</span> done?
+    column<span class="Special"> &lt;- </span>copy left
+    screen<span class="Special"> &lt;- </span>move-cursor screen, row, column
+    <span class="Comment"># initial leader for each row: two spaces and a '.'</span>
+    print-character screen, <span class="Constant">32/space</span>, <span class="Constant">245/grey</span>
+    print-character screen, <span class="Constant">32/space</span>, <span class="Constant">245/grey</span>
+    print-character screen, <span class="Constant">46/full-stop</span>, <span class="Constant">245/grey</span>
+    column<span class="Special"> &lt;- </span>add left, <span class="Constant">3</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># print row</span>
+      row-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal column, max-column
+      <span class="muControl">break-if</span> row-done?
+      curr:screen-cell<span class="Special"> &lt;- </span>index *buf, i
+      c:character<span class="Special"> &lt;- </span>get curr, <span class="Constant">contents:offset</span>
+      color:number<span class="Special"> &lt;- </span>get curr, <span class="Constant">color:offset</span>
+      <span class="Delimiter">{</span>
+        <span class="Comment"># damp whites down to grey</span>
+        white?:boolean<span class="Special"> &lt;- </span>equal color, <span class="Constant">7/white</span>
+        <span class="muControl">break-unless</span> white?
+        color<span class="Special"> &lt;- </span>copy <span class="Constant">245/grey</span>
+      <span class="Delimiter">}</span>
+      print-character screen, c, color
+      column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+      i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># print final '.'</span>
+    print-character screen, <span class="Constant">46/full-stop</span>, <span class="Constant">245/grey</span>
+    column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># clear rest of current line</span>
+      line-done?:boolean<span class="Special"> &lt;- </span>greater-than column, right
+      <span class="muControl">break-if</span> line-done?
+      print-character screen, <span class="Constant">32/space</span>
+      column<span class="Special"> &lt;- </span>add column, <span class="Constant">1</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> row/same-as-ingredient:<span class="Constant">4</span>, screen/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muScenario">scenario</span> run-updates-results [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">12/height</span>
+  <span class="Comment"># define a recipe (no indent for the 'add' line below so column numbers are more obvious)</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">z:number &lt;- add 2, 2</span>
+<span class="Constant">]</span>]
+  <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the code in the editors</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints the results</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .z:number &lt;- add 2, 2                              ┊                                                x.</span>
+   <span class="Constant"> .]                                                 ┊foo                                              .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># make a change (incrementing one of the args to 'add'), then rerun</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">28</span>  <span class="Comment"># one past the value of the second arg</span>
+    press backspace
+    type <span class="Constant">[3]</span>
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen updates the result on the right</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .z:number &lt;- add 2, 3                              ┊                                                x.</span>
+   <span class="Constant"> .]                                                 ┊foo                                              .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊5                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-instruction-manages-screen-per-sandbox [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
+  <span class="Comment"># left editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an instruction</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the code in the editor</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that it prints a little toy screen</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
+   <span class="Constant"> .                                                  ┊screen:                                          .</span>
+   <span class="Constant"> .                                                  ┊  .4                             .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muRecipe">recipe</span> editor-contents [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">80</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  <span class="Comment"># skip § sentinel</span>
+  assert curr, <span class="Constant">[editor without data is illegal; must have at least a sentinel]</span>
+  curr<span class="Special"> &lt;- </span>next-duplex curr
+  <span class="muControl">reply-unless</span> curr, <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> curr
+    c:character<span class="Special"> &lt;- </span>get *curr, <span class="Constant">value:offset</span>
+    buffer-append buf, c
+    curr<span class="Special"> &lt;- </span>next-duplex curr
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  result:address:array:character<span class="Special"> &lt;- </span>buffer-to-array buf
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> editor-provides-edited-contents [
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    type <span class="Constant">[def]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:address:array:character<span class="Special"> &lt;- </span>editor-contents <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">4</span>:array:character<span class="Special"> &lt;- </span>copy *<span class="Constant">3</span>:address:array:character
+  ]
+  memory-should-contain [
+    <span class="Constant">4</span>:string<span class="Special"> &lt;- </span><span class="Constant">[abdefc]</span>
+  ]
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/006-sandbox-edit.mu.html b/html/edit/006-sandbox-edit.mu.html
new file mode 100644
index 00000000..e5c2d430
--- /dev/null
+++ b/html/edit/006-sandbox-edit.mu.html
@@ -0,0 +1,212 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/006-sandbox-edit.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## editing sandboxes after they've been created</span>
+
+<span class="muScenario">scenario</span> clicking-on-a-sandbox-moves-it-to-editor [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># basic recipe</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  add 2, 2</span>
+<span class="Constant">]</span>]
+  <span class="Comment"># run it</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  assume-console [
+    press F4
+  ]
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  add 2, 2          ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># click somewhere on the sandbox</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">30</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># it pops back into editor</span>
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊foo                .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  add 2, 2          ┊                   .</span>
+   <span class="Constant"> .]                   ┊                   .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                   .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊0foo               .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  add 2, 2          ┊                   .</span>
+   <span class="Constant"> .]                   ┊                   .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                   .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [
+  <span class="Comment"># right side of screen and below sandbox editor? pop appropriate sandbox</span>
+  <span class="Comment"># contents back into sandbox editor provided it's empty</span>
+  <span class="Delimiter">{</span>
+    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
+    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
+    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
+    <span class="muControl">break-unless</span> on-sandbox-side?
+    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+    <span class="muControl">break-unless</span> first-sandbox
+    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
+    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
+    <span class="muControl">break-unless</span> below-sandbox-editor?
+    empty-sandbox-editor?:boolean<span class="Special"> &lt;- </span>empty-editor? current-sandbox
+    <span class="muControl">break-unless</span> empty-sandbox-editor?  <span class="Comment"># make the user hit F4 before editing a new sandbox</span>
+    <span class="Comment"># identify the sandbox to edit and remove it from the sandbox list</span>
+    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>extract-sandbox env, click-row
+    text:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
+    current-sandbox<span class="Special"> &lt;- </span>insert-text current-sandbox, text
+    hide-screen screen
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    show-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> empty-editor? [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  head:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span>
+  first:address:duplex-list<span class="Special"> &lt;- </span>next-duplex head
+  result:boolean<span class="Special"> &lt;- </span>not first
+  <span class="muControl">reply</span> result
+]
+
+<span class="muRecipe">recipe</span> extract-sandbox [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
+  sandbox:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
+  start:number<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
+  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
+  <span class="Delimiter">{</span>
+    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">break-unless</span> next-sandbox
+    <span class="Comment"># if click-row &lt; sandbox.next-sandbox.starting-row-on-screen, break</span>
+    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
+    <span class="muControl">break-if</span> found?
+    sandbox<span class="Special"> &lt;- </span>get-address **sandbox, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># snip sandbox out of its list</span>
+  result:address:sandbox-data<span class="Special"> &lt;- </span>copy *sandbox
+  *sandbox<span class="Special"> &lt;- </span>copy next-sandbox
+  <span class="Comment"># position cursor in sandbox editor</span>
+  sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span>
+  *sandbox-in-focus?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span>
+  <span class="muControl">reply</span> result
+]
+
+<span class="muScenario">scenario</span> sandbox-with-print-can-be-edited [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
+  <span class="Comment"># left editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an instruction</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen:address, 4]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the sandbox</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
+   <span class="Constant"> .                                                  ┊screen:                                          .</span>
+   <span class="Constant"> .                                                  ┊  .4                             .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊  .                              .               .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># edit the sandbox</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">70</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊print-integer screen:address, 4                  .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html
new file mode 100644
index 00000000..5f3cdfcf
--- /dev/null
+++ b/html/edit/007-sandbox-delete.mu.html
@@ -0,0 +1,149 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/007-sandbox-delete.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## deleting sandboxes</span>
+
+<span class="muScenario">scenario</span> deleting-sandboxes [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run a few commands</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">80</span>
+    type <span class="Constant">[divide-with-remainder 11, 3]</span>
+    press F4
+    type <span class="Constant">[add 2, 2]</span>
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
+   <span class="Constant"> .                                                  ┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊divide-with-remainder 11, 3                      .</span>
+   <span class="Constant"> .                                                  ┊3                                                .</span>
+   <span class="Constant"> .                                                  ┊2                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># delete second sandbox</span>
+  assume-console [
+    left-click <span class="Constant">7</span>, <span class="Constant">99</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
+   <span class="Constant"> .                                                  ┊4                                                .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># delete first sandbox</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">99</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [
+  <span class="Comment"># on a sandbox delete icon? process delete</span>
+  <span class="Delimiter">{</span>
+    was-delete?:boolean<span class="Special"> &lt;- </span>delete-sandbox *t, env
+    <span class="muControl">break-unless</span> was-delete?
+    hide-screen screen
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    show-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># was-deleted?:boolean &lt;- delete-sandbox t:touch-event, env:address:programming-environment-data</span>
+<span class="muRecipe">recipe</span> delete-sandbox [
+  <span class="Constant">local-scope</span>
+  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  click-column:number<span class="Special"> &lt;- </span>get t, <span class="Constant">column:offset</span>
+  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
+  right:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">right:offset</span>
+  at-right?:boolean<span class="Special"> &lt;- </span>equal click-column, right
+  <span class="muControl">reply-unless</span> at-right?, <span class="Constant">0/false</span>
+  click-row:number<span class="Special"> &lt;- </span>get t, <span class="Constant">row:offset</span>
+  prev:address:address:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span>
+  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> curr
+    <span class="Comment"># more sandboxes to check</span>
+    <span class="Delimiter">{</span>
+      target-row:number<span class="Special"> &lt;- </span>get *curr, <span class="Constant">starting-row-on-screen:offset</span>
+      delete-curr?:boolean<span class="Special"> &lt;- </span>equal target-row, click-row
+      <span class="muControl">break-unless</span> delete-curr?
+      <span class="Comment"># delete this sandbox, rerender and stop</span>
+      *prev<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
+      <span class="muControl">reply</span> <span class="Constant">1/true</span>
+    <span class="Delimiter">}</span>
+    prev<span class="Special"> &lt;- </span>get-address *curr, <span class="Constant">next-sandbox:offset</span>
+    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">0/false</span>
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/008-sandbox-test.mu.html b/html/edit/008-sandbox-test.mu.html
new file mode 100644
index 00000000..0cdd6a08
--- /dev/null
+++ b/html/edit/008-sandbox-test.mu.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/008-sandbox-test.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## clicking on sandbox results to 'fix' them and turn sandboxes into tests</span>
+
+<span class="muScenario">scenario</span> sandbox-click-on-result-toggles-color-to-green [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># basic recipe</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  add 2, 2</span>
+<span class="Constant">]</span>]
+  <span class="Comment"># run it</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  assume-console [
+    press F4
+  ]
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  add 2, 2          ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># click on the '4' in the result</span>
+  assume-console [
+    left-click <span class="Constant">5</span>, <span class="Constant">21</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># color toggles to green</span>
+  screen-should-contain-in-color <span class="Constant">2/green</span>, [
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                     4                  .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+  ]
+  <span class="Comment"># cursor should remain unmoved</span>
+  run [
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .␣                   ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  add 2, 2          ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># now change the second arg of the 'add'</span>
+  <span class="Comment"># then rerun</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">11</span>  <span class="Comment"># cursor to end of line</span>
+    press backspace
+    type <span class="Constant">[3]</span>
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># result turns red</span>
+  screen-should-contain-in-color <span class="Constant">1/red</span>, [
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                     5                  .</span>
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                                        .</span>
+  ]
+]
+
+<span class="Comment"># clicks on sandbox responses save it as 'expected'</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [
+  <span class="Comment"># right side of screen? check if it's inside the output of any sandbox</span>
+  <span class="Delimiter">{</span>
+    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
+    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
+    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
+    <span class="muControl">break-unless</span> on-sandbox-side?
+    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+    <span class="muControl">break-unless</span> first-sandbox
+    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
+    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
+    <span class="muControl">break-unless</span> below-sandbox-editor?
+    <span class="Comment"># identify the sandbox whose output is being clicked on</span>
+    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>find-click-in-sandbox-output env, click-row
+    <span class="muControl">break-unless</span> sandbox
+    <span class="Comment"># toggle its expected-response, and save session</span>
+    sandbox<span class="Special"> &lt;- </span>toggle-expected-response sandbox
+    save-sandboxes env
+    hide-screen screen
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span>
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    <span class="Comment"># no change in cursor</span>
+    show-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> find-click-in-sandbox-output [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
+  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
+  <span class="Comment"># while click-row &lt; sandbox.next-sandbox.starting-row-on-screen</span>
+  <span class="Delimiter">{</span>
+    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">break-unless</span> next-sandbox
+    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
+    <span class="muControl">break-if</span> found?
+    sandbox<span class="Special"> &lt;- </span>copy next-sandbox
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># return sandbox if click is in its output region</span>
+  response-starting-row:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>
+  <span class="muControl">reply-unless</span> response-starting-row, <span class="Constant">0/no-click-in-sandbox-output</span>
+  click-in-response?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, response-starting-row
+  <span class="muControl">reply-unless</span> click-in-response?, <span class="Constant">0/no-click-in-sandbox-output</span>
+  <span class="muControl">reply</span> sandbox
+]
+
+<span class="muRecipe">recipe</span> toggle-expected-response [
+  <span class="Constant">local-scope</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  expected-response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">expected-response:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if expected-response is set, reset</span>
+    <span class="muControl">break-unless</span> *expected-response
+    *expected-response<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+    <span class="muControl">reply</span> sandbox/same-as-ingredient:<span class="Constant">0</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if not, current response is the expected response</span>
+  response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">response:offset</span>
+  *expected-response<span class="Special"> &lt;- </span>copy response
+  <span class="muControl">reply</span> sandbox/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="Comment"># when rendering a sandbox, color it in red/green if expected response exists</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;render-sandbox-response&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> sandbox-response
+    expected-response:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">expected-response:offset</span>
+    <span class="muControl">break-unless</span> expected-response  <span class="Comment"># fall-through to print in grey</span>
+    response-is-expected?:boolean<span class="Special"> &lt;- </span>string-equal expected-response, sandbox-response
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> response-is-expected?:boolean
+      row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">1/red</span>, row
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> response-is-expected?:boolean
+      row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-response, left, right, <span class="Constant">2/green</span>, row
+    <span class="Delimiter">}</span>
+    <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span>
+  <span class="Delimiter">}</span>
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/009-sandbox-trace.mu.html b/html/edit/009-sandbox-trace.mu.html
new file mode 100644
index 00000000..b73fbee6
--- /dev/null
+++ b/html/edit/009-sandbox-trace.mu.html
@@ -0,0 +1,248 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/009-sandbox-trace.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muScenario { color: #00af00; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## clicking on the code typed into a sandbox toggles its trace</span>
+
+<span class="muScenario">scenario</span> sandbox-click-on-code-toggles-app-trace [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># basic recipe</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  stash [abc]</span>
+]]
+  <span class="Comment"># run it</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  assume-console [
+    press F4
+  ]
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># click on the 'foo' line in the sandbox</span>
+  assume-console [
+    left-click <span class="Constant">4</span>, <span class="Constant">21</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  <span class="Comment"># trace now printed and cursor shouldn't have budged</span>
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .␣                   ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
+   <span class="Constant"> .                                        .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                  x.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc                .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># click again on the same region</span>
+  assume-console [
+    left-click <span class="Constant">4</span>, <span class="Constant">25</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+    print-character screen:address, <span class="Constant">9251/␣/cursor</span>
+  ]
+  <span class="Comment"># trace hidden again</span>
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .␣                   ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
+   <span class="Constant"> .]                   ┊foo                .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> sandbox-shows-app-trace-and-result [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">40/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># basic recipe</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  stash [abc]</span>
+  add <span class="Constant">2</span>, <span class="Constant">2</span>
+]]
+  <span class="Comment"># run it</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  assume-console [
+    press F4
+  ]
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
+   <span class="Constant"> .  add 2, 2          ┊foo                .</span>
+   <span class="Constant"> .]                   ┊4                  .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+  <span class="Comment"># click on the 'foo' line in the sandbox</span>
+  assume-console [
+    left-click <span class="Constant">4</span>, <span class="Constant">21</span>
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># trace now printed</span>
+  screen-should-contain [
+   <span class="Constant"> .                     run (F4)           .</span>
+   <span class="Constant"> .                    ┊                   .</span>
+   <span class="Constant"> .recipe foo [        ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  stash [abc]       ┊                  x.</span>
+   <span class="Constant"> .  add 2, 2          ┊foo                .</span>
+   <span class="Constant"> .]                   ┊abc                .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4                  .</span>
+   <span class="Constant"> .                    ┊━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                    ┊                   .</span>
+  ]
+]
+
+<span class="muData">container</span> sandbox-data [
+  trace:address:array:character
+  display-trace?:boolean
+]
+
+<span class="Comment"># replaced in a later layer</span>
+<span class="muRecipe">recipe!</span> update-sandbox [
+  <span class="Constant">local-scope</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
+  response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span>
+  trace:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">trace:offset</span>
+  fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">screen:offset</span>
+  *response, _, *fake-screen, *trace<span class="Special"> &lt;- </span>run-interactive data
+]
+
+<span class="Comment"># clicks on sandbox code toggle its display-trace? flag</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [
+  <span class="Comment"># right side of screen? check if it's inside the code of any sandbox</span>
+  <span class="Delimiter">{</span>
+    sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
+    click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span>
+    on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin
+    <span class="muControl">break-unless</span> on-sandbox-side?
+    first-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+    <span class="muControl">break-unless</span> first-sandbox
+    first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span>
+    below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins
+    <span class="muControl">break-unless</span> below-sandbox-editor?
+    <span class="Comment"># identify the sandbox whose code is being clicked on</span>
+    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>find-click-in-sandbox-code env, click-row
+    <span class="muControl">break-unless</span> sandbox
+    <span class="Comment"># toggle its display-trace? property</span>
+    x:address:boolean<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">display-trace?:offset</span>
+    *x<span class="Special"> &lt;- </span>not *x
+    hide-screen screen
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span>
+    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+    <span class="Comment"># no change in cursor</span>
+    show-screen screen
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">recipe</span> find-click-in-sandbox-code [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  click-row:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># assert click-row &gt;= sandbox.starting-row-on-screen</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
+  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+  clicked-on-sandboxes?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, start
+  assert clicked-on-sandboxes?, <span class="Constant">[extract-sandbox called on click to sandbox editor]</span>
+  <span class="Comment"># while click-row &lt; sandbox.next-sandbox.starting-row-on-screen</span>
+  <span class="Delimiter">{</span>
+    next-sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">next-sandbox:offset</span>
+    <span class="muControl">break-unless</span> next-sandbox
+    next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+    found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start
+    <span class="muControl">break-if</span> found?
+    sandbox<span class="Special"> &lt;- </span>copy next-sandbox
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># return sandbox if click is in its code region</span>
+  code-ending-row:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>
+  click-above-response?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, code-ending-row
+  start:number<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">starting-row-on-screen:offset</span>
+  click-below-menu?:boolean<span class="Special"> &lt;- </span>greater-than click-row, start
+  click-on-sandbox-code?:boolean<span class="Special"> &lt;- </span>and click-above-response?, click-below-menu?
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> click-on-sandbox-code?
+    <span class="muControl">reply</span> <span class="Constant">0/no-click-in-sandbox-output</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> sandbox
+]
+
+<span class="Comment"># when rendering a sandbox, dump its trace before response/warning if display-trace? property is set</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;render-sandbox-results&gt;</span> [
+  <span class="Delimiter">{</span>
+    display-trace?:boolean<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">display-trace?:offset</span>
+    <span class="muControl">break-unless</span> display-trace?
+    sandbox-trace:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">trace:offset</span>
+    <span class="muControl">break-unless</span> sandbox-trace  <span class="Comment"># nothing to print; move on</span>
+    row, screen<span class="Special"> &lt;- </span>render-string, screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row
+  <span class="Delimiter">}</span>
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/010-warnings.mu.html b/html/edit/010-warnings.mu.html
new file mode 100644
index 00000000..ca9008b7
--- /dev/null
+++ b/html/edit/010-warnings.mu.html
@@ -0,0 +1,428 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/010-warnings.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muScenario { color: #00af00; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## handling malformed programs</span>
+
+<span class="muData">container</span> programming-environment-data [
+  recipe-warnings:address:array:character
+]
+
+<span class="Comment"># copy code from recipe editor, persist, load into mu, save any warnings</span>
+<span class="muRecipe">recipe!</span> update-recipes [
+  <span class="Constant">local-scope</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+  in:address:array:character<span class="Special"> &lt;- </span>editor-contents recipes
+  save <span class="Constant">[recipes.mu]</span>, in
+  recipe-warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">recipe-warnings:offset</span>
+  *recipe-warnings<span class="Special"> &lt;- </span>reload in
+  <span class="Comment"># if recipe editor has errors, stop</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> *recipe-warnings
+    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[errors found]</span>
+    update-status screen, status, <span class="Constant">1/red</span>
+    <span class="muControl">reply</span> <span class="Constant">1/errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> <span class="Constant">0/no-errors-found</span>, env/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span>
+]
+
+<span class="muRecipe">before</span> <span class="Constant">&lt;render-components-end&gt;</span> [
+  trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render status]</span>
+  recipe-warnings:address:array:character<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-warnings:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> recipe-warnings
+    status:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[errors found]</span>
+    update-status screen, status, <span class="Constant">1/red</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">before</span> <span class="Constant">&lt;render-recipe-components-end&gt;</span> [
+  <span class="Delimiter">{</span>
+    recipe-warnings:address:array:character<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-warnings:offset</span>
+    <span class="muControl">break-unless</span> recipe-warnings
+    row, screen<span class="Special"> &lt;- </span>render-string screen, recipe-warnings, left, right, <span class="Constant">1/red</span>, row
+  <span class="Delimiter">}</span>
+]
+
+<span class="muData">container</span> sandbox-data [
+  warnings:address:array:character
+]
+
+<span class="muRecipe">recipe!</span> update-sandbox [
+  <span class="Constant">local-scope</span>
+  sandbox:address:sandbox-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  data:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
+  response:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">response:offset</span>
+  warnings:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">warnings:offset</span>
+  trace:address:address:array:character<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">trace:offset</span>
+  fake-screen:address:address:screen<span class="Special"> &lt;- </span>get-address *sandbox, <span class="Constant">screen:offset</span>
+  *response, *warnings, *fake-screen, *trace, completed?:boolean<span class="Special"> &lt;- </span>run-interactive data
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> *warnings
+    <span class="muControl">break-if</span> completed?:boolean
+    *warnings<span class="Special"> &lt;- </span>new <span class="Constant">[took too long!</span>
+<span class="Constant">]</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;render-sandbox-results&gt;</span> [
+  <span class="Delimiter">{</span>
+    sandbox-warnings:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">warnings:offset</span>
+    <span class="muControl">break-unless</span> sandbox-warnings
+    *response-starting-row<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># no response</span>
+    row, screen<span class="Special"> &lt;- </span>render-string screen, sandbox-warnings, left, right, <span class="Constant">1/red</span>, row
+    <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> run-shows-warnings-in-get [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  get 123:number, foo:offset</span>
+<span class="Constant">]</span>]
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  get 123:number, foo:offset                      ┊                                                 .</span>
+   <span class="Constant"> .]                                                 ┊                                                 .</span>
+   <span class="Constant"> .unknown element foo in container number           ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">1/red</span>, [
+   <span class="Constant"> .  errors found                                                                                      .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .unknown element foo in container number                                                             .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-shows-missing-type-warnings [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  x &lt;- copy 0</span>
+<span class="Constant">]</span>]
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x &lt;- copy 0                                     ┊                                                 .</span>
+   <span class="Constant"> .]                                                 ┊                                                 .</span>
+   <span class="Constant"> .missing type in 'x &lt;- copy 0'                     ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-shows-unbalanced-bracket-warnings [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Comment"># recipe is incomplete (unbalanced '[')</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo «</span>
+<span class="Constant">  x &lt;- copy 0</span>
+<span class="Constant">]</span>
+  string-replace <span class="Constant">1</span>:address:array:character, <span class="Constant">171/«</span>, <span class="Constant">91</span>  <span class="Comment"># '['</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo \\\[                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x &lt;- copy 0                                     ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .9: unbalanced '\\\[' for recipe                      ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-shows-get-on-non-container-warnings [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  x:address:point &lt;- new point:type</span>
+<span class="Constant">  get x:address:point, 1:offset</span>
+<span class="Constant">]</span>]
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x:address:point &lt;- new point:type               ┊                                                x.</span>
+   <span class="Constant"> .  get x:address:point, 1:offset                   ┊foo                                              .</span>
+   <span class="Constant"> .]                                                 ┊foo: first ingredient of 'get' should be a conta↩.</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊iner, but got x:address:point                    .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-shows-non-literal-get-argument-warnings [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  x:number &lt;- copy 0</span>
+<span class="Constant">  y:address:point &lt;- new point:type</span>
+<span class="Constant">  get *y:address:point, x:number</span>
+<span class="Constant">]</span>]
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x:number &lt;- copy 0                              ┊                                                 .</span>
+   <span class="Constant"> .  y:address:point &lt;- new point:type               ┊                                                 .</span>
+   <span class="Constant"> .  get *y:address:point, x:number                  ┊                                                 .</span>
+   <span class="Constant"> .]                                                 ┊                                                 .</span>
+   <span class="Constant"> .foo: expected ingredient 1 of 'get' to have type ↩┊                                                 .</span>
+   <span class="Constant"> .'offset'; got x:number                            ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-shows-warnings-everytime [
+  $close-trace  <span class="Comment"># trace too long</span>
+  <span class="Comment"># try to run a file with an error</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">15/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
+<span class="Constant">recipe foo [</span>
+<span class="Constant">  x:number &lt;- copy y:number</span>
+<span class="Constant">]</span>]
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x:number &lt;- copy y:number                       ┊                                                 .</span>
+   <span class="Constant"> .]                                                 ┊                                                 .</span>
+   <span class="Constant"> .use before set: y in foo                          ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># rerun the file, check for the same error</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .  errors found                                                                   run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊foo                                              .</span>
+   <span class="Constant"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .  x:number &lt;- copy y:number                       ┊                                                 .</span>
+   <span class="Constant"> .]                                                 ┊                                                 .</span>
+   <span class="Constant"> .use before set: y in foo                          ┊                                                 .</span>
+   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-instruction-and-print-warnings [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># left editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an illegal instruction</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the code in the editors</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints error message in red</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
+   <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">7/white</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                   get 1234:number, foo:offset                      .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">1/red</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                   unknown element foo in container number          .</span>
+   <span class="Constant"> .                                                                                                    .</span>
+  ]
+  screen-should-contain-in-color <span class="Constant">245/grey</span>, [
+   <span class="Constant"> .                                                                                                    .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> run-instruction-and-print-warnings-only-once [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  <span class="Comment"># left editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Comment"># right editor contains an illegal instruction</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[get 1234:number, foo:offset]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the code in the editors multiple times</span>
+  assume-console [
+    press F4
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># check that screen prints error message just once</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                x.</span>
+   <span class="Constant"> .                                                  ┊get 1234:number, foo:offset                      .</span>
+   <span class="Constant"> .                                                  ┊unknown element foo in container number          .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> sandbox-can-handle-infinite-loop [
+  $close-trace  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span>
+  <span class="Comment"># left editor is empty</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[recipe foo [</span>
+<span class="Constant">  {</span>
+<span class="Constant">    loop</span>
+<span class="Constant">  }</span>
+<span class="Constant">]</span>]
+  <span class="Comment"># right editor contains an instruction</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span>
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  <span class="Comment"># run the sandbox</span>
+  assume-console [
+    press F4
+  ]
+  run [
+    event-loop screen:address, console:address, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .recipe foo [                                      ┊                                                 .</span>
+   <span class="Constant"> .  {                                               ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .    loop                                          ┊                                                x.</span>
+   <span class="Constant"> .  }                                               ┊foo                                              .</span>
+   <span class="Constant"> .]                                                 ┊took too long!                                   .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit/011-editor-undo.mu.html b/html/edit/011-editor-undo.mu.html
new file mode 100644
index 00000000..37417b7f
--- /dev/null
+++ b/html/edit/011-editor-undo.mu.html
@@ -0,0 +1,2095 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - edit/011-editor-undo.mu</title>
+<meta name="Generator" content="Vim/7.4">
+<meta name="plugin-version" content="vim7.4_v1">
+<meta name="syntax" content="none">
+<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
+body { font-family: monospace; color: #eeeeee; background-color: #080808; }
+* { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
+.muData { color: #ffff00; }
+.Special { color: #ff6060; }
+.muScenario { color: #00af00; }
+.Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
+.SalientComment { color: #00ffff; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+-->
+</script>
+</head>
+<body>
+<pre id='vimCodeElement'>
+<span class="SalientComment">## undo/redo</span>
+
+<span class="Comment"># for every undoable event, create a type of *operation* that contains all the</span>
+<span class="Comment"># information needed to reverse it</span>
+<span class="muData">exclusive-container</span> operation [
+  typing:insert-operation
+  move:move-operation
+  delete:delete-operation
+]
+
+<span class="muData">container</span> insert-operation [
+  before-row:number
+  before-column:number
+  before-top-of-screen:address:duplex-list:character
+  after-row:number
+  after-column:number
+  after-top-of-screen:address:duplex-list:character
+  <span class="Comment"># inserted text is from 'insert-from' until 'insert-until'; list doesn't have to terminate</span>
+  insert-from:address:duplex-list:character
+  insert-until:address:duplex-list:character
+  tag:number  <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span>
+    <span class="Comment"># 0: no coalesce (enter+indent)</span>
+    <span class="Comment"># 1: regular alphanumeric characters</span>
+]
+
+<span class="muData">container</span> move-operation [
+  before-row:number
+  before-column:number
+  before-top-of-screen:address:duplex-list:character
+  after-row:number
+  after-column:number
+  after-top-of-screen:address:duplex-list:character
+  tag:number  <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span>
+    <span class="Comment"># 0: no coalesce (touch events, etc)</span>
+    <span class="Comment"># 1: left arrow</span>
+    <span class="Comment"># 2: right arrow</span>
+    <span class="Comment"># 3: up arrow</span>
+    <span class="Comment"># 4: down arrow</span>
+]
+
+<span class="muData">container</span> delete-operation [
+  before-row:number
+  before-column:number
+  before-top-of-screen:address:duplex-list:character
+  after-row:number
+  after-column:number
+  after-top-of-screen:address:duplex-list:character
+  deleted-text:address:duplex-list:character
+  delete-from:address:duplex-list:character
+  delete-until:address:duplex-list:character
+  tag:number  <span class="Comment"># event causing this operation; might be used to coalesce runs of similar events</span>
+    <span class="Comment"># 0: no coalesce (ctrl-k, ctrl-u)</span>
+    <span class="Comment"># 1: backspace</span>
+    <span class="Comment"># 2: delete</span>
+]
+
+<span class="Comment"># every editor accumulates a list of operations to undo/redo</span>
+<span class="muData">container</span> editor-data [
+  undo:address:list:address:operation
+  redo:address:list:address:operation
+]
+
+<span class="Comment"># ctrl-z - undo operation</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    undo?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">26/ctrl-z</span>
+    <span class="muControl">break-unless</span> undo?
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    <span class="muControl">break-unless</span> *undo
+    op:address:operation<span class="Special"> &lt;- </span>first *undo
+    *undo<span class="Special"> &lt;- </span>rest *undo
+    redo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span>
+    *redo<span class="Special"> &lt;- </span>push op, *redo
+<span class="Constant">    &lt;handle-undo&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># ctrl-y - redo operation</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
+  <span class="Delimiter">{</span>
+    redo?:boolean<span class="Special"> &lt;- </span>equal *c, <span class="Constant">25/ctrl-y</span>
+    <span class="muControl">break-unless</span> redo?
+    redo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span>
+    <span class="muControl">break-unless</span> *redo
+    op:address:operation<span class="Special"> &lt;- </span>first *redo
+    *redo<span class="Special"> &lt;- </span>rest *redo
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    *undo<span class="Special"> &lt;- </span>push op, *undo
+<span class="Constant">    &lt;handle-redo&gt;</span>
+    <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># undo typing</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-typing [
+  <span class="Comment"># create an editor and type a character</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># character should be gone</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .1         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># save operation to undo</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;insert-character-begin&gt;</span> [
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  cursor-before:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;insert-character-end&gt;</span> [
+  top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span>
+    <span class="muControl">break-unless</span> *undo
+    op:address:operation<span class="Special"> &lt;- </span>first *undo
+    typing:address:insert-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">typing:variant</span>
+    <span class="muControl">break-unless</span> typing
+    previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *typing, <span class="Constant">tag:offset</span>
+    <span class="muControl">break-unless</span> previous-coalesce-tag
+    insert-until:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">insert-until:offset</span>
+    *insert-until<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    after-row:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-row:offset</span>
+    *after-row<span class="Special"> &lt;- </span>copy *cursor-row
+    after-column:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-column:offset</span>
+    *after-column<span class="Special"> &lt;- </span>copy *cursor-column
+    after-top:address:number<span class="Special"> &lt;- </span>get-address *typing, <span class="Constant">after-top-of-screen:offset</span>
+    *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    <span class="muControl">break</span> <span class="Constant">+done-adding-insert-operation:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if not, create a new operation</span>
+  insert-from:address:duplex-list<span class="Special"> &lt;- </span>next-duplex cursor-before
+  insert-to:address:duplex-list<span class="Special"> &lt;- </span>next-duplex insert-from
+  op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+  *op<span class="Special"> &lt;- </span>merge <span class="Constant">0/insert-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, insert-from, insert-to, <span class="Constant">1/coalesce</span>
+  editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">  +done-adding-insert-operation</span>
+]
+
+<span class="Comment"># enter operations never coalesce with typing before or after</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;insert-enter-begin&gt;</span> [
+  cursor-row-before:number<span class="Special"> &lt;- </span>copy *cursor-row
+  cursor-column-before:number<span class="Special"> &lt;- </span>copy *cursor-column
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  cursor-before:address:duplex-list<span class="Special"> &lt;- </span>copy *before-cursor
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;insert-enter-end&gt;</span> [
+  top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  <span class="Comment"># never coalesce</span>
+  insert-from:address:duplex-list<span class="Special"> &lt;- </span>next-duplex cursor-before
+  insert-to:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+  op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+  *op<span class="Special"> &lt;- </span>merge <span class="Constant">0/insert-operation</span>, cursor-row-before, cursor-column-before, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, insert-from, insert-to, <span class="Constant">0/never-coalesce</span>
+  editor<span class="Special"> &lt;- </span>add-operation editor, op
+]
+
+<span class="Comment"># Everytime you add a new operation to the undo stack, be sure to clear the</span>
+<span class="Comment"># redo stack, because it's now obsolete.</span>
+<span class="Comment"># Beware: since we're counting cursor moves as operations, this means just</span>
+<span class="Comment"># moving the cursor can lose work on the undo stack.</span>
+<span class="muRecipe">recipe</span> add-operation [
+  <span class="Constant">local-scope</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  op:address:operation<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  undo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+  *undo<span class="Special"> &lt;- </span>push op *undo
+  redo:address:address:list:address:operation<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">redo:offset</span>
+  *redo<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-undo&gt;</span> [
+  <span class="Delimiter">{</span>
+    typing:address:insert-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">typing:variant</span>
+    <span class="muControl">break-unless</span> typing
+    start:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span>
+    end:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-until:offset</span>
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    *before-cursor<span class="Special"> &lt;- </span>prev-duplex start
+    remove-duplex-between *before-cursor, end
+    *cursor-row<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-column:offset</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    *top<span class="Special"> &lt;- </span>get *typing, <span class="Constant">before-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-typing-multiple [
+  <span class="Comment"># create an editor and type multiple characters</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[012]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># all characters must be gone</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-typing-multiple-2 [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># type some characters</span>
+  assume-console [
+    type <span class="Constant">[012]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .012a      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># back to original text</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[3]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .3a        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-typing-enter [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[  abc]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># new line</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">8</span>
+    press enter
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  abc     .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># line is indented</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">5</span>
+  ]
+  <span class="Comment"># back to original text</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  abc     .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should be at end of line</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  abc1    .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># redo typing</span>
+
+<span class="muScenario">scenario</span> editor-redo-typing [
+  <span class="Comment"># create an editor, type something, undo</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[012]</span>
+    press ctrl-z
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># all characters must be back</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .012a      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[3]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0123a     .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-redo&gt;</span> [
+  <span class="Delimiter">{</span>
+    typing:address:insert-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">typing:variant</span>
+    <span class="muControl">break-unless</span> typing
+    insert-from:address:duplex-list<span class="Special"> &lt;- </span>get *typing, <span class="Constant">insert-from:offset</span>  <span class="Comment"># ignore insert-to because it's already been spliced away</span>
+    <span class="Comment"># assert insert-to matches next-duplex(*before-cursor)</span>
+    insert-duplex-range *before-cursor, insert-from
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    *cursor-row<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-column:offset</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    *top<span class="Special"> &lt;- </span>get *typing, <span class="Constant">after-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-redo-typing-empty [
+  <span class="Comment"># create an editor, type something, undo</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[012]</span>
+    press ctrl-z
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># all characters must be back</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .012       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[3]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0123      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-work-clears-redo-stack [
+  <span class="Comment"># create an editor with some text, do some work, undo</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[1]</span>
+    press ctrl-z
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># do some more work</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0abc      .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># nothing should happen</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .0abc      .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-redo-typing-and-enter-and-tab [
+  <span class="Comment"># create an editor</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># insert some text and tabs, hit enter, some more text and tabs</span>
+  assume-console [
+    press tab
+    type <span class="Constant">[ab]</span>
+    press tab
+    type <span class="Constant">[cd]</span>
+    press enter
+    press tab
+    type <span class="Constant">[efg]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+   <span class="Constant"> .    efg   .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># typing in second line deleted, but not indent</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># undo again</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># indent and newline deleted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">8</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># undo again</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># empty screen</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">8</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo again</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># newline and indent inserted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo again</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># indent and newline deleted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">7</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .  ab  cd  .</span>
+   <span class="Constant"> .    efg   .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># undo cursor movement and scroll</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-touch [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">1</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># click undone</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .1abc      .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;move-cursor-begin&gt;</span> [
+  before-cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
+  before-cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span>
+  before-top-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;move-cursor-end&gt;</span> [
+  after-cursor-row:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-row:offset</span>
+  after-cursor-column:number<span class="Special"> &lt;- </span>get *editor, <span class="Constant">cursor-column:offset</span>
+  after-top-of-screen:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> undo-coalesce-tag
+    <span class="Comment"># if previous operation was also a move, and also had the same coalesce</span>
+    <span class="Comment"># tag, coalesce with it</span>
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    <span class="muControl">break-unless</span> *undo
+    op:address:operation<span class="Special"> &lt;- </span>first *undo
+    move:address:move-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">move:variant</span>
+    <span class="muControl">break-unless</span> move
+    previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *move, <span class="Constant">tag:offset</span>
+    coalesce?:boolean<span class="Special"> &lt;- </span>equal undo-coalesce-tag, previous-coalesce-tag
+    <span class="muControl">break-unless</span> coalesce?
+    after-row:address:number<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-row:offset</span>
+    *after-row<span class="Special"> &lt;- </span>copy after-cursor-row
+    after-column:address:number<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-column:offset</span>
+    *after-column<span class="Special"> &lt;- </span>copy after-cursor-column
+    after-top:address:number<span class="Special"> &lt;- </span>get-address *move, <span class="Constant">after-top-of-screen:offset</span>
+    *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    <span class="muControl">break</span> <span class="Constant">+done-adding-move-operation:label</span>
+  <span class="Delimiter">}</span>
+  op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+  *op<span class="Special"> &lt;- </span>merge <span class="Constant">1/move-operation</span>, before-cursor-row, before-cursor-column, before-top-of-screen, after-cursor-row, after-cursor-column, after-top-of-screen, undo-coalesce-tag
+  editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">  +done-adding-move-operation</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-undo&gt;</span> [
+  <span class="Delimiter">{</span>
+    move:address:move-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">move:variant</span>
+    <span class="muControl">break-unless</span> move
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">top-of-screen:offset</span>
+    *cursor-row<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-column:offset</span>
+    *top<span class="Special"> &lt;- </span>get *move, <span class="Constant">before-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-scroll [
+  <span class="Comment"># screen has 1 line for menu + 3 lines</span>
+  assume-screen <span class="Constant">5/width</span>, <span class="Constant">4/height</span>
+  <span class="Comment"># editor contains a wrapped line</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">cdefgh]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># position cursor at end of screen and try to move right</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">3</span>
+    press right-arrow
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  <span class="Comment"># screen scrolls</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+<span class="Constant">    .cdef↩.</span>
+   <span class="Constant"> .gh   .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moved back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># scroll undone</span>
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .a    .</span>
+   <span class="Constant"> .b    .</span>
+<span class="Constant">    .cdef↩.</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .b    .</span>
+<span class="Constant">    .cde1↩.</span>
+   <span class="Constant"> .fgh  .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-left-arrow [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">1</span>
+    press left-arrow
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .g1hi      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-up-arrow [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor</span>
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">1</span>
+    press up-arrow
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .g1hi      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-down-arrow [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press down-arrow
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .d1ef      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-ctrl-f [
+  <span class="Comment"># create an editor with multiple pages of text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># scroll the page</span>
+  assume-console [
+    press ctrl-f
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen should again show page 1</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-page-down [
+  <span class="Comment"># create an editor with multiple pages of text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># scroll the page</span>
+  assume-console [
+    press page-down
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen should again show page 1</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .b         .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .d         .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-ctrl-b [
+  <span class="Comment"># create an editor with multiple pages of text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># scroll the page down and up</span>
+  assume-console [
+    press page-down
+    press ctrl-b
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen should again show page 2</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .f         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-page-up [
+  <span class="Comment"># create an editor with multiple pages of text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[a</span>
+<span class="Constant">b</span>
+<span class="Constant">c</span>
+<span class="Constant">d</span>
+<span class="Constant">e</span>
+<span class="Constant">f]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># scroll the page down and up</span>
+  assume-console [
+    press page-down
+    press page-up
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen should again show page 2</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .f         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-ctrl-a [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor, then to start of line</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press ctrl-a
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .d1ef      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-home [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor, then to start of line</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press home
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .d1ef      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-ctrl-e [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor, then to start of line</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press ctrl-e
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .d1ef      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-end [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor, then to start of line</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press end
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves back</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .d1ef      .</span>
+   <span class="Constant"> .ghi       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-separates-undo-insert-from-undo-cursor-move [
+  <span class="Comment"># create an editor, type some text, move the cursor, type some more text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    type <span class="Constant">[abc]</span>
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    type <span class="Constant">[d]</span>
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .adbc      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># last letter typed is deleted</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># undo again</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># no change to screen; cursor moves</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># undo again</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># screen empty</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .          .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># first insert</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># redo again</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># redo again</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># second insert</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .adbc      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-can-undo-multiple-arrows-in-the-same-direction [
+  <span class="Comment"># create an editor with some text</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># move the cursor</span>
+  assume-console [
+    left-click <span class="Constant">2</span>, <span class="Constant">1</span>
+    press right-arrow
+    press right-arrow
+    press up-arrow
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># up-arrow is undone</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  <span class="Comment"># undo again</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># both right-arrows are undone</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+]
+
+<span class="Comment"># redo cursor movement and scroll</span>
+
+<span class="muScenario">scenario</span> editor-redo-touch [
+  <span class="Comment"># create an editor with some text, click on a character, undo</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">ghi]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  assume-console [
+    left-click <span class="Constant">3</span>, <span class="Constant">1</span>
+    press ctrl-z
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+    <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+    <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  ]
+  <span class="Comment"># cursor moves to left-click</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .g1hi      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-redo&gt;</span> [
+  <span class="Delimiter">{</span>
+    move:address:move-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">move:variant</span>
+    <span class="muControl">break-unless</span> move
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    *cursor-row<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-column:offset</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    *top<span class="Special"> &lt;- </span>get *move, <span class="Constant">after-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># undo backspace</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-and-redo-backspace [
+  <span class="Comment"># create an editor</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># insert some text and hit backspace</span>
+  assume-console [
+    type <span class="Constant">[abc]</span>
+    press backspace
+    press backspace
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">3</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># save operation to undo</span>
+<span class="muRecipe">after</span> <span class="Constant">&lt;backspace-character-begin&gt;</span> [
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;backspace-character-end&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> backspaced-cell  <span class="Comment"># backspace failed; don't add an undo operation</span>
+    top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span>
+      <span class="muControl">break-unless</span> *undo
+      op:address:operation<span class="Special"> &lt;- </span>first *undo
+      deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span>
+      <span class="muControl">break-unless</span> deletion
+      previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">tag:offset</span>
+      coalesce?:boolean<span class="Special"> &lt;- </span>equal previous-coalesce-tag, <span class="Constant">1/coalesce-backspace</span>
+      <span class="muControl">break-unless</span> coalesce?
+      delete-from:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-from:offset</span>
+      *delete-from<span class="Special"> &lt;- </span>copy *before-cursor
+      backspaced-so-far:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span>
+      insert-duplex-range backspaced-cell, *backspaced-so-far
+      *backspaced-so-far<span class="Special"> &lt;- </span>copy backspaced-cell
+      after-row:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-row:offset</span>
+      *after-row<span class="Special"> &lt;- </span>copy *cursor-row
+      after-column:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-column:offset</span>
+      *after-column<span class="Special"> &lt;- </span>copy *cursor-column
+      after-top:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span>
+      *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+      <span class="muControl">break</span> <span class="Constant">+done-adding-backspace-operation:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if not, create a new operation</span>
+    op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+    deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, backspaced-cell/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">1/coalesce-backspace</span>
+    editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">    +done-adding-backspace-operation</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-undo&gt;</span> [
+  <span class="Delimiter">{</span>
+    deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span>
+    <span class="muControl">break-unless</span> deletion
+    start2:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">data:offset</span>
+    anchor:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span>
+    <span class="muControl">break-unless</span> anchor
+    deleted:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">deleted-text:offset</span>
+    old-cursor:address:duplex-list<span class="Special"> &lt;- </span>last-duplex deleted
+    insert-duplex-range anchor, deleted
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    *before-cursor<span class="Special"> &lt;- </span>copy old-cursor
+    *cursor-row<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-column:offset</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    *top<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">before-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;handle-redo&gt;</span> [
+  <span class="Delimiter">{</span>
+    deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span>
+    <span class="muControl">break-unless</span> deletion
+    start:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-from:offset</span>
+    end:address:duplex-list<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">delete-until:offset</span>
+    remove-duplex-between start, end
+    <span class="Comment"># assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen</span>
+    *cursor-row<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-row:offset</span>
+    *cursor-column<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-column:offset</span>
+    top:address:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    *top<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">after-top-of-screen:offset</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># undo delete</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-and-redo-delete [
+  <span class="Comment"># create an editor</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># insert some text and hit delete and backspace a few times</span>
+  assume-console [
+    type <span class="Constant">[abcdef]</span>
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    press delete
+    press backspace
+    press delete
+    press delete
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .af        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># undo deletes</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .adef      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># undo backspace</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abdef     .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># undo first delete</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcdef    .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo first delete</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abdef     .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo backspace</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .adef      .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># redo deletes</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .af        .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;delete-character-begin&gt;</span> [
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;delete-character-end&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> deleted-cell  <span class="Comment"># delete failed; don't add an undo operation</span>
+    top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># if previous operation was an insert, coalesce this operation with it</span>
+      <span class="muControl">break-unless</span> *undo
+      op:address:operation<span class="Special"> &lt;- </span>first *undo
+      deletion:address:delete-operation<span class="Special"> &lt;- </span>maybe-convert *op, <span class="Constant">delete:variant</span>
+      <span class="muControl">break-unless</span> deletion
+      previous-coalesce-tag:number<span class="Special"> &lt;- </span>get *deletion, <span class="Constant">tag:offset</span>
+      coalesce?:boolean<span class="Special"> &lt;- </span>equal previous-coalesce-tag, <span class="Constant">2/coalesce-delete</span>
+      <span class="muControl">break-unless</span> coalesce?
+      delete-until:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">delete-until:offset</span>
+      *delete-until<span class="Special"> &lt;- </span>next-duplex *before-cursor
+      deleted-so-far:address:address:duplex-list<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">deleted-text:offset</span>
+      *deleted-so-far<span class="Special"> &lt;- </span>append-duplex *deleted-so-far, deleted-cell
+      after-row:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-row:offset</span>
+      *after-row<span class="Special"> &lt;- </span>copy *cursor-row
+      after-column:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-column:offset</span>
+      *after-column<span class="Special"> &lt;- </span>copy *cursor-column
+      after-top:address:number<span class="Special"> &lt;- </span>get-address *deletion, <span class="Constant">after-top-of-screen:offset</span>
+      *after-top<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+      <span class="muControl">break</span> <span class="Constant">+done-adding-delete-operation:label</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if not, create a new operation</span>
+    op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+    deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cell/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">2/coalesce-delete</span>
+    editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">    +done-adding-delete-operation</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># undo ctrl-k</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-and-redo-ctrl-k [
+  <span class="Comment"># create an editor</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># insert some text and hit delete and backspace a few times</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">1</span>
+    press ctrl-k
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a         .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .a1        .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;delete-to-end-of-line-begin&gt;</span> [
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;delete-to-end-of-line-end&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> deleted-cells  <span class="Comment"># delete failed; don't add an undo operation</span>
+    top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+    deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">0/never-coalesce</span>
+    editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">    +done-adding-delete-operation</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># undo ctrl-u</span>
+
+<span class="muScenario">scenario</span> editor-can-undo-and-redo-ctrl-u [
+  <span class="Comment"># create an editor</span>
+  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
+  <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  <span class="Constant">2</span>:address:editor-data<span class="Special"> &lt;- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
+  editor-render screen, <span class="Constant">2</span>:address:editor-data
+  <span class="Comment"># insert some text and hit delete and backspace a few times</span>
+  assume-console [
+    left-click <span class="Constant">1</span>, <span class="Constant">2</span>
+    press ctrl-u
+  ]
+  editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># undo</span>
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">2</span>
+  ]
+  <span class="Comment"># redo</span>
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  <span class="Comment"># first line inserted</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .c         .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span>
+  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span>
+  memory-should-contain [
+    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
+    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">0</span>
+  ]
+  <span class="Comment"># cursor should be in the right place</span>
+  assume-console [
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .1c        .</span>
+   <span class="Constant"> .def       .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈.</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;delete-to-start-of-line-begin&gt;</span> [
+  top-before:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+]
+<span class="muRecipe">before</span> <span class="Constant">&lt;delete-to-start-of-line-end&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> deleted-cells  <span class="Comment"># delete failed; don't add an undo operation</span>
+    top-after:address:duplex-list<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+    undo:address:address:list<span class="Special"> &lt;- </span>get-address *editor, <span class="Constant">undo:offset</span>
+    op:address:operation<span class="Special"> &lt;- </span>new <span class="Constant">operation:type</span>
+    deleted-until:address:duplex-list<span class="Special"> &lt;- </span>next-duplex *before-cursor
+    *op<span class="Special"> &lt;- </span>merge <span class="Constant">2/delete-operation</span>, save-row/<span class="muRecipe">before</span>, save-column/<span class="muRecipe">before</span>, top-before, *cursor-row/<span class="muRecipe">after</span>, *cursor-column/<span class="muRecipe">after</span>, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, <span class="Constant">0/never-coalesce</span>
+    editor<span class="Special"> &lt;- </span>add-operation editor, op
+<span class="Constant">    +done-adding-delete-operation</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="Comment"># todo:</span>
+<span class="Comment"># operations for recipe side and each sandbox-data</span>
+<span class="Comment"># undo delete sandbox as a separate primitive on the status bar</span>
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
diff --git a/html/factorial.mu.html b/html/factorial.mu.html
index 30cf628b..d3837c22 100644
--- a/html/factorial.mu.html
+++ b/html/factorial.mu.html
@@ -13,10 +13,13 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
+.muScenario { color: #00af00; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -30,36 +33,36 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: compute the factorial of 5</span>
 
-recipe main [
-  <span class="Underlined">local</span>-scope
-  x:number<span class="Special"> &lt;- </span>factorial 5
-  $<span class="Identifier">print</span> [result: ], x, [
-]
+<span class="muRecipe">recipe</span> main [
+  <span class="Constant">local-scope</span>
+  x:number<span class="Special"> &lt;- </span>factorial <span class="Constant">5</span>
+  $print <span class="Constant">[result: ]</span>, x, <span class="Constant">[ </span>
+<span class="Constant">]</span>
 ]
 
-recipe factorial [
-  <span class="Underlined">local</span>-scope
-  n:number<span class="Special"> &lt;- </span>next-ingredient
-  {
+<span class="muRecipe">recipe</span> factorial [
+  <span class="Constant">local-scope</span>
+  n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
     <span class="Comment"># if n=0 return 1</span>
-    zero?:boolean<span class="Special"> &lt;- </span>equal n, 0
-    break-unless zero?
-    reply 1
-  }
+    zero?:boolean<span class="Special"> &lt;- </span>equal n, <span class="Constant">0</span>
+    <span class="muControl">break-unless</span> zero?
+    <span class="muControl">reply</span> <span class="Constant">1</span>
+  <span class="Delimiter">}</span>
   <span class="Comment"># return n * factorial(n-1)</span>
-  x:number<span class="Special"> &lt;- </span>subtract n, 1
+  x:number<span class="Special"> &lt;- </span>subtract n, <span class="Constant">1</span>
   subresult:number<span class="Special"> &lt;- </span>factorial x
   result:number<span class="Special"> &lt;- </span>multiply subresult, n
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
 <span class="Comment"># unit test</span>
-scenario factorial-test [
+<span class="muScenario">scenario</span> factorial-test [
   run [
-    1:number<span class="Special"> &lt;- </span>factorial 5
+    <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>factorial <span class="Constant">5</span>
   ]
   memory-should-contain [
-    1<span class="Special"> &lt;- </span>120
+    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">120</span>
   ]
 ]
 </pre>
diff --git a/html/fork.mu.html b/html/fork.mu.html
index b75cceac..09d02860 100644
--- a/html/fork.mu.html
+++ b/html/fork.mu.html
@@ -13,8 +13,11 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -28,19 +31,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: running multiple routines</span>
 
-recipe main [
-  start-running thread2:recipe
-  {
-    $<span class="Identifier">print</span> 34
-    loop
-  }
+<span class="muRecipe">recipe</span> main [
+  start-running <span class="Constant">thread2:recipe</span>
+  <span class="Delimiter">{</span>
+    $print <span class="Constant">34</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
 ]
 
-recipe thread2 [
-  {
-    $<span class="Identifier">print</span> 35
-    loop
-  }
+<span class="muRecipe">recipe</span> thread2 [
+  <span class="Delimiter">{</span>
+    $print <span class="Constant">35</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
 ]
 </pre>
 </body>
diff --git a/html/global.mu.html b/html/global.mu.html
index f94b215c..6e2c0491 100644
--- a/html/global.mu.html
+++ b/html/global.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -29,17 +30,17 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: creating and using global variables</span>
 
-recipe main [
+<span class="muRecipe">recipe</span> main [
   <span class="Comment"># allocate 5 locations for globals</span>
-  global-space:address:<span class="Identifier">array</span>:location<span class="Special"> &lt;- </span><span class="Identifier">new</span> location:<span class="Identifier">type</span>, 5
+  <span class="Constant">global-space</span>:address:array:location<span class="Special"> &lt;- </span>new <span class="Constant">location:type</span>, <span class="Constant">5</span>
   <span class="Comment"># read to globals by using /space:global</span>
-  1:number/space:global<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 3
+  <span class="Special">1:number/space:global</span><span class="Special"> &lt;- </span>copy <span class="Constant">3</span>
   foo
 ]
 
-recipe foo [
+<span class="muRecipe">recipe</span> foo [
   <span class="Comment"># ditto for writing to globals</span>
-  $<span class="Identifier">print</span> 1:number/space:global
+  $print <span class="Special">1:number/space:global</span>
 ]
 </pre>
 </body>
diff --git a/html/screen.mu.html b/html/screen.mu.html
index 72156547..6efea923 100644
--- a/html/screen.mu.html
+++ b/html/screen.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -28,30 +29,30 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: managing the display using 'screen' objects</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># The zero screen below means 'use the real screen'. Tests can also use fake</span>
 <span class="Comment"># screens.</span>
 
-recipe main [
+<span class="muRecipe">recipe</span> main [
   open-console
-  <span class="Identifier">print</span>-character 0/screen, 97/a, 2/red
-  1:number/<span class="Special">raw</span>, 2:number/<span class="Special">raw &lt;- </span>cursor-position 0/screen
-  wait-for-event 0/console
-  clear-screen 0/screen
-  move-cursor 0/screen, 0/row, 4/column
-  <span class="Identifier">print</span>-character 0/screen, 98/b
-  wait-for-event 0/console
-  move-cursor 0/screen, 0/row, 0/column
-  clear-line 0/screen
-  wait-for-event 0/console
-  cursor-down 0/screen
-  wait-for-event 0/console
-  cursor-right 0/screen
-  wait-for-event 0/console
-  cursor-left 0/screen
-  wait-for-event 0/console
-  cursor-up 0/screen
-  wait-for-event 0/console
+  print-character <span class="Constant">0/screen</span>, <span class="Constant">97/a</span>, <span class="Constant">2/red</span>
+  <span class="Constant">1</span>:number/<span class="Special">raw</span>, <span class="Constant">2</span>:number/<span class="Special">raw &lt;- </span>cursor-position <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  clear-screen <span class="Constant">0/screen</span>
+  move-cursor <span class="Constant">0/screen</span>, <span class="Constant">0/row</span>, <span class="Constant">4/column</span>
+  print-character <span class="Constant">0/screen</span>, <span class="Constant">98/b</span>
+  wait-for-event <span class="Constant">0/console</span>
+  move-cursor <span class="Constant">0/screen</span>, <span class="Constant">0/row</span>, <span class="Constant">0/column</span>
+  clear-line <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  cursor-down <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  cursor-right <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  cursor-left <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
+  cursor-up <span class="Constant">0/screen</span>
+  wait-for-event <span class="Constant">0/console</span>
   close-console
 ]
 </pre>
diff --git a/html/tangle.mu.html b/html/tangle.mu.html
index aae321e8..e3dba023 100644
--- a/html/tangle.mu.html
+++ b/html/tangle.mu.html
@@ -13,10 +13,12 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
-.Special { color: #ff6060; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
-.Underlined { color: #c000c0; text-decoration: underline; }
-.Identifier { color: #804000; }
+.Constant { color: #00a0a0; }
+.Special { color: #ff6060; }
+.Delimiter { color: #a04060; }
+.muControl { color: #c0a020; }
 -->
 </style>
 
@@ -29,40 +31,40 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <body>
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: constructing recipes out of order</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># We construct a factorial function with separate base and recursive cases.</span>
 <span class="Comment"># Compare factorial.mu.</span>
-#
+<span class="Comment">#</span>
 <span class="Comment"># This isn't a very tasteful example, just a simple demonstration of</span>
 <span class="Comment"># possibilities.</span>
 
-recipe factorial [
-  <span class="Underlined">local</span>-scope
-  n:number<span class="Special"> &lt;- </span>next-ingredient
-  {
-    +base-case
-  }
-  +recursive-case
+<span class="muRecipe">recipe</span> factorial [
+  <span class="Constant">local-scope</span>
+  n:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Delimiter">{</span>
+<span class="Constant">    +base-case</span>
+  <span class="Delimiter">}</span>
+<span class="Constant">  +recursive-case</span>
 ]
 
-after +base-case [
+<span class="muRecipe">after</span> +base-case [
   <span class="Comment"># if n=0 return 1</span>
-  zero?:boolean<span class="Special"> &lt;- </span>equal n, 0
-  break-unless zero?
-  reply 1
+  zero?:boolean<span class="Special"> &lt;- </span>equal n, <span class="Constant">0</span>
+  <span class="muControl">break-unless</span> zero?
+  <span class="muControl">reply</span> <span class="Constant">1</span>
 ]
 
-after +recursive-case [
+<span class="muRecipe">after</span> +recursive-case [
   <span class="Comment"># return n * factorial(n - 1)</span>
-  x:number<span class="Special"> &lt;- </span>subtract n, 1
+  x:number<span class="Special"> &lt;- </span>subtract n, <span class="Constant">1</span>
   subresult:number<span class="Special"> &lt;- </span>factorial x
   result:number<span class="Special"> &lt;- </span>multiply subresult, n
-  reply result
+  <span class="muControl">reply</span> result
 ]
 
-recipe main [
-  1:number<span class="Special"> &lt;- </span>factorial 5
-  $<span class="Identifier">print</span> [result: ], 1:number, [
+<span class="muRecipe">recipe</span> main [
+  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>factorial <span class="Constant">5</span>
+  $print <span class="Constant">[result: ]</span>, <span class="Constant">1</span>:number, [
 ]
 ]
 </pre>
diff --git a/html/x.mu.html b/html/x.mu.html
index aa8162bc..7ff0e1aa 100644
--- a/html/x.mu.html
+++ b/html/x.mu.html
@@ -13,9 +13,10 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 1.05em; }
+.muRecipe { color: #ff8700; }
 .Comment { color: #9090ff; }
+.Constant { color: #00a0a0; }
 .Special { color: #ff6060; }
-.Identifier { color: #804000; }
 -->
 </style>
 
@@ -29,11 +30,11 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <pre id='vimCodeElement'>
 <span class="Comment"># example program: add two numbers</span>
 
-recipe main [
-  11:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 1
-  12:number<span class="Special"> &lt;- </span><span class="Identifier">copy</span> 3
-  13:number<span class="Special"> &lt;- </span>add 11:number, 12:number
-  $dump-memory
+<span class="muRecipe">recipe</span> main [
+  <span class="Constant">11</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
+  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>
+  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>add <span class="Constant">11</span>:number, <span class="Constant">12</span>:number
+<span class="Constant">  $dump-memory</span>
 ]
 </pre>
 </body>