about summary refs log blame commit diff stats
path: root/html/edit/002-typing.mu.html
blob: c651168ac952505ba77f30099c74376db52b8bb1 (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/002-typing.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; }
.Delimiter { color: #800080; }
.muControl { color: #c0a020; }
.Special { color: #c00000; }
.muData { color: #ffff00; }
.Comment { color: #9090ff; }
.Constant { color: #00a0a0; }
.SalientComment { color: #00ffff; }
.muRecipe { color: #ff8700; }
.muScenario { color: #00af00; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span>

<span class="Comment"># temporary main: interactive editor</span>
<span class="Comment"># hit ctrl-c to exit</span>
<span class="muRecipe">def!</span> main text:text [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  open-console
  editor:&amp;:editor <span class="Special">&lt;-</span> new-editor text, <span class="Constant">5/left</span>, <span class="Constant">45/right</span>
  editor-event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, editor
  close-console
]

<span class="muRecipe">def</span> editor-event-loop screen:&amp;:screen, console:&amp;:console, editor:&amp;:editor<span class="muRecipe"> -&gt; </span>screen:&amp;:screen, console:&amp;:console, editor:&amp;:editor [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="Delimiter">{</span>
    <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span>
<span class="Constant">    +next-event</span>
    cursor-row:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-row:offset</span>
    cursor-column:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-column:offset</span>
    screen <span class="Special">&lt;-</span> move-cursor screen, cursor-row, cursor-column
    e:event, found?:bool, quit?:bool, console <span class="Special">&lt;-</span> read-event console
    <span class="muControl">loop-unless</span> found?
    <span class="muControl">break-if</span> quit?  <span class="Comment"># only in tests</span>
    trace<span class="Constant"> 10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
    <span class="Comment"># 'touch' event</span>
    t:touch-event, is-touch?:bool <span class="Special">&lt;-</span> maybe-convert e, <span class="Constant">touch:variant</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-unless</span> is-touch?
      move-cursor-in-editor screen, editor, t
      <span class="muControl">loop</span> <span class="Constant">+next-event</span>
    <span class="Delimiter">}</span>
    <span class="Comment"># keyboard events</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-if</span> is-touch?
      go-render?:bool <span class="Special">&lt;-</span> handle-keyboard-event screen, editor, e
      <span class="Delimiter">{</span>
        <span class="muControl">break-unless</span> go-render?
        screen <span class="Special">&lt;-</span> editor-render screen, editor
      <span class="Delimiter">}</span>
    <span class="Delimiter">}</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="Comment"># process click, return if it was on current editor</span>
<span class="muRecipe">def</span> move-cursor-in-editor screen:&amp;:screen, editor:&amp;:editor, t:touch-event<span class="muRecipe"> -&gt; </span>in-focus?:bool, editor:&amp;:editor [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="muControl">return-unless</span> editor, <span class="Constant">0/false</span>
  click-row:num <span class="Special">&lt;-</span> get t, <span class="Constant">row:offset</span>
  <span class="muControl">return-unless</span> click-row, <span class="Constant">0/false</span>  <span class="Comment"># ignore clicks on 'menu'</span>
  click-column:num <span class="Special">&lt;-</span> get t, <span class="Constant">column:offset</span>
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  too-far-left?:bool <span class="Special">&lt;-</span> lesser-than click-column, left
  <span class="muControl">return-if</span> too-far-left?, <span class="Constant">0/false</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  too-far-right?:bool <span class="Special">&lt;-</span> greater-than click-column, right
  <span class="muControl">return-if</span> too-far-right?, <span class="Constant">0/false</span>
  <span class="Comment"># position cursor</span>
<span class="Constant">  &lt;move-cursor-begin&gt;</span>
  editor <span class="Special">&lt;-</span> snap-cursor screen, editor, click-row, click-column
  undo-coalesce-tag:num <span class="Special">&lt;-</span> copy <span class="Constant">0/never</span>
<span class="Constant">  &lt;move-cursor-end&gt;</span>
  <span class="Comment"># gain focus</span>
  <span class="muControl">return</span> <span class="Constant">1/true</span>
]

<span class="Comment"># Variant of 'render' that only moves the cursor (coordinates and</span>
<span class="Comment"># before-cursor). If it's past the end of a line, it 'slides' it left. If it's</span>
<span class="Comment"># past the last line it positions at end of last line.</span>
<span class="muRecipe">def</span> snap-cursor screen:&amp;:screen, editor:&amp;:editor, target-row:num, target-column:num<span class="muRecipe"> -&gt; </span>editor:&amp;:editor [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="muControl">return-unless</span> editor
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  screen-height:num <span class="Special">&lt;-</span> screen-height screen
  <span class="Comment"># count newlines until screen row</span>
  curr:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">top-of-screen:offset</span>
  prev:&amp;:duplex-list:char <span class="Special">&lt;-</span> copy curr  <span class="Comment"># just in case curr becomes null and we can't compute prev</span>
  curr <span class="Special">&lt;-</span> next curr
  row:num <span class="Special">&lt;-</span> copy <span class="Constant">1/top</span>
  column:num <span class="Special">&lt;-</span> copy left
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-row:offset</span>, target-row
  cursor-row:num <span class="Special">&lt;-</span> copy target-row
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, target-column
  cursor-column:num <span class="Special">&lt;-</span> copy target-column
  before-cursor:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">before-cursor:offset</span>
  <span class="Delimiter">{</span>
<span class="Constant">    +next-character</span>
    <span class="muControl">break-unless</span> curr
    off-screen?:bool <span class="Special">&lt;-</span> greater-or-equal row, screen-height
    <span class="muControl">break-if</span> off-screen?
    <span class="Comment"># update editor.before-cursor</span>
    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
    <span class="Comment"># the current character.</span>
    <span class="Delimiter">{</span>
      at-cursor-row?:bool <span class="Special">&lt;-</span> equal row, cursor-row
      <span class="muControl">break-unless</span> at-cursor-row?
      at-cursor?:bool <span class="Special">&lt;-</span> equal column, cursor-column
      <span class="muControl">break-unless</span> at-cursor?
      before-cursor <span class="Special">&lt;-</span> copy prev
      *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
    <span class="Delimiter">}</span>
    c:char <span class="Special">&lt;-</span> get *curr, <span class="Constant">value:offset</span>
    <span class="Delimiter">{</span>
      <span class="Comment"># newline? move to left rather than 0</span>
      newline?:bool <span class="Special">&lt;-</span> equal c, <span class="Constant">10/newline</span>
      <span class="muControl">break-unless</span> newline?
      <span class="Comment"># adjust cursor if necessary</span>
      <span class="Delimiter">{</span>
        at-cursor-row?:bool <span class="Special">&lt;-</span> equal row, cursor-row
        <span class="muControl">break-unless</span> at-cursor-row?
        left-of-cursor?:bool <span class="Special">&lt;-</span> lesser-than column, cursor-column
        <span class="muControl">break-unless</span> left-of-cursor?
        cursor-column <span class="Special">&lt;-</span> copy column
        *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
        before-cursor <span class="Special">&lt;-</span> copy prev
        *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
      <span class="Delimiter">}</span>
      <span class="Comment"># skip to next line</span>
      row <span class="Special">&lt;-</span> add row,<span class="Constant"> 1</span>
      column <span class="Special">&lt;-</span> copy left
      curr <span class="Special">&lt;-</span> next curr
      prev <span class="Special">&lt;-</span> next prev
      <span class="muControl">loop</span> <span class="Constant">+next-character</span>
    <span class="Delimiter">}</span>
    <span class="Delimiter">{</span>
      <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span>
      <span class="Comment"># room for clicking on the cursor after it.</span>
      at-right?:bool <span class="Special">&lt;-</span> equal column, right
      <span class="muControl">break-unless</span> at-right?
      column <span class="Special">&lt;-</span> copy left
      row <span class="Special">&lt;-</span> add row,<span class="Constant"> 1</span>
      <span class="Comment"># don't increment curr/prev</span>
      <span class="muControl">loop</span> <span class="Constant">+next-character</span>
    <span class="Delimiter">}</span>
    curr <span class="Special">&lt;-</span> next curr
    prev <span class="Special">&lt;-</span> next prev
    column <span class="Special">&lt;-</span> add column,<span class="Constant"> 1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
  <span class="Comment"># is cursor to the right of the last line? move to end</span>
  <span class="Delimiter">{</span>
    at-cursor-row?:bool <span class="Special">&lt;-</span> equal row, cursor-row
    cursor-outside-line?:bool <span class="Special">&lt;-</span> lesser-or-equal column, cursor-column
    before-cursor-on-same-line?:bool <span class="Special">&lt;-</span> and at-cursor-row?, cursor-outside-line?
    above-cursor-row?:bool <span class="Special">&lt;-</span> lesser-than row, cursor-row
    before-cursor?:bool <span class="Special">&lt;-</span> or before-cursor-on-same-line?, above-cursor-row?
    <span class="muControl">break-unless</span> before-cursor?
    cursor-row <span class="Special">&lt;-</span> copy row
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
    cursor-column <span class="Special">&lt;-</span> copy column
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
    before-cursor <span class="Special">&lt;-</span> copy prev
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
  <span class="Delimiter">}</span>
]

<span class="Comment"># Process an event 'e' and try to minimally update the screen.</span>
<span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span>
<span class="muRecipe">def</span> handle-keyboard-event screen:&amp;:screen, editor:&amp;:editor, e:event<span class="muRecipe"> -&gt; </span>go-render?:bool, screen:&amp;:screen, editor:&amp;:editor [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="muControl">return-unless</span> editor, <span class="Constant">0/don't-render</span>
  screen-width:num <span class="Special">&lt;-</span> screen-width screen
  screen-height:num <span class="Special">&lt;-</span> screen-height screen
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  before-cursor:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">before-cursor:offset</span>
  cursor-row:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-row:offset</span>
  cursor-column:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-column:offset</span>
  save-row:num <span class="Special">&lt;-</span> copy cursor-row
  save-column:num <span class="Special">&lt;-</span> copy cursor-column
  <span class="Comment"># character</span>
  <span class="Delimiter">{</span>
    c:char, is-unicode?:bool <span class="Special">&lt;-</span> maybe-convert e, <span class="Constant">text:variant</span>
    <span class="muControl">break-unless</span> is-unicode?
    trace<span class="Constant"> 10</span>, <span class="Constant">[app]</span>, <span class="Constant">[handle-keyboard-event: special character]</span>
    <span class="Comment"># exceptions for special characters go here</span>
<span class="Constant">    &lt;handle-special-character&gt;</span>
    <span class="Comment"># ignore any other special characters</span>
    regular-character?:bool <span class="Special">&lt;-</span> greater-or-equal c, <span class="Constant">32/space</span>
    <span class="muControl">return-unless</span> regular-character?, <span class="Constant">0/don't-render</span>
    <span class="Comment"># otherwise type it in</span>
<span class="Constant">    &lt;insert-character-begin&gt;</span>
    go-render? <span class="Special">&lt;-</span> insert-at-cursor editor, c, screen
<span class="Constant">    &lt;insert-character-end&gt;</span>
    <span class="muControl">return</span>
  <span class="Delimiter">}</span>
  <span class="Comment"># special key to modify the text or move the cursor</span>
  k:num, is-keycode?:bool <span class="Special">&lt;-</span> maybe-convert e:event, <span class="Constant">keycode:variant</span>
  assert is-keycode?, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
  <span class="Comment"># handlers for each special key will go here</span>
<span class="Constant">  &lt;handle-special-key&gt;</span>
  <span class="muControl">return</span> <span class="Constant">1/go-render</span>
]

<span class="muRecipe">def</span> insert-at-cursor editor:&amp;:editor, c:char, screen:&amp;:screen<span class="muRecipe"> -&gt; </span>go-render?:bool, editor:&amp;:editor, screen:&amp;:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  before-cursor:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">before-cursor:offset</span>
  insert c, before-cursor
  before-cursor <span class="Special">&lt;-</span> next before-cursor
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
  cursor-row:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-row:offset</span>
  cursor-column:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-column:offset</span>
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  save-row:num <span class="Special">&lt;-</span> copy cursor-row
  save-column:num <span class="Special">&lt;-</span> copy cursor-column
  screen-width:num <span class="Special">&lt;-</span> screen-width screen
  screen-height:num <span class="Special">&lt;-</span> screen-height screen
  <span class="Comment"># occasionally we'll need to mess with the cursor</span>
<span class="Constant">  &lt;insert-character-special-case&gt;</span>
  <span class="Comment"># but mostly we'll just move the cursor right</span>
  cursor-column <span class="Special">&lt;-</span> add cursor-column,<span class="Constant"> 1</span>
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
  next:&amp;:duplex-list:char <span class="Special">&lt;-</span> next before-cursor
  <span class="Delimiter">{</span>
    <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span>
    at-end?:bool <span class="Special">&lt;-</span> equal next, <span class="Constant">0/null</span>
    <span class="muControl">break-unless</span> at-end?
    bottom:num <span class="Special">&lt;-</span> subtract screen-height,<span class="Constant"> 1</span>
    at-bottom?:bool <span class="Special">&lt;-</span> equal save-row, bottom
    at-right?:bool <span class="Special">&lt;-</span> equal save-column, right
    overflow?:bool <span class="Special">&lt;-</span> and at-bottom?, at-right?
    <span class="muControl">break-if</span> overflow?
    move-cursor screen, save-row, save-column
    print screen, c
    <span class="muControl">return</span> <span class="Constant">0/don't-render</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    <span class="Comment"># not at right margin? print the character and rest of line</span>
    <span class="muControl">break-unless</span> next
    at-right?:bool <span class="Special">&lt;-</span> greater-or-equal cursor-column, screen-width
    <span class="muControl">break-if</span> at-right?
    curr:&amp;:duplex-list:char <span class="Special">&lt;-</span> copy before-cursor
    move-cursor screen, save-row, save-column
    curr-column:num <span class="Special">&lt;-</span> copy save-column
    <span class="Delimiter">{</span>
      <span class="Comment"># hit right margin? give up and let caller render</span>
      at-right?:bool <span class="Special">&lt;-</span> greater-than curr-column, right
      <span class="muControl">return-if</span> at-right?, <span class="Constant">1/go-render</span>
      <span class="muControl">break-unless</span> curr
      <span class="Comment"># newline? done.</span>
      currc:char <span class="Special">&lt;-</span> get *curr, <span class="Constant">value:offset</span>
      at-newline?:bool <span class="Special">&lt;-</span> equal currc, <span class="Constant">10/newline</span>
      <span class="muControl">break-if</span> at-newline?
      print screen, currc
      curr-column <span class="Special">&lt;-</span> add curr-column,<span class="Constant"> 1</span>
      curr <span class="Special">&lt;-</span> next curr
      <span class="muControl">loop</span>
    <span class="Delimiter">}</span>
    <span class="muControl">return</span> <span class="Constant">0/don't-render</span>
  <span class="Delimiter">}</span>
  <span class="muControl">return</span> <span class="Constant">1/go-render</span>
]

<span class="Comment"># helper for tests</span>
<span class="muRecipe">def</span> editor-render screen:&amp;:screen, editor:&amp;:editor<span class="muRecipe"> -&gt; </span>screen:&amp;:screen, editor:&amp;:editor [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  row:num, column:num <span class="Special">&lt;-</span> render screen, editor
  clear-line-until screen, right
  row <span class="Special">&lt;-</span> add row,<span class="Constant"> 1</span>
  draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span>
  row <span class="Special">&lt;-</span> add row,<span class="Constant"> 1</span>
  clear-screen-from screen, row, left, left, right
]

<span class="muScenario">scenario</span> editor-handles-empty-event-queue [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  assume-console <span class="Constant">[]</span>
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 1</span>  <span class="Comment"># on the 'b'</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>  <span class="Comment"># cursor is at row 0..</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>  <span class="Comment"># ..and column 1</span>
  ]
  check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 7</span>  <span class="Comment"># last line, to the right of text</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor column</span>
  ]
  check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">def]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 7</span>  <span class="Comment"># interior line, to the right of text</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor column</span>
  ]
  check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">def]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 7</span>  <span class="Comment"># below text</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 2</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor column</span>
  ]
  check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  <span class="Comment"># editor occupies only left half of screen</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    <span class="Comment"># click on right half of screen</span>
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 8</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>  <span class="Comment"># no change to cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 0</span>  <span class="Comment"># ..or column</span>
  ]
  check-trace-count-for-label<span class="Constant"> 0</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-handles-mouse-clicks-in-menu-area [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    <span class="Comment"># click on first, 'menu' row</span>
    left-click<span class="Constant"> 0</span>,<span class="Constant"> 3</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  <span class="Comment"># no change to cursor</span>
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 1</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 0</span>
  ]
]

<span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    type <span class="Constant">[abc]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 3</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  <span class="Comment"># type two letters at different places</span>
  assume-console [
    type <span class="Constant">[0]</span>
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 2</span>
    type <span class="Constant">[d]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .0adbc     .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 7</span>, <span class="Constant">[print-character]</span>  <span class="Comment"># 4 for first letter, 3 for second</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 5</span>  <span class="Comment"># right of last line</span>
    type <span class="Constant">[d]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd      .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">d]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 5</span>  <span class="Comment"># right of non-last line</span>
    type <span class="Constant">[e]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abce      .</span>
   <span class="Constant"> .d         .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 5</span>  <span class="Comment"># below all text</span>
    type <span class="Constant">[d]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd      .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">d]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 5</span>  <span class="Comment"># below all text</span>
    type <span class="Constant">[e]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
   <span class="Constant"> .de        .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 1</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">d]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  editor-render screen, e
  $clear-trace
  assume-console [
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 5</span>  <span class="Comment"># below all text</span>
    type <span class="Constant">[ef]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
   <span class="Constant"> .def       .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
  check-trace-count-for-label<span class="Constant"> 2</span>, <span class="Constant">[print-character]</span>
]

<span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[ab]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  assume-console [
    type <span class="Constant">[01]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .01ab      .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
]

<span class="Comment"># if the cursor reaches the right margin, wrap the line</span>

<span class="muScenario">scenario</span> editor-wraps-line-on-insert [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  <span class="Comment"># type a letter</span>
  assume-console [
    type <span class="Constant">[e]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  <span class="Comment"># no wrap yet</span>
  screen-should-contain [
   <span class="Constant"> .     .</span>
   <span class="Constant"> .eabc .</span>
<span class="Constant">    .╌╌╌╌╌.</span>
   <span class="Constant"> .     .</span>
   <span class="Constant"> .     .</span>
  ]
  <span class="Comment"># type a second letter</span>
  assume-console [
    type <span class="Constant">[f]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  <span class="Comment"># now wrap</span>
  screen-should-contain [
   <span class="Constant"> .     .</span>
<span class="Constant">    .efab↩.</span>
   <span class="Constant"> .c    .</span>
<span class="Constant">    .╌╌╌╌╌.</span>
   <span class="Constant"> .     .</span>
  ]
]

<span class="muScenario">scenario</span> editor-wraps-line-on-insert-2 [
  <span class="Constant">local-scope</span>
  <span class="Comment"># create an editor with some text</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abcdefg</span>
<span class="Constant">defg]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  <span class="Comment"># type more text at the start</span>
  assume-console [
    left-click<span class="Constant"> 3</span>,<span class="Constant"> 0</span>
    type <span class="Constant">[abc]</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  <span class="Comment"># cursor is not wrapped</span>
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>
  ]
  <span class="Comment"># but line is wrapped</span>
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd↩     .</span>
   <span class="Constant"> .efg       .</span>
   <span class="Constant"> .abcd↩     .</span>
   <span class="Constant"> .efg       .</span>
  ]
]

<span class="muRecipe">after</span> <span class="Constant">&lt;insert-character-special-case&gt;</span> [
  <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span>
  <span class="Delimiter">{</span>
    <span class="Comment"># if either:</span>
    <span class="Comment"># a) we're at the end of the line and at the column of the wrap indicator, or</span>
    <span class="Comment"># b) we're not at end of line and just before the column of the wrap indicator</span>
    wrap-column:num <span class="Special">&lt;-</span> copy right
    before-wrap-column:num <span class="Special">&lt;-</span> subtract wrap-column,<span class="Constant"> 1</span>
    at-wrap?:bool <span class="Special">&lt;-</span> greater-or-equal cursor-column, wrap-column
    just-before-wrap?:bool <span class="Special">&lt;-</span> greater-or-equal cursor-column, before-wrap-column
    next:&amp;:duplex-list:char <span class="Special">&lt;-</span> next before-cursor
    <span class="Comment"># at end of line? next == 0 || next.value == 10/newline</span>
    at-end-of-line?:bool <span class="Special">&lt;-</span> equal next,<span class="Constant"> 0</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-if</span> at-end-of-line?
      next-character:char <span class="Special">&lt;-</span> get *next, <span class="Constant">value:offset</span>
      at-end-of-line? <span class="Special">&lt;-</span> equal next-character, <span class="Constant">10/newline</span>
    <span class="Delimiter">}</span>
    <span class="Comment"># break unless ((eol? and at-wrap?) or (~eol? and just-before-wrap?))</span>
    move-cursor-to-next-line?:bool <span class="Special">&lt;-</span> copy <span class="Constant">0/false</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-if</span> at-end-of-line?
      move-cursor-to-next-line? <span class="Special">&lt;-</span> copy just-before-wrap?
      <span class="Comment"># if we're moving the cursor because it's in the middle of a wrapping</span>
      <span class="Comment"># line, adjust it to left-most column</span>
      potential-new-cursor-column:num <span class="Special">&lt;-</span> copy left
    <span class="Delimiter">}</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-unless</span> at-end-of-line?
      move-cursor-to-next-line? <span class="Special">&lt;-</span> copy at-wrap?
      <span class="Comment"># if we're moving the cursor because it's at the end of a wrapping line,</span>
      <span class="Comment"># adjust it to one past the left-most column to make room for the</span>
      <span class="Comment"># newly-inserted wrap-indicator</span>
      potential-new-cursor-column:num <span class="Special">&lt;-</span> add left, <span class="Constant">1/make-room-for-wrap-indicator</span>
    <span class="Delimiter">}</span>
    <span class="muControl">break-unless</span> move-cursor-to-next-line?
    cursor-column <span class="Special">&lt;-</span> copy potential-new-cursor-column
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
    cursor-row <span class="Special">&lt;-</span> add cursor-row,<span class="Constant"> 1</span>
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
    <span class="Comment"># if we're out of the screen, scroll down</span>
    <span class="Delimiter">{</span>
      below-screen?:bool <span class="Special">&lt;-</span> greater-or-equal cursor-row, screen-height
      <span class="muControl">break-unless</span> below-screen?
<span class="Constant">      &lt;scroll-down&gt;</span>
    <span class="Delimiter">}</span>
    <span class="muControl">return</span> <span class="Constant">1/go-render</span>
  <span class="Delimiter">}</span>
]

<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-in-middle-of-line [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abcde]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 3</span>  <span class="Comment"># right before the wrap icon</span>
    type <span class="Constant">[f]</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcf↩     .</span>
   <span class="Constant"> .de        .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 2</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 0</span>  <span class="Comment"># cursor column</span>
  ]
]

