godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add a editor API feature to integrate custom scripting languages #3445

Open ghsoares opened 2 years ago

ghsoares commented 2 years ago

Describe the project you are working on

React GD A project where I have a JSX-like syntax inside regular gdscript, which the tag blocks are parsed into Dictionaries. The name of the custom language I called GDXScript

Describe the problem or limitation you are having in your project

My objective is to have user-friendly JSX-like syntax for my plugin, and it would be useful to have a Editor API feature which I can add a simple enough custom language support. The goal is to have a plugin where you can select the custom language from "Create Script" dialog, letting the user to edit from the Godot's code editor.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The feature is a class like EditorImportPlugin, called EditorScriptParserPlugin, in this class there would be some virtual functions to describe the custom script language and how to parse to GDScript. A class to interact with Godot's text editor TextEdit to change syntax highlighting and maybe custom intellisense support, called EditorScriptLanguagePlugin. And finally, a way to extend Script resource to actually create the custom script resource.

This feature isn't to actually create the language, the details of the custom language is up for the developer, would be better to use modules for more complex programming languages. This feature is only for a simple integration into Godot's editor for simple custom script languages without needing to use external tools or native modules.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Some virtual functions for EditorScriptParserPlugin:

# Returns the script language name, appears on "Create Script" dialog on the language dropdown
String get_language_name()

# Returns a PoolStringArray with the valid extensions for this script language
PoolStringArray get_recognized_extensions()

# Returns an String of the default script template, used when a new custom script is created
String get_default_template()

# The actual function to parse from the custom language into gdscript
void parse(source: Script, target: GDScript)

On editor, whenever the custom language is selected to create the new script, the first recognized extension is used as default. Then the custom script resource is populated with the string returned from get_default_template. Finally, whenever the custom script is saved, parse is called to save the target with the parsed code.

Some virtual functions for EditorScriptLanguagePlugin:

# Function called whenever the custom script is focused on script editor, to setup syntax highlighting and connect signals
void enter_editor(editor: TextEdit)

# Function called to disconnect signals from TextEdit
void exit_editor(editor: TextEdit)

# I don't know exactly, this function would be useful to create custom intellisense
# Would return a array of dictionaries containing info for auto complete, like variables, functions, etc.
Array get_auto_complete_info()

Then you could override from Script class to create the custom script resource:

extends Script

class_name GDXScript

# Insert any extra relevant info here, like export variables, helper functions, etc.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, there's no way to add custom language integration support without native modules.

Is there a reason why this should be core and not an add-on in the asset library?

Same as above.

YuriSizov commented 2 years ago

Note that syntax highlighting is already exposed in 4: https://docs.godotengine.org/en/latest/classes/class_syntaxhighlighter.html#class-syntaxhighlighter

ghsoares commented 2 years ago

@pycbouh Awesome, I forgot to include functions used by EditorPlugin when enabling and disabling the plugin:


# Function to add a custom language, provide the script class name (In my example, "GDXScript"), the parser class name ("EditorScriptParserPlugin") and the syntax highlighter class name
void add_custom_language(script_class: String, parser_class: String, syntax_highlighter_class: String)

# Remove the custom language support followed by the script class name, parser class name and the syntax highlighter class name
void remove_custom_language(script_class: String, parser_class: String, syntax_highlighter_class: String)