about summary refs log blame commit diff stats
path: root/084console.mu
blob: 0ae0f610bf7257a48f347a041fccfcf7e98dd988 (plain) (tree)
1
2
3
4
5
6
7
8

                                                                            
 
                           
           
                                                                  
                                              
                     


                                                              
                       


            

 
                        

            

 
                   
                         
                  

 
                                                           
             
                  
                                      
                                               

 
                                                                                              
             
                  
   
                        
                                                                       
                                                
     
                            
                                                             
                        
                                     
                                                                  
     


                                                                             
                                                                
   
                                                                      
                                                    
                                                             

 


                                                                            
                                                                                           
             
                  
                                                                 

                                                                      
                                                          

                                                                            
 
 
                                                                                                                                       
             
                  
   
                                                                


                                            
                             
                         

        
                    
 
 
                                                           
             
                  
   
                                                 
                      

   

                                                                             
                                                       
             
                  
   
                        
                                                     
                  
   
                              
 
# Wrappers around interaction primitives that take a potentially fake object
# and are thus easier to test.

exclusive-container event [
  text:char
  keycode:num  # keys on keyboard without a unicode representation
  touch:touch-event  # mouse, track ball, etc.
  resize:resize-event
  # update the assume-console handler if you add more variants
]

container touch-event [
  type:num
  row:num
  column:num
]

container resize-event [
  width:num
  height:num
]

container console [
  current-event-index:num
  events:&:@:event
]

def new-fake-console events:&:@:event -> result:&:console [
  local-scope
  load-ingredients
  result:&:console <- new console:type
  *result <- put *result, events:offset, events
]

def read-event console:&:console -> result:event, console:&:console, found?:bool, quit?:bool [
  local-scope
  load-ingredients
  {
    break-unless console
    current-event-index:num <- get *console, current-event-index:offset
    buf:&:@:event <- get *console, events:offset
    {
      max:num <- length *buf
      done?:bool <- greater-or-equal current-event-index, max
      break-unless done?
      dummy:&:event <- new event:type
      return *dummy, console/same-as-ingredient:0, 1/found, 1/quit
    }
    result <- index *buf, current-event-index
    current-event-index <- add current-event-index, 1
    *console <- put *console, current-event-index:offset, current-event-index
    return result, console/same-as-ingredient:0, 1/found, 0/quit
  }
  switch  # real event source is infrequent; avoid polling it too much
  result:event, found?:bool <- check-for-interaction
  return result, console/same-as-ingredient:0, found?, 0/quit
]

# variant of read-event for just keyboard events. Discards everything that
# isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get
# newlines, tabs, ctrl-d..
def read-key console:&:console -> result:char, console:&:console, found?:bool, quit?:bool [
  local-scope
  load-ingredients
  x:event, console, found?:bool, quit?:bool <- read-event console
  return-if quit?, 0, console/same-as-ingredient:0, found?, quit?
  return-unless found?, 0, console/same-as-ingredient:0, found?, quit?
  c:char, converted?:bool <- maybe-convert x, text:variant
  return-unless converted?, 0, console/same-as-ingredient:0, 0/found, 0/quit
  return c, console/same-as-ingredient:0, 1/found, 0/quit
]

def send-keys-to-channel console:&:console, chan:&:sink:char, screen:&:screen -> console:&:console, chan:&:sink:char, screen:&:screen [
  local-scope
  load-ingredients
  {
    c:char, console, found?:bool, quit?:bool <- read-key console
    loop-unless found?
    break-if quit?
    assert c, [invalid event, expected text]
    screen <- print screen, c
    chan <- write chan, c
    loop
  }
  chan <- close chan
]

def wait-for-event console:&:console -> console:&:console [
  local-scope
  load-ingredients
  {
    _, console, found?:bool <- read-event console
    loop-unless found?
  }
]

# use this helper to skip rendering if there's lots of other events queued up
def has-more-events? console:&:console -> result:bool [
  local-scope
  load-ingredients
  {
    break-unless console
    # fake consoles should be plenty fast; never skip
    return 0/false
  }
  result <- interactions-left?
]