about summary refs log tree commit diff stats
path: root/html/edit
diff options
context:
space:
mode:
Diffstat (limited to 'html/edit')
-rw-r--r--html/edit/002-typing.mu.html81
-rw-r--r--html/edit/004-programming-environment.mu.html185
-rw-r--r--html/edit/005-sandbox.mu.html246
-rw-r--r--html/edit/006-sandbox-copy.mu.html3
-rw-r--r--html/edit/007-sandbox-delete.mu.html10
-rw-r--r--html/edit/008-sandbox-edit.mu.html6
-rw-r--r--html/edit/009-sandbox-test.mu.html6
-rw-r--r--html/edit/010-sandbox-trace.mu.html46
-rw-r--r--html/edit/011-errors.mu.html4
9 files changed, 450 insertions, 137 deletions
diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html
index 7375cd90..69e1b614 100644
--- a/html/edit/002-typing.mu.html
+++ b/html/edit/002-typing.mu.html
@@ -726,12 +726,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 <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>
+    <span class="Comment"># if either:</span>
+    <span class="Comment"># a) we're at the end of the line and at the column of the wrap indicator, or</span>
+    <span class="Comment"># b) we're not at end of line and just before the column of the wrap indicator</span>
+    wrap-column:number<span class="Special"> &lt;- </span>copy right
+    before-wrap-column:number<span class="Special"> &lt;- </span>subtract wrap-column, <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
+    just-before-wrap?:boolean<span class="Special"> &lt;- </span>greater-or-equal cursor-column, before-wrap-column
+    next:address:duplex-list:character<span class="Special"> &lt;- </span>next before-cursor
+    <span class="Comment"># at end of line? next == 0 || next.value == 10/newline</span>
+    at-end-of-line?:boolean<span class="Special"> &lt;- </span>equal next, <span class="Constant">0</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> at-end-of-line?
+      next-character:character<span class="Special"> &lt;- </span>get *next, <span class="Constant">value:offset</span>
+      at-end-of-line?<span class="Special"> &lt;- </span>equal next-character, <span class="Constant">10/newline</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># break unless ((eol? and at-wrap?) or (~eol? and just-before-wrap?))</span>
+    move-cursor-to-next-line?:boolean<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-if</span> at-end-of-line?
+      move-cursor-to-next-line?<span class="Special"> &lt;- </span>copy just-before-wrap?
+      <span class="Comment"># if we're moving the cursor because it's in the middle of a wrapping</span>
+      <span class="Comment"># line, adjust it to left-most column</span>
+      potential-new-cursor-column:number<span class="Special"> &lt;- </span>copy left
+    <span class="Delimiter">}</span>
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> at-end-of-line?
+      move-cursor-to-next-line?<span class="Special"> &lt;- </span>copy at-wrap?
+      <span class="Comment"># if we're moving the cursor because it's at the end of a wrapping line,</span>
+      <span class="Comment"># adjust it to one past the left-most column to make room for the</span>
+      <span class="Comment"># newly-inserted wrap-indicator</span>
+      potential-new-cursor-column:number<span class="Special"> &lt;- </span>add left, <span class="Constant">1/make-room-for-wrap-indicator</span>
+    <span class="Delimiter">}</span>
+    <span class="muControl">break-unless</span> move-cursor-to-next-line?
+    cursor-column<span class="Special"> &lt;- </span>copy potential-new-cursor-column
     *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
     cursor-row<span class="Special"> &lt;- </span>add cursor-row, <span class="Constant">1</span>
     *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
@@ -746,12 +774,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">}</span>
 ]
 
