Skip to content
EricGebhart edited this page Sep 27, 2021 · 8 revisions

With

The with construct in SPR is a bit like a let in lisp or a where in Haskell.

I think of it as a flashlight that I can shine around in the data store tree.

With is also a stack, which by default will be searched for parameter resolution when calling functions.

The with stack is just a list of paths, They should all begin with /. The variable /with_path points to the current with stack. This makes it possible to use ~/with_path for any operations on the current with stack. The default is /with. But it is possible to move it to other places, or swap them, since they are just SPR lists. They can be defined in yaml.

Giving with a list instead of a pathname will result in a complete replacement of the with stack. The dedupwith function uses that functionality.

  • with foo Will push the path /foo onto the with stack

  • pop-with. Will pop the current with.

  • pop ~/_with_path_. Will also pop the current with.

  • with foo <somefunction> Will push /foo, evaluate the function, then pop.

  • with foo <somefunction> some/path Will push /foo, evaluate the function, pop the result to some/path and then pop. The usual path prefix rules, of '/' and '.' apply. A '.' indicates to pop the result into that symbol in the invoking with path. A '/' is an absolute path. A symbol without a prefix will be created in the excursion with and left there.

  • with Will show the path and listing of the current with.

  • with <list> will replace the current with stack with .

  • as/show-with will show the entire with stack as a list of data trees.

  • ls ~/_with_path_ will also show the current with stack.

  • show will show the current with tree.

SPR will automatically bind python function parameters to their corresponding values from within the with. When parameters are provided, SPR will use those provided as their positional parameters, and will still build a kwargs map from the with if it has more to fill in.

Any inline YAML will automatically merge into the datastore tree at the current with location.

This means that it's super easy to add data where you are.

'
msg: This is my new message.

If a function has a return value, it will be pushed onto a results stack within the with. To move the results somewhere/else pop results somewhere/else

Paths without a leading / are relative to the setting of the with. When using set. Set also understands a leading . in a source to mean local to the with.

set msg .nomsg

will set the value of the local nomsg variable to the local msg value.

Because of the stack it is possible to construct a nice environment for defaults and other things.

    with /home
    with /config/device/waiting
    with /config/device/handshake
    with /config/dialogs
    with /device

Patterns

For now, There are with-, initialize and clear functions in various name spaces which set up a desirable with stack and workspace for a given module. Use help on each namespace to understand what is there. Once a complete default stack is built for the functionality desired, Add one more empty space to work in. Using a clean space as a workspace with excursions to other paths seems to work really nicely.

dedupwith can help clean up the with stack if there are repeating paths in the stack.

This helps. in this statement, /my/tmp/spot will be put on the stack, and maybe it has stuff, do-this-thing is called, and the results stack there, because of the '.' is popped to spot-result in the original/calling with path.

with /my/tmp/spot do-this-thing .spot-result

The ability to move the stack around and manipulate it is new, on verra.

Initialize that is in various modules is meant to be used once, so is best used in the exec startup hooks. Otherwise the with stack could get unnecessarily deep.

Simple Session.

SPR:> show
/home
msg: hello, welcome home.


SPR:> ui/with-ui
/config/dialogs
-------------------------
    title                         
    msg                           
    yn_msg                        
    yn_fail_msg                   
    plugin_start                  
    ready_to_test                 
    ready_to_flash                
    process_failed                
    process_success               
    process_finish                
    continue                      
    input_please                  
    input_regex                   
    input_is_correct              
    input_must                    
    hellomsg                      
/config/print_commands
-------------------------
    menu_msg                      
    Linux                         
    Windows                       
    Darwin                        

SPR:> ls-with
    /                             
    /home                         
    /config/dialogs               
    /config/print_commands        

SPR:> cli/msg
Just in case msg is empty.
Press any key to continue;

SPR:> with /home
/home
-------------------------
    msg                           

SPR:> cli/msg
hello, welcome home.
Press any key to continue;

SPR:> ls-with
    /                             
    /home                         
    /config/dialogs               
    /config/print_commands        
    /home                         

SPR:> dedupwith
/tmp
-------------------------
   Is Empty.
/tmp
-------------------------
    results                       
    _last_result_                 

SPR:> ls-with
    /                             
    /config/dialogs               
    /config/print_commands        
    /home                         

SPR:> as/show-with
/config/dialogs
continue: Ready to Continue ?
hellomsg: You have received this message because your autoexec attribute is set to
  'hello' or None, or can't be found. Maybe make some new commands to create some
  processes. When you get a command you want to run automatically set autoexec exec/autoexec
  in the config file to it's name. Here are the commands the interpreter currently
  recognizes.
input_is_correct: This entry is correct ?
input_must: 'Entry must match regex:'
input_please: Please input Something.
input_regex: ^\d{8}$
msg: Just in case msg is empty.
plugin_start: Plug in a new device, press OK to start
process_failed: Process Failed!
process_finish: Turn the Power Switch Off and Disconnect the Battery and USB.
process_success: Process Succeeded!
ready_to_flash: Ready to flash.
ready_to_test: Ready to test.
title: The Simple Process REPL
yn_fail_msg: 'This fails if you do not say yes. ? Y/N: '
yn_msg: 'Did you expect this message? Y/N: '

/config/print_commands
Darwin:
  brother: brother_ql -m QL-700 -p usb://04f9:2042 print -l 29 %s
  default: echo "Sorry I dont know how to print this %s"
Linux:
  brother: brother_ql -m QL-700 -p usb://04f9:2042 print -l 29 %s
  default: echo "Sorry I dont know how to print this %s"
Windows:
  brother: brother_ql -m QL-700 -p usb://04f9:2042 print -l 29 %s
  default: echo "Sorry I dont know how to print this %s"
menu_msg: Please choose a printer command

/home
msg: hello, welcome home.

Clone this wiki locally