<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-at-end-of-line [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  <span class="Comment"># create an editor containing two lines</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[abc</span>
<span class="Constant">xyz]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abc       .</span>
   <span class="Constant"> .xyz       .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 4</span>  <span class="Comment"># at end of first line</span>
    type <span class="Constant">[de]</span>  <span class="Comment"># trigger wrap</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd↩     .</span>
   <span class="Constant"> .e         .</span>
   <span class="Constant"> .xyz       .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
  ]
]

<span class="muScenario">scenario</span> editor-wraps-cursor-to-left-margin [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abcde]</span>, <span class="Constant">2/left</span>, <span class="Constant">7/right</span>
  assume-console [
    left-click<span class="Constant"> 1</span>,<span class="Constant"> 5</span>  <span class="Comment"># line is full; no wrap icon yet</span>
    type <span class="Constant">[01]</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .  abc0↩   .</span>
   <span class="Constant"> .  1de     .</span>
   <span class="Constant"> .  ╌╌╌╌╌   .</span>
   <span class="Constant"> .          .</span>
  ]
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 2</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor column</span>
  ]
]

<span class="Comment"># if newline, move cursor to start of next line, and maybe align indent with previous line</span>

<span class="muData">container</span> editor [
  indent?:bool
]

<span class="muRecipe">after</span> <span class="Constant">&lt;editor-initialization&gt;</span> [
  *result <span class="Special">&lt;-</span> put *result, <span class="Constant">indent?:offset</span>, <span class="Constant">1/true</span>
]

