about summary refs log blame commit diff stats
path: root/html/edit/005-sandbox.mu.html
blob: 47a291e5eb0c7702699025fb6fcec1d3f221d7e0 (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                                                                                          

                                                
                                   

                                                                                         

                       
                                                                                                 
                                                                                            

                                      
                           
                            

                               
                            
                             
                                   
                              

        





                               

       
                         




                                                                                                        


                                                                                                         
 
                                         

                                           

                                                                                                           
                                                    
                                                                                                                                                                                 
                                                              
                                                                



                                                                                                 
                                                                    
                                                                                                    




                                                                                                                  
                                                                                                                                            


                                                    

               
                                                            
                                                                                                        

                                                                                   

                                                                                     


                                                               
                                                                                                  

                                                                                                
                                                                                                              
                                                                                               

                                                                                                                                                                                                                                       




                                                            
                                                                                                                                   





                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                          




















                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                          





                                                                                                                                                                                                                                            

                                                                           


                                                                                                                                        
                                                                                                                                        
   






                                                                                
                                                                                                                                   





                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                          


                                                                                                                                                                                                                                            
                                                                                                                                          







                                                                                                                                                                                                                                            


                                                                                           
                                                                                                      
                                                       
                                                                                                                                                             

                                                                                            
                                                                            

                                                    
                                                                                                                                                               
                                    
                                                                                                                    



                                                                                       
                                                                                                                                                                                                                                            
                                           

                                                                                                  
                                                        
                                                                         
                                                           
                                                                                                                                       
                                  
                                                                                            


                                                                                 

                                                                                                                                 
                                                               


                                                                                                                             
                                                       


                                                                                                                              
                                                       


                                                                                                                                                         



                                                                                                    
                                                                                                                     
                                                                                    

                                                    
                                                                         
                                                                                                        
                                                                                   

                                       
                                                         


                                                                                  
                                                                                                       
                                                                                                                                                                                                                                             
                                           
                                                
                                                                                                                       
                                                                    
                                                                                                           
           
                                                                                             


                                                        
                                                                                                                                                                                                                                                 
                                           
                                                

                                                                                                      

                                                                                                                    

 
                                                                                                                                                         
                                           
                                                
                                                                                                                                
                                                                                                                       

 
                                                                                           
                                           
                                                
                                                                                                                                       

                                                                                                                                                                                          
                                                                                                                     


                                                                                    

                                                                                                     
                       
                                                          





                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                           
                                                
                                                                                                                                  
                                                                                                                                       
                                                                                                                                    

                                                                                                                  




                                                                                                                          
                                                                                                                       



                                                                                   
                                                                                                
                                                                                                                        

                                                                                                                

 
                                                                                                                                                                                                                                                                                   
                                           
                                                
                                                      

                                                                                           
                                                             
                                                                                 
                                  



                                                                                   
                                                                                          
                                                                                    
                                                                                                                              


                                                                                   
                                                                                                                
                                                                                                     
                                                                                                                                 
                                                                                             
                                                                                                                        

                                                                
                                                                                                                                





                                                                                                           
                                                                   
                                                                                                                                                   


                                                                                             
                                                       

                                                                                                  
                                  
                                                                
                                  
                                                       

                                                                                                                                                             
                                                                         
                                  
                                                  
                                                                                                                                      

                                                                                                                               

 







































                                                                                                                                                                                                                                                      

                                                                                        
                                                                                                                                                                                                        


























































                                                                                                                                     
                                                                                                                    
                                                                                                                                                                           
                                           
                                                
                                                                                               
                                                                                    

                                                                                                   
                                  

                                                                     
                                                                                                                                        
                                                                                    
                                                              

                                                                                                           
                                                             
                                    

                                                                                                          
                                    
                                    
                                                     

                                                                                                                 
                                                                                   
                                                     

                                       
                                                     
                                                                                                                 

 

                                                                                                    
                                                                                                                                                                                                                   
                                           
                                                
                                                             
                                                
                                                                                                                                                              
                                                                         
                                                              
                                                            

                                                                                 
                                                                                                                                 












                                                                                                            




                                                                                                       













                                                                                                            
                            




                                                                                           
                                                                   




                                                                                         
                         





                                                                                           


                                                              
                                                                                                  

                                                                                                                        
                                                                                                              
                                          
                                         
                                                     
                                     

                                                                                               

                                                                                                                                                                                                                                       



                                                            
                                                                                                                                 



                                                                                                                                                                                                                                            
                                                                                                                                          



                                                                                                                                                                                                                                              



                                                                                                                                          
                                                                                                                                                     




                                          
                                                                                                                                   





                                                                                                                                                                                                                                            
                                                                                                                                          



                                                                                                                                                                                                                                              




                                                                                                                                          
                                                                                                  

                                                                                                
                                                                                                              
                                                                     

                                                                                                                                                                                                                                       




                                                           
                                                                                                                                   





                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                          
                                                                                                                                          










                                                                                                                                                                                                                                            
                                                                                                                              
                                           
                                                

                                                                                                                              

                                                                                                            
                                                   
                                                                                    


                                                                                                        
                                                        
                                                     

                                       
                                                               



                                                                                              

                                                                                                                                                                                                                                             




                                                                               
                                                                                                                         

                                                                                                                                               

                         
                                                                                                                             

   
 

























































































































































                                                                                                                                                                                                                                                                                                                                                



                                                                                                  
                                                                                                
                                                        


                                                                                                                                                                                                                                       
                                                                                                 


                                                   
   
                                                                                                                                 
                         






                                                                                                                                                                                                                                                                                                                                                
                  

                   

       
                                                                                                                                   
                                                                                                                                   
                                                                                 



                                                                               






                                                                                                                                                                                                                                                
                  
                 

       
                                                                                                                                   
                                                                                                                                   
                                                                                 
   
                                                                                   
                         




                                                                                                                                                                                                                                                                                                                                                


   
                                                                                                

                                                                                           
                                                                 

                                                                                                                
                                                                                                                          


                                                         
                                                                                                                      

                                                                                                                                      
                                                                                          
                                                                                                                                                      

                                                                                                                     

                                    
                                                                                     













                                                                                                                                                                                                   
                                         


                                  
                                                                                                                

                                                                                           
                                                                 

                                                                                                            

                                                                                                                    
                                                         

                                                                                                                   
                      
                                                                                     






                                                                                                                                                 
                                                                                                                                                                                   

                                                
                                                                                                                     
                                                                                        
                                                                                                                           
                                  
                                                                                          





                                                                                                        
                                            



                                                                                                  
                                                                                                
                                                                             
                                                                                                              

                                                 

                                                                                                                                                                                                                                       
                                                                                                 


                  
                                                                                                                                 

                                                            
                   

       
                                                                                                                                   
                                                                                                                                   
                                                                                 
   
                                                                 
                         
                                                                                                                                        

                                                                                                                                                                                                                                            

                                                                                                                                                                                                                                              




                                                                                                  
                                                                                                
                                                       


                                                                                                                                                                                                                                       
                                                                                                 







                                                   
                                                                                                                                 
                                                                                                                                 
                                                                               
                         











                                                                                                                                                                                                                                                                                                                                                
                  
                   

       
                                                                                                                                   
                                                                                                                                   
                                                                                 



                                                                               










                                                                                                                                                                                                                                                
                  
                   

       
                                                                                                                                   


                                                              








                                                                                                                                                                                                                                              
                  
                   

       
                                                                                                                                   


                                          








                                                                                                                                                                                                                                              
                  
                 

       
                                                                                                                                   


                                                                                 










                                                                                                                                                                                                                                              
                  
                 

       
                                                                                                                                   
                                                                                                                                   
                                                                                 


                                                                                    











                                                                                                                                                                                                                                                                                                                                                
                  
                 

       
                                                                                                                                   

                                                                                                                                   


                                          









                                                                                                                                                                                                                                                                                                                                                




                                                                                                  
                                                                                                
                                                       


                                                                                                                                                                                                                                       
                                                                                                 





                                                 
                                                                                                                                 
                         









                                                                                                                                                                                                                                                                                                                                                
                  
                   

       
                                                                                                                                   



                                                                               








                                                                                                                                                                                                                                              
                  
                 

       
                                                                                                                                   


                                                                                    









                                                                                                                                                                                                                                                                                                                                                
                  
                   

       
                                                                                                                                   



                                                                               






                                                                                                                                                                                                                                              

   


       
                                     
<!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_v2">
<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-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.muRecipe { color: #ff8700; }
.muData { color: #ffff00; }
.Special { color: #c00000; }
.muScenario { color: #00af00; }
.Delimiter { color: #800080; }
.Comment { color: #9090ff; }
.Constant { color: #00a0a0; }
.SalientComment { color: #00ffff; }
.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="Comment">#</span>
<span class="Comment"># This layer draws the menubar buttons non-editable sandboxes but they don't</span>
<span class="Comment"># do anything yet. Later layers implement each button.</span>

<span class="muRecipe">def!</span> main [
  <span class="Constant">local-scope</span>
  open-console
  initial-recipe:text<span class="Special"> &lt;- </span>restore <span class="Constant">[recipes.mu]</span>
  initial-sandbox:text<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, render
  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 [
  sandbox:address:sandbox-data  <span class="Comment"># list of sandboxes, from top to bottom</span>
  render-from:number
  number-of-sandboxes:number
]

<span class="muRecipe">after</span> <span class="Constant">&lt;programming-environment-initialization&gt;</span> [
  *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">render-from:offset</span>, <span class="Constant">-1</span>
]

<span class="muData">container</span> sandbox-data [
  data:text
  response:text
  <span class="Comment"># coordinates to track clicks</span>
  <span class="Comment"># constraint: will be 0 for sandboxes at positions before env.render-from</span>
  starting-row-on-screen:number
  code-ending-row-on-screen:number  <span class="Comment"># past end of code</span>
  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 [
  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">15/height</span>
  <span class="Comment"># recipe editor is empty</span>
  <span class="Constant">1</span>:text<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>:text<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:screen, <span class="Constant">1</span>:text, <span class="Constant">2</span>:text
  <span class="Comment"># run the code in the editors</span>
  assume-console [
    press F4
  ]
  run [
    event-loop screen:address:screen, console:address:console, <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"> .                                                  ┊0   edit          copy            delete         .</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"> .                                                  ┊                                                 .</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"># sandbox menu in reverse video</span>
  screen-should-contain-in-color <span class="Constant">232/black</span>, [
   <span class="Constant"> .                                                                                                    .</span>
   <span class="Constant"> .                                                                                                    .</span>
   <span class="Constant"> .                                                                                                    .</span>
   <span class="Constant"> .                                                   0   edit          copy            delete         .</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:screen, console:address:console, <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"> .                                                  ┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</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="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?
    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, 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>
    <span class="Delimiter">}</span>
    screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
    <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
  <span class="Delimiter">}</span>
]

<span class="muRecipe">def</span> run-sandboxes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  errors-found?:boolean, env, screen<span class="Special"> &lt;- </span>update-recipes env, screen
  <span class="muControl">return-if</span> errors-found?
  <span class="Comment"># check contents of right editor (sandbox)</span>
<span class="Constant">  &lt;run-sandboxes-begin&gt;</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:text<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>
    *new-sandbox<span class="Special"> &lt;- </span>put *new-sandbox, <span class="Constant">data:offset</span>, sandbox-contents
    <span class="Comment"># push to head of sandbox list</span>
    dest:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
    *new-sandbox<span class="Special"> &lt;- </span>put *new-sandbox, <span class="Constant">next-sandbox:offset</span>, dest
    *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">sandbox:offset</span>, new-sandbox
    <span class="Comment"># update sandbox count</span>
    sandbox-count:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span>
    sandbox-count<span class="Special"> &lt;- </span>add sandbox-count, <span class="Constant">1</span>
    *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, sandbox-count
    <span class="Comment"># clear sandbox editor</span>
    init:address:duplex-list:character<span class="Special"> &lt;- </span>push <span class="Constant">167/§</span>, <span class="Constant">0/tail</span>
    *current-sandbox<span class="Special"> &lt;- </span>put *current-sandbox, <span class="Constant">data:offset</span>, init
    *current-sandbox<span class="Special"> &lt;- </span>put *current-sandbox, <span class="Constant">top-of-screen:offset</span>, 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>
  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Delimiter">{</span>
    <span class="muControl">break-unless</span> curr
    curr<span class="Special"> &lt;- </span>update-sandbox curr, env, idx
    curr<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
<span class="Constant">  &lt;run-sandboxes-end&gt;</span>
]

<span class="Comment"># copy code from recipe editor, persist, load into mu</span>
<span class="Comment"># replaced in a later layer (whereupon errors-found? will actually be set)</span>
<span class="muRecipe">def</span> update-recipes env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -&gt; </span>errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  recipes:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">recipes:offset</span>
  in:text<span class="Special"> &lt;- </span>editor-contents recipes
  save <span class="Constant">[recipes.mu]</span>, in  <span class="Comment"># newlayer: persistence</span>
  reload in
  errors-found?<span class="Special"> &lt;- </span>copy <span class="Constant">0/false</span>
]

<span class="Comment"># replaced in a later layer</span>
<span class="muRecipe">def!</span> update-sandbox sandbox:address:sandbox-data, env:address:programming-environment-data, idx:number<span class="muRecipe"> -&gt; </span>sandbox:address:sandbox-data, env:address:programming-environment-data [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  data:text<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
  response:text, _, fake-screen:address:screen<span class="Special"> &lt;- </span>run-sandboxed data
  *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">response:offset</span>, response
  *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">screen:offset</span>, fake-screen
]

<span class="muRecipe">def</span> update-status screen:address:screen, msg:text, color:number<span class="muRecipe"> -&gt; </span>screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</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 screen, msg, color, <span class="Constant">238/grey/background</span>
]

<span class="muRecipe">def</span> save-sandboxes 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>
  <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>
  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:text<span class="Special"> &lt;- </span>get *curr, <span class="Constant">data:offset</span>
    filename:text<span class="Special"> &lt;- </span>to-text idx
    save filename, data
<span class="Constant">    &lt;end-save-sandbox&gt;</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">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>
  current-sandbox:address:editor-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">current-sandbox:offset</span>
  row:number, column:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>, <span class="Constant">0</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>
  <span class="Comment"># render sandbox editor</span>
  render-from:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">render-from:offset</span>
  <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>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>
  <span class="Comment"># render sandboxes</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, render-from
  clear-rest-of-screen screen, row, left, right
]

<span class="muRecipe">def</span> render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number<span class="muRecipe"> -&gt; </span>row:number, screen:address:screen, sandbox:address:sandbox-data [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="muControl">return-unless</span> sandbox
  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">return-if</span> at-bottom?:boolean
  hidden?:boolean<span class="Special"> &lt;- </span>lesser-than idx, render-from
  <span class="Delimiter">{</span>
    <span class="muControl">break-if</span> hidden?
    <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
    screen<span class="Special"> &lt;- </span>render-sandbox-menu screen, idx, left, right
    <span class="Comment"># save menu row so we can detect clicks to it later</span>
    *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">starting-row-on-screen:offset</span>, 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:text<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span>
    row, screen<span class="Special"> &lt;- </span>render-code screen, sandbox-data, left, right, row
    *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>, row
    <span class="Comment"># render sandbox warnings, screen or response, in that order</span>
    sandbox-response:text<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:screen<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?
<span class="Constant">      &lt;render-sandbox-response&gt;</span>
      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
    <span class="muControl">return-if</span> at-bottom?
    <span class="Comment"># draw solid line after sandbox</span>
    draw-horizontal screen, row, left, right, <span class="Constant">9473/horizontal-double</span>
  <span class="Delimiter">}</span>
  <span class="Comment"># if hidden, reset row attributes</span>
  <span class="Delimiter">{</span>
    <span class="muControl">break-unless</span> hidden?
    *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">starting-row-on-screen:offset</span>, <span class="Constant">0</span>
    *sandbox<span class="Special"> &lt;- </span>put *sandbox, <span class="Constant">code-ending-row-on-screen:offset</span>, <span class="Constant">0</span>
<span class="Constant">    &lt;end-render-sandbox-reset-hidden&gt;</span>
  <span class="Delimiter">}</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>
  next-idx:number<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
  row, screen<span class="Special"> &lt;- </span>render-sandboxes screen, next-sandbox, left, right, row, render-from, next-idx
]

<span class="muRecipe">def</span> render-sandbox-menu screen:address:screen, sandbox-index:number, left:number, right:number<span class="muRecipe"> -&gt; </span>screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  move-cursor-to-column screen, left
  edit-button-left:number, edit-button-right:number, copy-button-left:number, copy-button-right:number, delete-button-left:number<span class="Special"> &lt;- </span>sandbox-menu-columns left, right
  print screen, sandbox-index, <span class="Constant">232/dark-grey</span>, <span class="Constant">245/grey</span>
  start-buttons:number<span class="Special"> &lt;- </span>subtract edit-button-left, <span class="Constant">1</span>
  clear-line-until screen, start-buttons, <span class="Constant">245/grey</span>
  print screen, <span class="Constant">[edit]</span>, <span class="Constant">232/black</span>, <span class="Constant">94/background-orange</span>
  clear-line-until screen, edit-button-right, <span class="Constant">94/background-orange</span>
  _, col:number<span class="Special"> &lt;- </span>cursor-position screen
  at-start-of-copy-button?:boolean<span class="Special"> &lt;- </span>equal col, copy-button-left
  assert at-start-of-copy-button?, <span class="Constant">[aaa]</span>
  print screen, <span class="Constant">[copy]</span>, <span class="Constant">232/black</span>, <span class="Constant">58/background-green</span>
  clear-line-until screen, copy-button-right, <span class="Constant">58/background-green</span>
  _, col:number<span class="Special"> &lt;- </span>cursor-position screen
  at-start-of-delete-button?:boolean<span class="Special"> &lt;- </span>equal col, delete-button-left
  assert at-start-of-delete-button?, <span class="Constant">[bbb]</span>
  print screen, <span class="Constant">[delete]</span>, <span class="Constant">232/black</span>, <span class="Constant">52/background-red</span>
  clear-line-until screen, right, <span class="Constant">52/background-red</span>
]

<span class="Comment"># divide up the menu bar for a sandbox into 3 segments, for edit/copy/delete buttons</span>
<span class="Comment"># delete-button-right == right</span>
<span class="Comment"># all left/right pairs are inclusive</span>
<span class="muRecipe">def</span> sandbox-menu-columns left:number, right:number<span class="muRecipe"> -&gt; </span>edit-button-left:number, edit-button-right:number, copy-button-left:number, copy-button-right:number, delete-button-left:number [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  start-buttons:number<span class="Special"> &lt;- </span>add left, <span class="Constant">4/space-for-sandbox-index</span>
  buttons-space:number<span class="Special"> &lt;- </span>subtract right, start-buttons
  button-width:number<span class="Special"> &lt;- </span>divide-with-remainder buttons-space, <span class="Constant">3</span>  <span class="Comment"># integer division</span>
  buttons-wide-enough?:boolean<span class="Special"> &lt;- </span>greater-or-equal button-width, <span class="Constant">8</span>
  assert buttons-wide-enough?, <span class="Constant">[sandbox must be at least 30 or so characters wide]</span>
  edit-button-left:number<span class="Special"> &lt;- </span>copy start-buttons
  copy-button-left:number<span class="Special"> &lt;- </span>add start-buttons, button-width
  edit-button-right:number<span class="Special"> &lt;- </span>subtract copy-button-left, <span class="Constant">1</span>
  delete-button-left:number<span class="Special"> &lt;- </span>subtract right, button-width
  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:text, 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>
  <span class="Constant">load-ingredients</span>
  <span class="Comment"># read all scenarios, pushing them to end of a list of scenarios</span>
  idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  curr:address:sandbox-data<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  prev:address:sandbox-data<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Delimiter">{</span>
    filename:text<span class="Special"> &lt;- </span>to-text idx
    contents:text<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"># todo: handle empty sandbox</span>
    <span class="Comment"># create new sandbox for file</span>
    curr<span class="Special"> &lt;- </span>new <span class="Constant">sandbox-data:type</span>
    *curr<span class="Special"> &lt;- </span>put *curr, <span class="Constant">data:offset</span>, contents
<span class="Constant">    &lt;end-restore-sandbox&gt;</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-if</span> idx
      *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">sandbox:offset</span>, curr
    <span class="Delimiter">}</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-unless</span> idx
      *prev<span class="Special"> &lt;- </span>put *prev, <span class="Constant">next-sandbox:offset</span>, curr
    <span class="Delimiter">}</span>
    idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span>
    prev<span class="Special"> &lt;- </span>copy curr
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
  <span class="Comment"># update sandbox count</span>
  *env<span class="Special"> &lt;- </span>put *env, <span class="Constant">number-of-sandboxes:offset</span>, idx
]

<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">def</span> render-screen screen:address:screen, sandbox-screen:address:screen, left:number, right: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> sandbox-screen
  <span class="Comment"># print 'screen:'</span>
  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
  s-width:number<span class="Special"> &lt;- </span>screen-width sandbox-screen
  s-height:number<span class="Special"> &lt;- </span>screen-height sandbox-screen
  buf:address:array:screen-cell<span class="Special"> &lt;- </span>get *sandbox-screen, <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>
    space:character<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
    print screen, space, <span class="Constant">245/grey</span>
    print screen, space, <span class="Constant">245/grey</span>
    full-stop:character<span class="Special"> &lt;- </span>copy <span class="Constant">46/period</span>
    print screen, full-stop, <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 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 screen, full-stop, <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 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>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="muScenario">scenario</span> run-updates-results [
  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">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>:text<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
<span class="Constant">recipe foo [</span>
<span class="Constant">local-scope</span>
<span class="Constant">z:number &lt;- add 2, 2</span>
<span class="Constant">reply z</span>
<span class="Constant">]</span>]
  <span class="Comment"># sandbox editor contains an instruction without storing outputs</span>
  <span class="Constant">2</span>:text<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:screen, <span class="Constant">1</span>:text, <span class="Constant">2</span>:text
  <span class="Comment"># run the code in the editors</span>
  assume-console [
    press F4
  ]
  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"> .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .local-scope                                       ┊0   edit          copy            delete         .</span>
   <span class="Constant"> .z:number &lt;- add 2, 2                              ┊foo                                              .</span>
   <span class="Constant"> .reply z                                           ┊4                                                .</span>
   <span class="Constant"> .]                                                 ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</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">4</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:screen, console:address:console, <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"> .local-scope                                       ┊0   edit          copy            delete         .</span>
   <span class="Constant"> .z:number &lt;- add 2, 3                              ┊foo                                              .</span>
   <span class="Constant"> .reply z                                           ┊5                                                .</span>
   <span class="Constant"> .]                                                 ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
]

<span class="muScenario">scenario</span> run-instruction-manages-screen-per-sandbox [
  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">20/height</span>
  <span class="Comment"># left editor is empty</span>
  <span class="Constant">1</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
  <span class="Comment"># right editor contains an instruction</span>
  <span class="Constant">2</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen, 4]</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>:text, <span class="Constant">2</span>:text
  <span class="Comment"># run the code in the editor</span>
  assume-console [
    press F4
  ]
  run [
    event-loop screen:address:screen, console:address:console, <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"> .                                                  ┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊print-integer screen, 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">def</span> editor-contents editor:address:editor-data<span class="muRecipe"> -&gt; </span>result:text [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  buf:address:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">80</span>
  curr:address:duplex-list:character<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 curr
  <span class="muControl">return-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>
    buf<span class="Special"> &lt;- </span>append buf, c
    curr<span class="Special"> &lt;- </span>next curr
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
  result<span class="Special"> &lt;- </span>buffer-to-array buf
]

<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>:text<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>:text, screen:address:screen, <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:screen, console:address:console, <span class="Constant">2</span>:address:editor-data
    <span class="Constant">3</span>:text<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>:text
  ]
  memory-should-contain [
    <span class="Constant">4</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abdefc]</span>
  ]
]

