Skip to content

Resident plugins and listeners

Lauri-Matti Parppei edited this page Feb 18, 2022 · 3 revisions

Running plugins in the background

Usually plugins are just run once, and not left in the memory. If you want the plugin to remain active and track changes to the document, you either need to set up a listener function, or have a floating HTML window attached to your plugin.

Resident plugins remain in memory even after using return, and can be terminated with Beat.end() or by unchecking the plugin from Tools menu.

Note that listener methods have to be very efficient to avoid slowing down the editor.

Adding Listeners

Listen to Text Change

Runs whenever the screenplay is edited, and receives location and length of the latest change.

Beat.onTextChange(
    function (location, length) {
        Beat.log("Edited at " + location + " (length: " + length +")")
    }
);

Listen to Selection Change

You can listen to selection changes with setSelectionUpdate().

Note: this method is also run when the text changes. Make your listener method as snappy as possible.

Beat.onSelectionChange(
    function (location, length) {
        Beat.log("Selection changed to " + location + "/" + length)
    }
)

Listen to Changes in Outline

onOutlineChange() fires when a scene is added — or something is edited on the edge of a scene.

Beat.onOutlineChange(
    function (...outline) {
        for (let i=0; i < outline.length; i++) {
            // Do something with the new outline
        }
    }
)

Listen to Current Scene

Instead of listening to changes in selection and figuring out current scene, you can ask for current scene index. Like .onSelectionChange(), .onSceneIndexUpdate(...) runs whenever the user selects anything, but only returns the index for current outline item. It can be the same as it before.

This should only be used for updating something in your UI. For example, if you have created a visual representation of the screenplay using Beat.outline() and keep it updated using Beat.onOutlineChange(), you current scene index can be used to highlight the scene being edited.

NOTE: Index is valid ONLY for the full outline (Beat.outline())

Beat.onSceneIndexUpdate(
    function (sceneIndex) {
        const scenes = Beat.outline()
        let currentScene = scenes[sceneIndex]
    }
)

Disabling Listeners

If you are listening to text changes and would like to make changes to the text on some event, your original update function will be called again. This can cause an infinite loop.

To avoid strange loops, you can disable the listeners when needed:

Beat.onTextChange(function (len, loc) {
    Beat.onTextChangeDisabled = true
    Beat.replaceRange(0,0, "Hello World! ")
    Beat.onTextChangeDisabled = false
})

Property names for disabling change listeners correspond to their setter methods.

Beat.onTextChangeDisabled = true/false
Beat.onOutlineChangeDisabled = true/false
Beat.onSelectionChangeDisabled = true/false
Beat.onSceneIndexChangeDisabled = true/false