Script Editor API: Now in Beta!

Hey Developers,

Hope you’re having a great summer! For all the Plugin devs out there, we’re thrilled to announce something we hope you’ll be as excited about as we are: the Script Editor API beta.

This API vastly expands the extent to which Plugins can interact with the Script Editor, providing the ability to:

  • Monitor when Scripts are opened, closed, and edited
  • Access information on a user’s cursor, including selected text
  • Read and edit specified portions of a Script without overwriting the entire contents

The beta can be enabled by toggling Studio > Beta Features > Script Editor API.

See below for more detailed information!

API Overview

ScriptDocument

A ScriptDocument instance is a proxy of an open Script Editor document (including the Command Bar). It represents the contents of the document, including ephemeral data such as cursor position and selection, as well as uncommitted edits made in Team Create Collab Editing mode (which may not be in the .Source property yet). The provided ScriptDocument methods allow you to asynchronously query and modify the state of these contents.

For example, the following method retrieves text from a Script at a specified location:

string ScriptDocument:GetText(int startLine?, int startColumn?, int endLine?, int endColumn?)

While the following method edits text in at a specified location:

bool, string? ScriptDocument:EditTextAsync(string newText, int startLine, int startColumn, int endLine, int endColumn)

The existence of a ScriptDocument signifies a Script being open in the Script Editor. All ScriptDocuments are parented to the ScriptEditorService.

All APIs for ScriptDocument are at Plugin level security.

Click here for more info and documentation on the ScriptDocument API.

ScriptEditorService

ScriptEditorService provides the ability to both monitor and interact with the ScriptDocuments it owns. Specifically, it allows you to access ScriptDocuments in order to utilize the ScriptDocument API, and to handle events when a ScriptDocument is opened, closed or edited.

For example, the following code attempts to retrieve a ScriptDocument corresponding the Script “myScript” in the workspace:

game:GetService("ScriptEditorService"):FindScriptDocument(workspace.myScript)

While the following Plugin code prints a statement to the output when any ScriptDocument is edited:

game:GetService("ScriptEditorService").TextDocumentDidChange:Connect(function(doc, tbl) print("Changed", doc, tbl) end)

Click here for more info and documentation on ScriptEditorService.

Example Usage

The following Plugin is an example of what can be done with the Script Editor Plugin API: when the user types GS(<some_service>), it replaces the text with <some_service> = game:GetService("<some_service>"):

function IsValidServiceName(ServiceName)
   local Success, Service = pcall(function() return game:GetService(ServiceName) end)
   return Success and Service
end

game:GetService("ScriptEditorService").TextDocumentDidChange:Connect(function(Document, _)
   local Line = Document:GetLine()
   local ServiceName = string.match(Line, "GS%((%w+)%)")
   if not ServiceName or not IsValidServiceName(ServiceName) then return end
   local LineNumber, _, _, _ = Document:GetSelection()
   local NewText = string.format("local %s = game:GetService(\"%s\")", ServiceName, ServiceName)
   Document:EditTextAsync(NewText, LineNumber, 1, LineNumber, string.len(Line) + 1)
end)

Looking Forward

The Script Editor Plugin API beta revolutionizes what’s possible for Script Editor Plugins, and we can’t wait to see what the community builds with these new tools. We look forward to hearing your feedback on what we have provided, and hope to continue to expand what the API offers.

Please note: Because this API is still in beta, we may make code-breaking changes based on your feedback. If this is necessary, we will let you know.

A huge thanks to the following who’ve contributed to the project: @swmaniac, @code4xp, @cruiser_forever, @windy0724, @infomancer

Happy scripting!

251 Likes

This topic was automatically opened after 11 minutes.

Finally, I’ve been waiting so long for this, thank you. Can’t wait to see what amazing plugins come of this I already have some ideas for what I could try to make.

21 Likes

Will breakpoints be apart of the API in the future?

20 Likes

Seems nice. I was going to get into making plugins soon, but alot of the ideas I had were scripting related and I think this will make it safer and easier! Thanks

9 Likes

Let’s GOOO I’ve been waiting for this for eons.

Can we see further API, e.g. being able to know what line the user has scrolled to in the current script? Then we know what is currently visible which lets us keep external widgets in sync with what the user is currently looking at.

Setters for cursor position, selected text, highlighted text (like Ctrl F) might also be useful for various purposes. (E.g. highlighting particular patterns or errors that are project specific, moving the cursor to particular points in code snippets, etc.)

Being able to detect enter presses (not sure if user input service works in the script editor) would also let us detect when people have filled out a field in a code snippet which would be useful in conjunction with the previous setters.

23 Likes

This is extremely exciting news! Been asking for this capability for years and it’s finally here! Huge thanks to the team behind this.

I’m going to get cracking on some plugins…

39 Likes

Heya, this is great! However, I was hoping there to be a method to close scripts. Is this something that could be added in the future?

9 Likes

Finally, now i can update my plugin properly without needing third party functions which are very unreliable

4 Likes

Part of the reason for this beta is to collect feedback on pieces this API is missing that people want. Suggestions are greatly appreciated.

15 Likes

This is exactly what i needed for my plugin. Thanks for this update!

3 Likes

I can see virus plugins using this to add lines to our scripts which just require viruses, but besides this it’s exciting!

2 Likes

This is a great update for people who want to scripts. I can see many different uses for this update. :slight_smile:

4 Likes

This doesn’t bring on many new problems, malicious plugins already can add lines to scripts

9 Likes

Does the new ScriptDocument.EditTextAsync function allow me to programmatically set the source of a script to have more than 200k characters?

My biggest problem with the existing API (and by that i just mean the Source property on Scripts) was that It would refuse to take a string longer than 200k. If I can now just repeatedly append to a script in smaller chunks that would completely solve my problem.

4 Likes

Been looking at the API change history and thought that this could be enabled on live experiences. Is there a reason to why we can’t enable this in our experiences?

3 Likes

Besides not having a Script Editor in live experiences, what would be a use case?

4 Likes

Well, I’m not sure how you would use a plugin in a live game

4 Likes

I hadn’t actually tried this, but it should!

For example,

local x = string.rep("-", 1000) .. "\n"; 
for i = 1, 500 do 
    game:GetService("ScriptEditorService"):FindScriptDocument(workspace.Script):EditTextAsync(x, i, 1, i, 1) 
    wait() 
end
10 Likes

To make a script made by the player run in the game. I have had this as a feature request for my Build Mode system.

2 Likes