<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 [
  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="Comment"># initialize sandbox side</span>
  <span class="Constant">1</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
  <span class="Constant">2</span>:text<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>:text, <span class="Constant">2</span>:text
  render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render
  assume-console [
    <span class="Comment"># create a sandbox</span>
    press F4
  ]
  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"> .                                                  ┊add 2, 2                                         .</span>
  ]
  <span class="Comment"># switch to sandbox window and hit 'page-down'</span>
  assume-console [
    press ctrl-n
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <span class="Comment"># sandbox editor hidden; first sandbox displayed</span>
  <span class="Comment"># cursor moves to first sandbox</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊␣   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
  <span class="Comment"># hit 'page-up'</span>
  assume-console [
    press page-up
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <span class="Comment"># sandbox editor displays again, cursor is in editor</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"> .                                                  ┊add 2, 2                                         .</span>
  ]
]

<span class="Comment"># page-down on sandbox side updates render-from to scroll sandboxes</span>
<span class="muRecipe">after</span> <span class="Constant">&lt;global-keypress&gt;</span> [
  <span class="Delimiter">{</span>
    <span class="muControl">break-unless</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?
    sandbox:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
    <span class="muControl">break-unless</span> sandbox
    <span class="Comment"># slide down if possible</span>
    <span class="Delimiter">{</span>
      render-from:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">render-from:offset</span>
      number-of-sandboxes:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">number-of-sandboxes:offset</span>
      max:number<span class="Special"> &lt;- </span>subtract number-of-sandboxes, <span class="Constant">1</span>
      at-end?:boolean<span class="Special"> &lt;- </span>greater-or-equal render-from, max
      <span class="muControl">jump-if</span> at-end?, <span class="Constant">+finish-event:label</span>  <span class="Comment"># render nothing</span>
      render-from<span class="Special"> &lt;- </span>add render-from, <span class="Constant">1</span>
      *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, render
    show-screen screen
    <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
  <span class="Delimiter">}</span>
]

<span class="Comment"># update-cursor takes render-from into account</span>
<span class="muRecipe">after</span> <span class="Constant">&lt;update-cursor-special-cases&gt;</span> [
  <span class="Delimiter">{</span>
    <span class="muControl">break-unless</span> sandbox-in-focus?
    render-from:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">render-from:offset</span>
    scrolling?:boolean<span class="Special"> &lt;- </span>greater-or-equal render-from, <span class="Constant">0</span>
    <span class="muControl">break-unless</span> scrolling?
    cursor-column:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span>
    screen<span class="Special"> &lt;- </span>move-cursor screen, <span class="Constant">2/row</span>, cursor-column  <span class="Comment"># highlighted sandbox will always start at row 2</span>
    <span class="muControl">return</span>
  <span class="Delimiter">}</span>
]

<span class="Comment"># 'page-up' on sandbox side is like 'page-down': updates render-from when necessary</span>
<span class="muRecipe">after</span> <span class="Constant">&lt;global-keypress&gt;</span> [
  <span class="Delimiter">{</span>
    <span class="muControl">break-unless</span> sandbox-in-focus?
    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?
    render-from:number<span class="Special"> &lt;- </span>get *env, <span class="Constant">render-from:offset</span>
    at-beginning?:boolean<span class="Special"> &lt;- </span>equal render-from, <span class="Constant">-1</span>
    <span class="muControl">break-if</span> at-beginning?
    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, render
    show-screen screen
    <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span>
  <span class="Delimiter">}</span>
]

<span class="Comment"># sandbox belonging to 'env' whose next-sandbox is 'in'</span>
<span class="Comment"># return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox</span>
<span class="muRecipe">def</span> previous-sandbox env:address:programming-environment-data, in:address:sandbox-data<span class="muRecipe"> -&gt; </span>out:address:sandbox-data [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  curr:address:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span>
  <span class="muControl">return-unless</span> curr, <span class="Constant">0/nil</span>
  next:address:sandbox-data<span class="Special"> &lt;- </span>get *curr, <span class="Constant">next-sandbox:offset</span>
  <span class="Delimiter">{</span>
    <span class="muControl">return-unless</span> next, <span class="Constant">0/nil</span>
    found?:boolean<span class="Special"> &lt;- </span>equal next, in
    <span class="muControl">break-if</span> found?
    curr<span class="Special"> &lt;- </span>copy next
    next<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">return</span> curr
]

<span class="muScenario">scenario</span> scrolling-down-on-recipe-side [
  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="Comment"># initialize sandbox side and create a sandbox</span>
  <span class="Constant">1</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[ </span>
<span class="Constant">]</span>
  <span class="Comment"># create a sandbox</span>
  <span class="Constant">2</span>:text<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>:text, <span class="Constant">2</span>:text
  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 page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <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"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
  ]
]

<span class="muScenario">scenario</span> scrolling-through-multiple-sandboxes [
  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="Comment"># initialize environment</span>
  <span class="Constant">1</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
  <span class="Constant">2</span>:text<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>:text, <span class="Constant">2</span>:text
  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
    type <span class="Constant">[add 2, 2]</span>
    press F4
    type <span class="Constant">[add 1, 1]</span>
    press F4
  ]
  event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
  print screen:address:screen, <span class="Constant">4</span>:character/cursor
  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"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
  <span class="Comment"># hit 'page-down'</span>
  assume-console [
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <span class="Comment"># sandbox editor hidden; first sandbox displayed</span>
  <span class="Comment"># cursor moves to first sandbox</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊␣   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
  <span class="Comment"># hit 'page-down' again</span>
  assume-console [
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># just second sandbox displayed</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
  <span class="Comment"># hit 'page-down' again</span>
  assume-console [
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># no change</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
  <span class="Comment"># hit 'page-up'</span>
  assume-console [
    press page-up
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># back to displaying both sandboxes without editor</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
  <span class="Comment"># hit 'page-up' again</span>
  assume-console [
    press page-up
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <span class="Comment"># back to displaying both sandboxes as well as editor</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"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
  <span class="Comment"># hit 'page-up' again</span>
  assume-console [
    press page-up
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
    <span class="Constant">4</span>:character/cursor<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    print screen:address:screen, <span class="Constant">4</span>:character/cursor
  ]
  <span class="Comment"># no change</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"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊1   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 2, 2                                         .</span>
   <span class="Constant"> .                                                  ┊4                                                .</span>
  ]
]

<span class="muScenario">scenario</span> scrolling-manages-sandbox-index-correctly [
  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="Comment"># initialize environment</span>
  <span class="Constant">1</span>:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
  <span class="Constant">2</span>:text<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>:text, <span class="Constant">2</span>:text
  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
    type <span class="Constant">[add 1, 1]</span>
    press F4
  ]
  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"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
  <span class="Comment"># hit 'page-down' and 'page-up' a couple of times. sandbox index should be stable</span>
  assume-console [
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># sandbox editor hidden; first sandbox displayed</span>
  <span class="Comment"># cursor moves to first sandbox</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
  <span class="Comment"># hit 'page-up' again</span>
  assume-console [
    press page-up
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># back to displaying both sandboxes as well as editor</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"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
  <span class="Comment"># hit 'page-down'</span>
  assume-console [
    press page-down
  ]
  run [
    event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data
  ]
  <span class="Comment"># sandbox editor hidden; first sandbox displayed</span>
  <span class="Comment"># cursor moves to first sandbox</span>
  screen-should-contain [
   <span class="Constant"> .                                                                                 run (F4)           .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0   edit          copy            delete         .</span>
   <span class="Constant"> .                                                  ┊add 1, 1                                         .</span>
   <span class="Constant"> .                                                  ┊2                                                .</span>
   <span class="Constant"> .                                                  ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span>
   <span class="Constant"> .                                                  ┊                                                 .</span>
  ]
]
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->