-
Notifications
You must be signed in to change notification settings - Fork 13
API overview
The easiest way to debug your plugin code is to do it using the plugin console.
-
Beat.openConsole()— open console window -
Beat.log(string)— log something (note: single argument only)
See Document model
-
Beat.lines()– allLineobjects in the script -
Beat.outline()– all outline objects (OutlineScene), including synopsis lines and sections -
Beat.scenes()– only scene objects (OutlineScenewithheadingtype) -
Beat.linesForScene(scene)– lines for a specified scene -
Beat.getText()— whole document as string -
Beat.currentLine— line which has the caret -
Beat.setColorForScene(scene, color)— set color for a scene object (use"none"to remove any existing color)
-
line.string— string content -
line.position— starting index of line -
line.textRange— range of the line ({ location: ..., range: ... }) -
line.range— full location and length INCLUDING line break -
line.type— returns an integer value, matchesBeat.typevalues (see Document model for valid types) -
line.typeAsString()— returns type as string (see Document model for valid type strings) -
line.isTitlePage()— true/false -
line.isOutlineElement()— true/false -
line.isInvisible()— true/false -
line.cleanedString()— non-printing stuff removed -
line.stripFormatting()– non-printing suff and any Fountain formatting removed -
line.omitted— true/false, check if the line is inside an omitted block (/* */) -
line.note— true/false, check if the line is completely a note (wrapped in[[]]) -
line.clone()— make a copy of the line, detached from the parser -
line.forSerialization()- JSON data for the line
-
Beat.outlineAsJSON()— complete outline as JSON -
Beat.scenesAsJSON()— scenes as JSON -
line.forSerialization()— serialize a single line object
See Document data
-
Beat.createDocumentFile()— returns the plain-text Fountain file for current document, along with document settings JSON block -
Beat.createDocumentFileWithAdditionalSettings(settings)— returns the plain-text Fountain file for current document, and appends custom JSON settings to the block
-
Beat.addString(String, index)– add string at some index -
Beat.replaceRange(index, length, string)– replace a range with a string (which can be empty to remove text)
-
Beat.selectedRange()– returns a range object with.locationand.lengthproperties -
Beat.setSelectedRange(location, length)– set user selection (make sure you don't go out of range) -
Beat.scrollTo(index)– scroll to character index -
Beat.scrollToScene(scene)– scroll to a scene object -
Beat.scrollToLine(line)– scroll to a line object -
Beat.focusEditor()— focus the editor window (from an HTML, for example)
-
Beat.reformat(line)— reformat a single line in the screenplay -
Beat.reformatRange(location, length)— reformat a range
-
Beat.textBackgroundHighlight("#000000", location, length)– set text background color -
Beat.textHighlight("#000000", location, length)– set foreground color
Highlights can be cleared by reformatting the range (or the whole line).
-
Beat.alert("Alert title", "Informative Text")– simple alert box -
Beat.confirm("Title", "Informative text")— ask for confirmation, returnstrueorfalse -
Beat.prompt("Title", "Informative Text", "Placeholder string")– get text input from the user, returns a string -
Beat.dropdownPrompt("Title", "Informative Text", [value, value, value])– allow the user to select a value from an array, returns a string
You can create more advanced modal windows with multiple types of inputs using Beat.modal(). It takes in an object with the following properties: title (title of the modal), info (informative text) and items: [] (an array of inputs).
See the example below to get an idea on how advanced modals work.
Beat.modal({
title: "This is a test modal",
info: "You can input stuff into multiple types of fields",
items: [
{
type: "text",
name: "characterName",
label: "Character Name",
placeholder: "First Name"
},
{
type: "dropdown",
name: "characterRole",
label: "Role",
items: ["Protagonist", "Supporting Character", "Other"]
},
{
type: "space"
},
{
type: "checkbox",
name: "important",
label: "This is an important character"
},
{
type: "checkbox",
name: "recurring",
label: "Recurring character"
}
]
}, function(response) {
if (response) {
// The user clicked OK
Beat.log(JSON.stringify(response))
} else {
// The user clicked CANCEL
}
})See Saving User and Document Settings
-
Beat.getUserDefault("setting name")– get a user setting -
Beat.setUserDefault("setting name", value)– save a user setting
-
Beat.getDocumentSetting("setting name")– get a document-specific setting for current plugin -
Beat.setDocumentSetting("setting name", value)– set a document-specific setting for current plugin
You are only able to set plugin-specific document settings with these methods. If you really know what you are doing, you can access the actual document settings, such as character genders. Be sure not to overwrite any required values. To get a clue about the values, open a Fountain file created by Beat in a plain-text editor and see the JSON block at the end of the file.
-
Beat.setRawDocumentSetting("setting name", value)— set a document-specific setting -
Beat.getRawDocumentSetting()— get a document-specific setting
See Resident plugins and listeners
Beat.onTextChange(
function (location, length) {
Beat.log("Edited at " + location + " (length: " + length +")")
}
)Beat.onOutlineChange(
function (...outline) {
for (let i=0; i < outline.length; i++) {
// Do something with the new outline
}
}
)const scenes = Beat.outline()
Beat.onSceneIndexUpdate(
function (sceneIndex) {
let currentScene = scenes[sceneIndex]
}
)Beat.onDocumentSave(function () {
// Do something when the document is saved
})Beat.onTextChangeDisabled = true/false
Beat.onOutlineChangeDisabled = true/false
Beat.onSelectionChangeDisabled = true/false
Beat.onSceneIndexChangeDisabled = true/false-
Beat.nextTab()— move to next document tab -
Beat.previousTab()— move to previous document tab -
Beat.screen()— retrieve current screen size ([width, height]) -
Beat.windowFrame()— retrieve frame for current document window ([x, y, width, height])
-
Beat.htmlPanel(htmlContent, width, height, callback, okButton)— displays a modal HTML window -
let htmlWindow = Beat.htmlWindow(htmlContent, width, height, callback)— displays a standalone HTML window
-
htmlWindow.title— window title -
htmlWindow.setTitle(string)— set window title -
htmlWindow.setHTML(htmlString)— set window content -
htmlWindow.close()— close the window and run callback -
htmlWindow.setFrame(x, y, width, height)— set window position and size -
htmlWindow.getFrame()— returns position and size for the window -
htmlWindow.screenSize()— returns size for the screen window has appeared on -
htmlWindow.runJS(javascriptString)— sends JavaScript to be evaluated in the window
See File access
-
Beat.openFile([extensions], function (filePath) { })– displays an open dialog for an array of extensions and returns a path -
Beat.openFiles([extensions], function ([filePaths]) { })— as above, but allows selecting multiple files and returns an array of paths -
Beat.fileToString(path)– file contents as string -
Beat.pdfToString(path)– converts PDF file contents into a string
-
Beat.saveFile(extension, function (filePath) { })– displays a save dialog and returns the path to callback -
Beat.writeToFile(path, content)– write a string to path
See Printing
-
Beat.printHTML(htmlString, settings)— prints out a pure HTML document
- See Pagination
-
Beat.currentPagination()– pagination used by the preview controller -
Beat.pagination()— creates a new pagination
See Timer
let timer = Beat.timer(seconds, callback, repeat)-
timer.invalidate()— stop and remove the timer from memory -
timer.stop()— stop and reset the timer -
timer.start()— start the timer again -
timer.running()– check if the timer is currently running
When repeat is set to true the timer will stay in memory. It defaults to false, so you can create one-off timeouts, too:
Beat.timer(1.0, function () {
Beat.log("One second elapsed.")
})See Revisions
-
Beat.revisedRanges()— returns an object with revision generation as key and ranges as arrays, ie.{ "revisionColor": [[loc, len], ...], ... } -
Beat.bakeRevisions()— stores all the current revised ranges into lines (line.ranges.revisions) -
Beat.bakeRevisionsInRange(loc, len)— stores revisions in a given range into corresponding lines
-
Beat.async(function)— run asynchronous code in a background thread (note: never access anything related to UI or screenplay content) -
Beat.sync(function)— run synchronous code in the main thread (to return results to the UI)
-
Beat.currentParser— current parser -
Beat.parser(stringToParse)— create a new parser -
parser.lines— line objects (note: property, not a method) -
parser.outline— all scene objects, including synopsis lines and sections (note: property, not a method) -
parser.scenes— scene objects only (note: property, not a method) -
parser.titlePage— title page elements -
parser.linesInRange({ location: x, length: y })— get all lines in the selected range (note: parameter has to be a range object) -
parser.lineAtIndex(index)— get line item at given character index
parser.sceneAtIndex(index)— get outline item at given character index
-
Beat.document()- returns the document object for current document -
Beat.documents()– returns an array of every open document -
Beat.interface(document)— returns a plugin API interface for another document
The Beat object always refers to the current document. If you need to access the other documents, you'll have to first retrieve a Document object and then create an so-called interface for it, which is identical to the Beat object, but refers to another document.
const documents = Beat.documents()
for (const doc of documents) {
if (doc == Beat.document()) {
// This is our open document. Skip.
continue
}
const interface = Beat.interface(doc)
// You can now use any plugin API methods on the other document using this interface.
interface.addString("Hello world", 0)
}See Menus
-
Beat.menuItem(title, [shortcuts], callback)— creates and returns a menu item -
menuItem.on— whentrue, menu item will display a checkmark next to it -
Beat.separatorMenuItem()— creates and returns a separator menu items -
Beat.menu(title, [children])— creates (and adds) a menu with given menu items -
menu.addItem(menuItem)– adds a menu item -
menu.removeItem(menuItem)– removes a menu item
Whenever a menu is created, it's automatically added to the top menu bar.
let item = Beat.menuItem("Hello World", ["alt", "cmd", "x"], () => {
Beat.log("Hello world")
})
let menu = Beat.menu("My menu", [item])-
Beat.compatibleWith(versionString)— see if the user is running a compatible version of Beat
If you REALLY, REALLY know what you are doing, you can access document class property values. These calls should be used only for development purposes and preferrably not in a distributed plugin. Contact the developer for exposing the required property for actual plugin API, if you happen to find something that you need.
-
Beat.setPropertyValue(key, value)— set a property value by key -
Beat.getPropertyValue(key)— get property value by key
If you REALLY, REALLY, REALLY, REALLY know what you are doing, you can call Objective C methods in the document directly. This allows access to methods that are not exposed to the API, and might come in handy when debugging your plugin, or just generally poking around and experimenting.
Beat.objc_call(selector, [arg1, arg2, ...])selector is an Objective C selector, such as getText or replaceCharactersInRange:withString:. You need to have an understanding of how Objective C selectors and calls work, and bear in mind that it is extremely easy to crash the app with malformed selectors and arguments.