Skip to content

Reactive Scripts Deep Dive

Svein Arne Ackenhausen edited this page May 11, 2014 · 5 revisions

Reactive scripts are actions triggered by events in the OpenIDE environment. After starting an instance of the OpenIDE environment you can use the oi event-listener command to peek into what events are being passed around inside. Reactive script can trigger on any event. If you want to list reactive scripts use the oi rscript command. If you have a running environment you can also add the oi rscript -s argument to display the rscript state. As with scripts there is a oi rscript new myscript.py command to create a new reactive script based on the python template. As with everything in OpenIDE the API is stdin and stdout so any language is supported. If you had the editor open it would open a file similar to the file below. If not run the oi rscript edit myscript command to open it in the editor.

#!/usr/bin/env python
import sys

def print_react_patterns():
    # Write one event pr line that this script will react to
    print("'hello'")
    
def handle_event(event, global_profile, local_profile, args):
    # Write scirpt code here.
    print("Hello world!")

if __name__ == "__main__":
    #   Param 1: event
    #   Param 2: global profile name
    #   Param 3: local profile name
    #
    # When calling other commands use the --profile=PROFILE_NAME and 
    # --global-profile=PROFILE_NAME argument to ensure calling scripts
    # with the right profile.
    args = sys.argv
    if len(args) > 1 and args[1] == 'reactive-script-reacts-to':
        print_react_patterns()
    else:
        handle_event(args[1], args[2], args[3], args[4:])

React patterns

As with regular scripts there is a definition part and an execution part. The definition part of reactive script are the patterns to match events on. It supports * to match on things like 'codemodel' 'filesystem-change-filechanged' '*. The script we just created will match on the exact event 'hello'. Print one line to stdout for each pattern you want to react on. In addition to react patterns you can print run-as-service. This will lead to the script being started once and then have all event processing being passed to it through stdin. The script should loop until it receives the shutdown message and then exit gracefully.

Running the script

Naturally to run a reactive script we need to have the environment running and publish events that the script can react to. All output written to stdout will be redirected to the output endpoint. To listen for output run this command oi output-listener rscript-myscript to listen for any output generated by the script we created. Now to have it trigger we can use the oi codemodel publish "'hello'" command. You will now see Hello World! printed by the output listener.

Now instead of having to trigger that event constantly when writing the script there is a run on save for reactive script too. To trigger the script every time a change is made to it run oi rscript repl myscript "'hello'". This will publish the hello event every time a change is made to the script.

Other than printing raw output you reactive scripts handles the following features through stdout and stdin:

  • error|some text Outputs error text
  • event|some event Publishes an event
  • command|editor goto /my/file.txt|10|5 Runs a language, editor or codemodel command
  • request|editor get-caret Runs a request where result is printed to stdin
    • end-of-conversation is printed to stdin when command has completed
    • editor, codemodel and languages are supported for request

Folder structure

All extensions are allowed to have one file in the actual script folder and then whatever files it wants inside a folder called SCRIPT_NAME-files at the same place. If made in to a package any files you want to survive upgrades must be placed inside a SCRIPT_NAME-files/preserved-data folder. Any type of state that the script might have must be placed in a SCRIPT_NAME-files/state folder to not cause constant rebuilds of command definitions.

Configuration options

Any extension is free to have it's own configuration settings. All configuration settings are exposed through the oi conf list command which prints all available configuration options. To have your rscript configuration options show up there create a folder called myscript-files where the myscript.py file is located and place a file called myscript.oicfgoptions in it. The format of the file is one configuration option per line and the option format is myscript.some.config.option|This is the option description.

Typical usages

Events are something typically generated by any part of the system. For instance the editor will usually have events generated from key presses. In my setup I have this setting in my sublime user key bindings { "keys": ["f12"], "command": "open_ide_language_command", "args": { "message": "go-to-definition" } }. This will trigger a language command event which looks like this for .cs files: '.cs' 'command' 'go-to-definition'. These are events that will be translated by file extension to what language plugin handles it and then passed to it. However if the language plugin does not support go to definition you can have a reactive script trigger on it and do the job.

Clone this wiki locally