<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  assume-console [
    type <span class="Constant">[0</span>
<span class="Constant">1]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .0         .</span>
   <span class="Constant"> .1abc      .</span>
<span class="Constant">    .╌╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
]

<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-character&gt;</span> [
  <span class="Delimiter">{</span>
    newline?:bool <span class="Special">&lt;-</span> equal c, <span class="Constant">10/newline</span>
    <span class="muControl">break-unless</span> newline?
<span class="Constant">    &lt;insert-enter-begin&gt;</span>
    insert-new-line-and-indent editor, screen
<span class="Constant">    &lt;insert-enter-end&gt;</span>
    <span class="muControl">return</span> <span class="Constant">1/go-render</span>
  <span class="Delimiter">}</span>
]

<span class="muRecipe">def</span> insert-new-line-and-indent editor:&amp;:editor, screen:&amp;:screen<span class="muRecipe"> -&gt; </span>editor:&amp;:editor, screen:&amp;:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  cursor-row:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-row:offset</span>
  cursor-column:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">cursor-column:offset</span>
  before-cursor:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">before-cursor:offset</span>
  left:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">left:offset</span>
  right:num <span class="Special">&lt;-</span> get *editor, <span class="Constant">right:offset</span>
  screen-height:num <span class="Special">&lt;-</span> screen-height screen
  <span class="Comment"># insert newline</span>
  insert <span class="Constant">10/newline</span>, before-cursor
  before-cursor <span class="Special">&lt;-</span> next before-cursor
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">before-cursor:offset</span>, before-cursor
  cursor-row <span class="Special">&lt;-</span> add cursor-row,<span class="Constant"> 1</span>
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
  cursor-column <span class="Special">&lt;-</span> copy left
  *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column
  <span class="Comment"># maybe scroll</span>
  <span class="Delimiter">{</span>
    below-screen?:bool <span class="Special">&lt;-</span> greater-or-equal cursor-row, screen-height  <span class="Comment"># must be equal, never greater</span>
    <span class="muControl">break-unless</span> below-screen?
<span class="Constant">    &lt;scroll-down&gt;</span>
    cursor-row <span class="Special">&lt;-</span> subtract cursor-row,<span class="Constant"> 1</span>  <span class="Comment"># bring back into screen range</span>
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row
  <span class="Delimiter">}</span>
  <span class="Comment"># indent if necessary</span>
  indent?:bool <span class="Special">&lt;-</span> get *editor, <span class="Constant">indent?:offset</span>
  <span class="muControl">return-unless</span> indent?
  d:&amp;:duplex-list:char <span class="Special">&lt;-</span> get *editor, <span class="Constant">data:offset</span>
  end-of-previous-line:&amp;:duplex-list:char <span class="Special">&lt;-</span> prev before-cursor
  indent:num <span class="Special">&lt;-</span> line-indent end-of-previous-line, d
  i:num <span class="Special">&lt;-</span> copy<span class="Constant"> 0</span>
  <span class="Delimiter">{</span>
    indent-done?:bool <span class="Special">&lt;-</span> greater-or-equal i, indent
    <span class="muControl">break-if</span> indent-done?
    insert-at-cursor editor, <span class="Constant">32/space</span>, screen
    i <span class="Special">&lt;-</span> add i,<span class="Constant"> 1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
<span class="Comment"># the number of spaces at the start of the line containing 'curr'.</span>
<span class="muRecipe">def</span> line-indent curr:&amp;:duplex-list:char, start:&amp;:duplex-list:char<span class="muRecipe"> -&gt; </span>result:num [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  result:num <span class="Special">&lt;-</span> copy<span class="Constant"> 0</span>
  <span class="muControl">return-unless</span> curr
  at-start?:bool <span class="Special">&lt;-</span> equal curr, start
  <span class="muControl">return-if</span> at-start?
  <span class="Delimiter">{</span>
    curr <span class="Special">&lt;-</span> prev curr
    <span class="muControl">break-unless</span> curr
    at-start?:bool <span class="Special">&lt;-</span> equal curr, start
    <span class="muControl">break-if</span> at-start?
    c:char <span class="Special">&lt;-</span> get *curr, <span class="Constant">value:offset</span>
    at-newline?:bool <span class="Special">&lt;-</span> equal c, <span class="Constant">10/newline</span>
    <span class="muControl">break-if</span> at-newline?
    <span class="Comment"># if c is a space, increment result</span>
    is-space?:bool <span class="Special">&lt;-</span> equal c, <span class="Constant">32/space</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-unless</span> is-space?
      result <span class="Special">&lt;-</span> add result,<span class="Constant"> 1</span>
    <span class="Delimiter">}</span>
    <span class="Comment"># if c is not a space, reset result</span>
    <span class="Delimiter">{</span>
      <span class="muControl">break-if</span> is-space?
      result <span class="Special">&lt;-</span> copy<span class="Constant"> 0</span>
    <span class="Delimiter">}</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abc]</span>, <span class="Constant">1/left</span>, <span class="Constant">10/right</span>
  assume-console [
    type <span class="Constant">[0</span>
<span class="Constant">1]</span>
  ]
  run [
    editor-event-loop screen, console, e
  ]
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> . 0        .</span>
   <span class="Constant"> . 1abc     .</span>
   <span class="Constant"> . ╌╌╌╌╌╌╌╌╌.</span>
   <span class="Constant"> .          .</span>
  ]
]