-<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-in-middle-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">[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:screen, <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>
+    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 [
@@ -761,40 +789,43 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
   screen-should-contain [
    <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcd↩     .</span>
-   <span class="Constant"> .fe        .</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">1</span>  <span class="Comment"># cursor column</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-after-inserting-characters-2 [
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-at-end-of-line [
+  <span class="Constant">local-scope</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">[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:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
+  <span class="Comment"># create an editor containing two lines</span>
+  contents:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">xyz]</span>
+  <span class="Constant">1</span>:address:editor-data/<span class="Special">raw &lt;- </span>new-editor contents, screen, <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"> .xyz       .</span>
+   <span class="Constant"> .          .</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>
+    left-click <span class="Constant">1</span>, <span class="Constant">4</span>  <span class="Comment"># at end of first line</span>
+    type <span class="Constant">[de]</span>  <span class="Comment"># trigger wrap</span>
   ]
   run [
-    editor-event-loop screen:address:screen, console:address:console, <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>
+    editor-event-loop screen:address:screen, console:address:console, <span class="Constant">1</span>:address:editor-data/<span class="Special">raw</span>
   ]
   screen-should-contain [
    <span class="Constant"> .          .</span>
-   <span class="Constant"> .abcf↩     .</span>
-   <span class="Constant"> .de        .</span>
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .e         .</span>
+   <span class="Constant"> .xyz       .</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>
   ]
 ]
 
diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html
index 6ae14e6c..a640fa59 100644
--- a/html/edit/004-programming-environment.mu.html
+++ b/html/edit/004-programming-environment.mu.html
@@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 .Comment { color: #9090ff; }
 .Constant { color: #00a0a0; }
 .SalientComment { color: #00ffff; }
+.CommentedCode { color: #6c6c6c; }
 .muControl { color: #c0a020; }
 -->
 </style>
@@ -45,7 +46,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   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
-  render-all <span class="Constant">0/screen</span>, env
+  render-all <span class="Constant">0/screen</span>, env, render
   event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env
   <span class="Comment"># never gets here</span>
 ]
@@ -146,7 +147,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
       <span class="Delimiter">{</span>
         <span class="muControl">break-if</span> more-events?
         env, screen<span class="Special"> &lt;- </span>resize screen, env
-        screen<span class="Special"> &lt;- </span>render-all screen, env
+        screen<span class="Special"> &lt;- </span>render-all screen, env, render-without-moving-cursor
         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>
@@ -171,14 +172,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
           <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
+            screen<span class="Special"> &lt;- </span>render-all screen, env, render
             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
+            screen<span class="Special"> &lt;- </span>render-recipes screen, env, render
             <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
           <span class="Delimiter">}</span>
         <span class="Delimiter">}</span>
@@ -199,14 +200,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
           <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
+            screen<span class="Special"> &lt;- </span>render-all screen, env, render
             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
+            screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
             <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
           <span class="Delimiter">}</span>
         <span class="Delimiter">}</span>
@@ -243,6 +244,90 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   *current-sandbox<span class="Special"> &lt;- </span>put *current-sandbox, <span class="Constant">cursor-column:offset</span>, left
 ]
 
+<span class="Comment"># Variant of 'render' that updates cursor-row and cursor-column based on</span>
+<span class="Comment"># before-cursor (rather than the other way around). If before-cursor moves</span>
+<span class="Comment"># off-screen, it resets cursor-row and cursor-column.</span>
+<span class="muRecipe">def</span> render-without-moving-cursor screen:address:screen, editor:address:editor-data<span class="muRecipe"> -&gt; </span>last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  <span class="muControl">return-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>
+  curr:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  prev:address:duplex-list:character<span class="Special"> &lt;- </span>copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev</span>
+  curr<span class="Special"> &lt;- </span>next curr
+<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
+  <span class="Comment"># save before-cursor</span>
+  old-before-cursor:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">before-cursor:offset</span>
+  <span class="Comment"># initialze cursor-row/cursor-column/before-cursor to the top of the screen</span>
+  <span class="Comment"># by default</span>
+  *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-row:offset</span>, row
+  *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-column:offset</span>, column
+  top-of-screen:address:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">top-of-screen:offset</span>
+  *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">before-cursor:offset</span>, top-of-screen
+  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"># if we find old-before-cursor still on the new resized screen, update</span>
+    <span class="Comment"># editor-data.cursor-row and editor-data.cursor-column based on</span>
+    <span class="Comment"># old-before-cursor</span>
+    <span class="Delimiter">{</span>
+      at-cursor?:boolean<span class="Special"> &lt;- </span>equal old-before-cursor, prev
+      <span class="muControl">break-unless</span> at-cursor?
+      *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-row:offset</span>, row
+      *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">cursor-column:offset</span>, column
+      *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">before-cursor:offset</span>, old-before-cursor
+    <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"># clear rest of line in this window</span>
+      clear-line-until screen, 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 curr
+      prev<span class="Special"> &lt;- </span>next 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>
+      wrap-icon:character<span class="Special"> &lt;- </span>copy <span class="Constant">8617/loop-back-to-left</span>
+      print screen, wrap-icon, <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 screen, c, color
+    curr<span class="Special"> &lt;- </span>next curr
+    prev<span class="Special"> &lt;- </span>next 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>
+  *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">bottom-of-screen:offset</span>, curr
+  *editor<span class="Special"> &lt;- </span>put *editor, <span class="Constant">bottom:offset</span>, row
+  <span class="muControl">return</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>
+]
+
+
 <span class="muScenario">scenario</span> point-at-multiple-editors [
   trace-until <span class="Constant">100/app</span>  <span class="Comment"># trace too long</span>
   assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span>
@@ -276,7 +361,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <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>
@@ -321,7 +406,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     <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:screen, <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
+    render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   ]
   <span class="Comment"># divider isn't messed up</span>
   screen-should-contain [
@@ -339,7 +424,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># initialize programming environment and highlight cursor</span>
   assume-console <span class="Constant">[]</span>
   run [
@@ -373,14 +458,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 ]
 
 <span class="muScenario">scenario</span> backspace-in-sandbox-editor-joins-lines [
-  trace-until <span class="Constant">100/app</span>  <span class="Comment"># trace too long</span>
+<span class="CommentedCode">#?   trace-until 100/app  # 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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   screen-should-contain [
    <span class="Constant"> .           run (F4)           .</span>
    <span class="Constant"> .               ┊abc           .</span>
@@ -407,7 +492,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
 ]
 
-<span class="muRecipe">def</span> render-all screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
+<span class="muRecipe">def</span> render-all screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -&gt; </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
   trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[render all]</span>
@@ -427,8 +512,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   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
+  screen<span class="Special"> &lt;- </span>render-recipes screen, env, render-editor
+  screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render-editor
 <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>
@@ -439,7 +524,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   show-screen screen
 ]
 
-<span class="muRecipe">def</span> render-recipes screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
+<span class="muRecipe">def</span> render-recipes screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -&gt; </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
   trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render recipes]</span>