<span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor <span class="Constant">[abcde]</span>, <span class="Constant">0/left</span>, <span class="Constant">5/right</span>
  editor-render screen, e
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd↩     .</span>
   <span class="Constant"> .e         .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
   <span class="Constant"> .          .</span>
  ]
  assume-console [
    press enter
  ]
  run [
    editor-event-loop screen, console, e
  ]
  <span class="Comment"># line should be fully cleared</span>
  screen-should-contain [
   <span class="Constant"> .          .</span>
   <span class="Constant"> .          .</span>
   <span class="Constant"> .abcd↩     .</span>
   <span class="Constant"> .e         .</span>
   <span class="Constant"> .╌╌╌╌╌     .</span>
  ]
]

<span class="muScenario">scenario</span> editor-inserts-indent-after-newline [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[ab</span>
<span class="Constant">  cd</span>
<span class="Constant">ef]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  <span class="Comment"># position cursor after 'cd' and hit 'newline'</span>
  assume-console [
    left-click<span class="Constant"> 2</span>,<span class="Constant"> 8</span>
    type [
]
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  <span class="Comment"># cursor should be below start of previous line</span>
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 2</span>  <span class="Comment"># cursor column (indented)</span>
  ]
]

<span class="muScenario">scenario</span> editor-skips-indent-around-paste [
  <span class="Constant">local-scope</span>
  assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span>
  s:text <span class="Special">&lt;-</span> new <span class="Constant">[ab</span>
<span class="Constant">  cd</span>
<span class="Constant">ef]</span>
  e:&amp;:editor <span class="Special">&lt;-</span> new-editor s, <span class="Constant">0/left</span>, <span class="Constant">10/right</span>
  <span class="Comment"># position cursor after 'cd' and hit 'newline' surrounded by paste markers</span>
  assume-console [
    left-click<span class="Constant"> 2</span>,<span class="Constant"> 8</span>
    press<span class="Constant"> 65507</span>  <span class="Comment"># start paste</span>
    press enter
    press<span class="Constant"> 65506</span>  <span class="Comment"># end paste</span>
  ]
  run [
    editor-event-loop screen, console, e
    3:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-row:offset</span>
    4:num/<span class="Special">raw</span> <span class="Special">&lt;-</span> get *e, <span class="Constant">cursor-column:offset</span>
  ]
  <span class="Comment"># cursor should be below start of previous line</span>
  memory-should-contain [
   <span class="Constant"> 3</span> <span class="Special">&lt;-</span><span class="Constant"> 3</span>  <span class="Comment"># cursor row</span>
   <span class="Constant"> 4</span> <span class="Special">&lt;-</span><span class="Constant"> 0</span>  <span class="Comment"># cursor column (not indented)</span>
  ]
]