@@ -447,7 +532,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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
+  row:number, column:number, screen<span class="Special"> &lt;- </span>call render-editor, screen, recipes
   clear-line-until screen, right
   row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
 <span class="Constant">  &lt;render-recipe-components-end&gt;</span>
@@ -458,13 +543,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 ]
 
 <span class="Comment"># replaced in a later layer</span>
-<span class="muRecipe">def</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
+<span class="muRecipe">def</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -&gt; </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</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
+  row:number, column:number, screen, current-sandbox<span class="Special"> &lt;- </span>call render-editor, screen, current-sandbox
   clear-line-until screen, right
   row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
   <span class="Comment"># draw solid line after code (you'll see why in later layers)</span>
@@ -490,68 +575,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   screen<span class="Special"> &lt;- </span>move-cursor screen, cursor-row, cursor-column
 ]
 
-<span class="Comment"># print a text '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">def</span> render screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [
-  <span class="Constant">local-scope</span>
-  <span class="Constant">load-ingredients</span>
-  <span class="muControl">return-unless</span> s
-  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>
-      wrap-icon:character<span class="Special"> &lt;- </span>copy <span class="Constant">8617/loop-back-to-left</span>
-      print screen, wrap-icon, <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?
-        space:character<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
-        print screen, space
-        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 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-until screen, 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 screen, row, left
-]
-
 <span class="Comment"># like 'render' for texts, but with colorization for comments like in the editor</span>
 <span class="muRecipe">def</span> render-code screen:address:screen, s:address:array:character, left:number, right:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [
   <span class="Constant">local-scope</span>
@@ -621,7 +644,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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
+    screen<span class="Special"> &lt;- </span>render-all screen, env:address:programming-environment-data, render
     sync-screen screen
     <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
   <span class="Delimiter">}</span>
diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html
index e3523d27..a4aa964c 100644
--- a/html/edit/005-sandbox.mu.html
+++ b/html/edit/005-sandbox.mu.html
@@ -50,7 +50,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   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
+  render-all <span class="Constant">0/screen</span>, env, render
   event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env
   <span class="Comment"># never gets here</span>
 ]
@@ -167,7 +167,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     screen<span class="Special"> &lt;- </span>update-status screen, <span class="Constant">[running...       ]</span>, <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
+    screen<span class="Special"> &lt;- </span>render-all screen, env, render
     <span class="Delimiter">{</span>
       <span class="muControl">break-if</span> error?
       screen<span class="Special"> &lt;- </span>update-status screen, <span class="Constant">[                 ]</span>, <span class="Constant">245/grey</span>
@@ -269,7 +269,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">}</span>
 ]
 
-<span class="muRecipe">def!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
+<span class="muRecipe">def!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -&gt; </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -&gt; </span>screen:address:screen, env:address:programming-environment-data [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
   trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render sandbox side]</span>
@@ -282,7 +282,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">{</span>
     render-current-sandbox?:boolean<span class="Special"> &lt;- </span>equal render-from, <span class="Constant">-1</span>
     <span class="muControl">break-unless</span> render-current-sandbox?
-    row, column, screen, current-sandbox<span class="Special"> &lt;- </span>render screen, current-sandbox
+    row, column, screen, current-sandbox<span class="Special"> &lt;- </span>call render-editor, screen, current-sandbox
     clear-screen-from screen, row, column, left, right
     row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
   <span class="Delimiter">}</span>
@@ -327,7 +327,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     <span class="Delimiter">{</span>
       <span class="muControl">break-unless</span> empty-screen?
 <span class="Constant">      &lt;render-sandbox-response&gt;</span>
-      row, screen<span class="Special"> &lt;- </span>render screen, sandbox-response, left, right, <span class="Constant">245/grey</span>, row
+      row, screen<span class="Special"> &lt;- </span>render-text 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
@@ -388,6 +388,68 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   copy-button-right:number<span class="Special"> &lt;- </span>subtract delete-button-left, <span class="Constant">1</span>
 ]
 
+<span class="Comment"># print a text '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">def</span> render-text screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  <span class="muControl">return-unless</span> s
+  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>
+      wrap-icon:character<span class="Special"> &lt;- </span>copy <span class="Constant">8617/loop-back-to-left</span>
+      print screen, wrap-icon, <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?
+        space:character<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
+        print screen, space
+        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 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-until screen, 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 screen, row, left
+]
+
 <span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span>
 <span class="muRecipe">def</span> restore-sandboxes env:address:programming-environment-data<span class="muRecipe"> -&gt; </span>env:address:programming-environment-data [
   <span class="Constant">local-scope</span>
@@ -428,7 +490,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Constant">load-ingredients</span>
   <span class="muControl">return-unless</span> sandbox-screen
   <span class="Comment"># print 'screen:'</span>
-  row<span class="Special"> &lt;- </span>render screen, <span class="Constant">[screen:]</span>, left, right, <span class="Constant">245/grey</span>, row
+  row<span class="Special"> &lt;- </span>render-text screen, <span class="Constant">[screen:]</span>, 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 sandbox-screen</span>
   column:number<span class="Special"> &lt;- </span>copy left
@@ -611,6 +673,160 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
 ]
 
+<span class="Comment"># keep the bottom of recipes from scrolling off the screen</span>
+
+<span class="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor [
+  <span class="Constant">local-scope</span>
+  trace-until <span class="Constant">100/app</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span>
+  render-all screen, env, render
+  assume-console [
+    press enter
+    press down-arrow
+  ]
+  event-loop screen, console:address:console, env
+  <span class="Comment"># no scroll</span>
+  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="muScenario">scenario</span> cursor-down-in-recipe-editor [
+  <span class="Constant">local-scope</span>
+  trace-until <span class="Constant">100/app</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span>
+  render-all screen, env, render
+  assume-console [
+    press enter
+    press up-arrow
+    press down-arrow  <span class="Comment"># while cursor isn't at bottom</span>
+  ]
+  event-loop screen, console:address:console, env
+  cursor:character<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
+  print screen:address:screen, cursor
+  <span class="Comment"># cursor moves back to bottom</span>
+  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="Comment"># we'll not use the recipe-editor's 'bottom' element directly, because later</span>
+<span class="Comment"># layers will add other stuff to the left side below the editor (error messages)</span>
+
+<span class="muData">container</span> programming-environment-data [
+  recipe-bottom:number
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;render-recipe-components-end&gt;</span> [
+  *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">recipe-bottom:offset</span>, row
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-keypress&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?
+    down-arrow?:boolean<span class="Special"> &lt;- </span>equal k, <span class="Constant">65516/down-arrow</span>
+    <span class="muControl">break-unless</span> down-arrow?
+    recipe-editor:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
+    recipe-cursor-row:number<span class="Special"> &lt;- </span>get *recipe-editor, <span class="Constant">cursor-row:offset</span>
+    recipe-editor-bottom:number<span class="Special"> &lt;- </span>get *recipe-editor, <span class="Constant">bottom:offset</span>
+    at-bottom-of-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal recipe-cursor-row, recipe-editor-bottom
+    <span class="muControl">break-unless</span> at-bottom-of-editor?
+    more-to-scroll?:boolean<span class="Special"> &lt;- </span>more-to-scroll? env, screen
+    <span class="muControl">break-if</span> more-to-scroll?
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?
+    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?
+    more-to-scroll?:boolean<span class="Special"> &lt;- </span>more-to-scroll? env, screen
+    <span class="muControl">break-if</span> more-to-scroll?
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">after</span> <span class="Constant">&lt;global-type&gt;</span> [
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> sandbox-in-focus?
+    page-down?:boolean<span class="Special"> &lt;- </span>equal k, <span class="Constant">6/ctrl-f</span>
+    <span class="muControl">break-unless</span> page-down?
+    more-to-scroll?:boolean<span class="Special"> &lt;- </span>more-to-scroll? env, screen
+    <span class="muControl">break-if</span> more-to-scroll?
+    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+  <span class="Delimiter">}</span>
+]
+
+<span class="muRecipe">def</span> more-to-scroll? env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>result:boolean [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  recipe-bottom:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-bottom:offset</span>
+  height:number<span class="Special"> &lt;- </span>screen-height screen
+  result<span class="Special"> &lt;- </span>greater-or-equal recipe-bottom, height
+]
+
+<span class="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor-2 [
+  <span class="Constant">local-scope</span>
+  trace-until <span class="Constant">100/app</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span>
+  render-all screen, env, render
+  assume-console [
+    <span class="Comment"># add a line</span>
+    press enter
+    <span class="Comment"># cursor back to top line</span>
+    press up-arrow
+    <span class="Comment"># try to scroll</span>
+    press page-down  <span class="Comment"># or ctrl-f</span>
+  ]
+  event-loop screen, console:address:console, env
+  <span class="Comment"># no scroll, and cursor remains at top line</span>
+  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="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor-3 [
+  <span class="Constant">local-scope</span>
+  trace-until <span class="Constant">100/app</span>
+  assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span>
+  env:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[ab</span>
+<span class="Constant">cd]</span>
+  render-all screen, env, render
+  assume-console [
+    <span class="Comment"># add a line</span>
+    press enter
+    <span class="Comment"># switch to sandbox</span>
+    press ctrl-n
+    <span class="Comment"># move cursor</span>
+    press down-arrow
+  ]
+  event-loop screen, console:address:console, env
+  cursor:character<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
+  print screen:address:screen, cursor
+  <span class="Comment"># no scroll on recipe side, cursor moves on sandbox side</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊ab                                               .</span>
+   <span class="Constant"> .                                                  ┊␣d                                               .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
 <span class="Comment"># scrolling through sandboxes</span>
 
 <span class="muScenario">scenario</span> scrolling-down-past-bottom-of-sandbox-editor [
@@ -620,7 +836,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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">[add 2, 2]</span>
   <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   assume-console [
     <span class="Comment"># create a sandbox</span>
     press F4
@@ -690,7 +906,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
       *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">render-from:offset</span>, render-from
     <span class="Delimiter">}</span>
     hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
     show-screen screen
     <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
   <span class="Delimiter">}</span>
@@ -721,7 +937,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     render-from<span class="Special"> &lt;- </span>subtract render-from, <span class="Constant">1</span>
     *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">render-from:offset</span>, render-from
     hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
     show-screen screen
     <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
   <span class="Delimiter">}</span>