<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
  <span class="Delimiter">{</span>
    paste-start?:bool <span class="Special">&lt;-</span> equal k, <span class="Constant">65507/paste-start</span>
    <span class="muControl">break-unless</span> paste-start?
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">indent?:offset</span>, <span class="Constant">0/false</span>
    <span class="muControl">return</span> <span class="Constant">1/go-render</span>
  <span class="Delimiter">}</span>
]

<span class="muRecipe">after</span> <span class="Constant">&lt;handle-special-key&gt;</span> [
  <span class="Delimiter">{</span>
    paste-end?:bool <span class="Special">&lt;-</span> equal k, <span class="Constant">65506/paste-end</span>
    <span class="muControl">break-unless</span> paste-end?
    *editor <span class="Special">&lt;-</span> put *editor, <span class="Constant">indent?:offset</span>, <span class="Constant">1/true</span>
    <span class="muControl">return</span> <span class="Constant">1/go-render</span>
  <span class="Delimiter">}</span>
]

<span class="SalientComment">## helpers</span>

<span class="muRecipe">def</span> draw-horizontal screen:&amp;:screen, row:num, x:num, right:num<span class="muRecipe"> -&gt; </span>screen:&amp;:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  style:char, style-found?:bool <span class="Special">&lt;-</span> <span class="Constant">next-ingredient</span>
  <span class="Delimiter">{</span>
    <span class="muControl">break-if</span> style-found?
    style <span class="Special">&lt;-</span> copy <span class="Constant">9472/horizontal</span>
  <span class="Delimiter">}</span>
  color:num, color-found?:bool <span class="Special">&lt;-</span> <span class="Constant">next-ingredient</span>
  <span class="Delimiter">{</span>
    <span class="Comment"># default color to white</span>
    <span class="muControl">break-if</span> color-found?
    color <span class="Special">&lt;-</span> copy <span class="Constant">245/grey</span>
  <span class="Delimiter">}</span>
  bg-color:num, bg-color-found?:bool <span class="Special">&lt;-</span> <span class="Constant">next-ingredient</span>
  <span class="Delimiter">{</span>
    <span class="muControl">break-if</span> bg-color-found?
    bg-color <span class="Special">&lt;-</span> copy <span class="Constant">0/black</span>
  <span class="Delimiter">}</span>
  screen <span class="Special">&lt;-</span> move-cursor screen, row, x
  <span class="Delimiter">{</span>
    continue?:bool <span class="Special">&lt;-</span> lesser-or-equal x, right  <span class="Comment"># right is inclusive, to match editor semantics</span>
    <span class="muControl">break-unless</span> continue?
    print screen, style, color, bg-color
    x <span class="Special">&lt;-</span> add x,<span class="Constant"> 1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->