@@ -755,14 +971,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Comment"># create a sandbox</span>
   <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[add 2, 2]</span>
   <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   assume-console [
     press F4
   ]
   event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
   <span class="Comment"># hit 'down' in recipe editor</span>
   assume-console [
-    press down-arrow
+    press page-down
   ]
   run [
     event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
@@ -772,8 +988,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Comment"># cursor moves down on recipe side</span>
   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="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0   edit          copy            delete         .</span>
    <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   ]
@@ -786,7 +1002,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes</span>
   assume-console [
     press ctrl-n
@@ -938,7 +1154,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create a sandbox</span>
   assume-console [
     press ctrl-n
diff --git a/html/edit/006-sandbox-copy.mu.html b/html/edit/006-sandbox-copy.mu.html
index c201b609..ccf5d361 100644
--- a/html/edit/006-sandbox-copy.mu.html
+++ b/html/edit/006-sandbox-copy.mu.html
@@ -167,7 +167,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     copy?, env<span class="Special"> &lt;- </span>try-copy-sandbox click-row, env
     <span class="muControl">break-unless</span> copy?
     hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
     screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
     show-screen screen
     <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
@@ -215,6 +215,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Constant">load-ingredients</span>
   curr-sandbox: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-sandbox
     start:number<span class="Special"> &lt;- </span>get *curr-sandbox, <span class="Constant">starting-row-on-screen:offset</span>
     found?:boolean<span class="Special"> &lt;- </span>equal click-row, start
     <span class="muControl">return-if</span> found?, curr-sandbox
diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html
index 137a7887..f9f26d6f 100644
--- a/html/edit/007-sandbox-delete.mu.html
+++ b/html/edit/007-sandbox-delete.mu.html
@@ -106,7 +106,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     delete?, env<span class="Special"> &lt;- </span>try-delete-sandbox click-row, env
     <span class="muControl">break-unless</span> delete?
     hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
     screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
     show-screen screen
     <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
@@ -188,7 +188,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes and scroll to second</span>
   assume-console [
     press ctrl-n
@@ -234,7 +234,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes and scroll to second</span>
   assume-console [
     press ctrl-n
@@ -280,7 +280,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes and scroll to second</span>
   assume-console [
     press ctrl-n
@@ -328,7 +328,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes</span>
   assume-console [
     press ctrl-n
diff --git a/html/edit/008-sandbox-edit.mu.html b/html/edit/008-sandbox-edit.mu.html
index 80712819..e79738c5 100644
--- a/html/edit/008-sandbox-edit.mu.html
+++ b/html/edit/008-sandbox-edit.mu.html
@@ -162,7 +162,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     edit?, env<span class="Special"> &lt;- </span>try-edit-sandbox click-row, env
     <span class="muControl">break-unless</span> edit?
     hide-screen screen
-    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env
+    screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env, render
     screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
     show-screen screen
     <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
@@ -258,7 +258,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes and scroll to second</span>
   assume-console [
     press ctrl-n
@@ -306,7 +306,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <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:screen, <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
+  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
   <span class="Comment"># create 2 sandboxes</span>
   assume-console [
     press ctrl-n
diff --git a/html/edit/009-sandbox-test.mu.html b/html/edit/009-sandbox-test.mu.html
index 5d7e782a..eeb61f7f 100644
--- a/html/edit/009-sandbox-test.mu.html
+++ b/html/edit/009-sandbox-test.mu.html
@@ -165,7 +165,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     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>render-sandbox-side screen, env, render
     screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
     <span class="Comment"># no change in cursor</span>
     show-screen screen
@@ -226,11 +226,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     response-is-expected?:boolean<span class="Special"> &lt;- </span>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 screen, sandbox-response, left, right, <span class="Constant">1/red</span>, row
+      row, screen<span class="Special"> &lt;- </span>render-text 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 screen, sandbox-response, left, right, <span class="Constant">2/green</span>, row
+      row, screen<span class="Special"> &lt;- </span>render-text 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>
diff --git a/html/edit/010-sandbox-trace.mu.html b/html/edit/010-sandbox-trace.mu.html
index 282d2463..b791d18b 100644
--- a/html/edit/010-sandbox-trace.mu.html
+++ b/html/edit/010-sandbox-trace.mu.html
@@ -156,6 +156,48 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
 ]
 
+<span class="muScenario">scenario</span> clicking-on-app-trace-does-nothing [
+  trace-until <span class="Constant">100/app</span>  <span class="Comment"># trace too long</span>
+  assume-screen <span class="Constant">100/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">[]</span>
+  <span class="Comment"># create and expand the trace</span>
+  <span class="Constant">2</span>:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[stash 123456789]</span>
+  assume-console [
+    press F4
+    left-click <span class="Constant">4</span>, <span class="Constant">51</span>
+  ]
+  <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character
+  event-loop screen:address:screen, console:address:console, <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"> .                                                  ┊0   edit          copy            delete         .</span>
+   <span class="Constant"> .                                                  ┊stash 123456789                                  .</span>
+   <span class="Constant"> .                                                  ┊123456789                                        .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+  <span class="Comment"># click on the stash under the edit-button region (or any of the other buttons, really)</span>
+  assume-console [
+    left-click <span class="Constant">5</span>, <span class="Constant">57</span>
+  ]
+  run [
+    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
+  ]
+  <span class="Comment"># no change; doesn't die</span>
+  screen-should-contain [
+   <span class="Constant"> .                                                                                 run (F4)           .</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+<span class="Constant">    .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊0   edit          copy            delete         .</span>
+   <span class="Constant"> .                                                  ┊stash 123456789                                  .</span>
+   <span class="Constant"> .                                                  ┊123456789                                        .</span>
+   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
+   <span class="Constant"> .                                                  ┊                                                 .</span>
+  ]
+]
+
 <span class="muData">container</span> sandbox-data [
   trace:address:array:character
   display-trace?:boolean
@@ -194,7 +236,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     x<span class="Special"> &lt;- </span>not x
     *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">display-trace?:offset</span>, 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>render-sandbox-side screen, env, render
     screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
     <span class="Comment"># no change in cursor</span>
     show-screen screen
@@ -240,7 +282,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     <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 screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row
+    row, screen<span class="Special"> &lt;- </span>render-text screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row
   <span class="Delimiter">}</span>
 <span class="Constant">  &lt;render-sandbox-trace-done&gt;</span>
 ]
diff --git a/html/edit/011-errors.mu.html b/html/edit/011-errors.mu.html
index 9689ea9f..6bf5c452 100644
--- a/html/edit/011-errors.mu.html
+++ b/html/edit/011-errors.mu.html
@@ -71,7 +71,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   <span class="Delimiter">{</span>
     recipe-errors:address:array:character<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipe-errors:offset</span>
     <span class="muControl">break-unless</span> recipe-errors
-    row, screen<span class="Special"> &lt;- </span>render screen, recipe-errors, left, right, <span class="Constant">1/red</span>, row
+    row, screen<span class="Special"> &lt;- </span>render-text screen, recipe-errors, left, right, <span class="Constant">1/red</span>, row
   <span class="Delimiter">}</span>
 ]
 
@@ -143,7 +143,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     sandbox-errors:address:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">errors:offset</span>
     <span class="muControl">break-unless</span> sandbox-errors
     *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>, <span class="Constant">0</span>  <span class="Comment"># no response</span>
-    row, screen<span class="Special"> &lt;- </span>render screen, sandbox-errors, left, right, <span class="Constant">1/red</span>, row
+    row, screen<span class="Special"> &lt;- </span>render-text screen, sandbox-errors, left, right, <span class="Constant">1/red</span>, row
     <span class="Comment"># don't try to print anything more for this sandbox</span>
     <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span>
   <span class="Delimiter">}</span>