EditorSyntaxHighlighter in Godot – Complete Guide

Welcome to this in-depth exploration of the EditorSyntaxHighlighter class in Godot 4, an essential tool for developers looking to enhance their script editing process in the Godot Engine. If you’re a game developer or interested in creating interactive content, understanding syntax highlighting is crucial for improving your workflow and making code easier to read and debug. By the end of this tutorial, you’ll have a solid foundation in using and customizing syntax highlighting within Godot’s ScriptEditor to streamline your development experience.

What is EditorSyntaxHighlighter?

The EditorSyntaxHighlighter is a Godot Engine class that serves as the base for all syntax highlighters used within the integrated ScriptEditor. Syntax highlighting is a feature that displays source code in different colors and fonts according to the category of terms. This enhances the readability of code and helps to identify errors at a glance, making it an indispensable feature for developers.

What is it used for?

ScriptEditor, Godot’s built-in code editor, utilizes these custom syntax highlighters to visually distinguish between various parts of code, such as keywords, functions, variables, and comments. By extending the EditorSyntaxHighlighter, you can add support for new languages or modify the existing highlighting rules to fit your preferences or project needs.

Why should I learn it?

Customizing your development environment, especially the code editor, can significantly impact productivity and code quality. For beginners, learning about syntax highlighting is a step toward mastering your tools, while experienced coders will appreciate the flexibility and efficiency that comes from tailoring the editor to their coding style. With the ability to create or tweak syntax highlighters, Godot developers can ensure that their scripting environment is as helpful and user-friendly as possible.

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Creating a Custom Syntax Highlighter

To create a custom syntax highlighter in Godot, you need to extend the EditorSyntaxHighlighter class. Here’s an example of how you can start setting up a simple syntax highlighter for a hypothetical programming language:

extends EditorSyntaxHighlighter

func _get_language_name():
    return "MyCustomLanguage"

This function identifies the language name for the Godot editor to use. Next, let’s define some basic syntax patterns you want to highlight:

var keywords = [
    "func", "var", "if", "else", "for", "while"
]

var symbols = [
    "=", "+", "-", "*", "/", "%", "!"
]

func _get_highlighting_patterns():
    var patterns = []
    for keyword in keywords:
        patterns.append({"pattern": keyword, "color": EditorSettings.get_singleton().get("text_editor/highlighting/keyword_color")})
    for symbol in symbols:
        patterns.append({"pattern": symbol, "color": EditorSettings.get_singleton().get("text_editor/highlighting/symbol_color")})
    return patterns

These methods set up arrays with keywords and symbols and apply colors based on the editor’s current settings. Notice we’re using the editor’s settings to ensure consistency with other languages.

Applying Highlighting Rules

Once you’ve defined your language’s patterns, you need to define how and when these patterns will be applied. The _get_highlighting_patterns method helps with that:

func _get_highlighting_patterns():
    var patterns = []
    # Add keyword patterns
    for keyword in keywords:
        patterns.append({
            "pattern": "\\b" + keyword + "\\b", # \b indicates word boundary
            "type": "keyword",
            "color": EditorSettings.get_singleton().get("text_editor/highlighting/keyword_color"),
            "custom_bg_color": Color(0, 0, 0, 0) # Background color, transparent by default
        })
    # Add symbol patterns
    for symbol in symbols:
        patterns.append({
            "pattern": "\\" + symbol, # Escape symbol to be taken literally
            "type": "symbol",
            "color": EditorSettings.get_singleton().get("text_editor/highlighting/symbol_color"),
            "custom_bg_color": Color(0, 0, 0, 0)
        })
    return patterns

In this block of code, we’re not only setting the color but also defining the type and using regex word boundaries to ensure that keywords are matched as entire words. Symbols are escaped properly to be recognized as specific characters.

Highlighting Comments and Strings

Comments and strings in most languages also follow specific patterns. Here’s how you might extend your highlighter to include those:

var comment_pattern = "#.*"
var string_pattern = "\"[^\"]*\""

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Add comment pattern
    patterns.append({
        "pattern": comment_pattern,
        "type": "comment",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/comment_color"),
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    # Add string pattern
    patterns.append({
        "pattern": string_pattern,
        "type": "string",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/string_color"),
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    return patterns

Here, we add regular expressions for single-line comments (anything following a # symbol until the end of the line) and for strings (text enclosed in double quotes).

Enhancing Readability with Custom Background Colors

Sometimes, highlighting text isn’t enough. You might want to use custom background colors for specific elements in your code:

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Modify keyword pattern for custom background color
    for i in range(patterns.size()):
        if patterns[i].type == "keyword":
            patterns[i].custom_bg_color = Color(0.25, 0.25, 0.25, 0.5) # A semi-transparent gray
    
    return patterns

This functionality is particularly useful for differentiating between various sections of code, such as marking TODO comments or differentiating between different types of variables.

Remember that good highlighting is not just about applying colors; it’s about improving the clarity and readability of your code. Take the time to test your custom syntax patterns and adjust them until they provide the best possible experience for you and your team.

Expanding on the syntax highlighter we’ve begun, let’s incorporate more advanced functionality. To give feedback on codes like magic numbers or TODO comments, we can create further custom highlighting rules.

Let’s start by identifying ‘magic numbers’ – numbers that appear in code without clear meaning. Highlighting these could encourage developers to use named constants for clarity:

var magic_number_pattern = "\\b[0-9]+\\b" # Matches whole numbers

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Add magic number pattern
    patterns.append({
        "pattern": magic_number_pattern,
        "type": "number",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/number_color"),
        "custom_bg_color": Color(1, 0, 0, 0.2) # Light red background to warn developers
    })
    
    return patterns

Highlighting ‘TODO’ comments can be helpful for developers to easily spot areas that require further work or consideration:

var todo_comment_pattern = "TODO:.*"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Add TODO comment pattern
    patterns.append({
        "pattern": todo_comment_pattern,
        "type": "todo",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/todo_color",
            Color(0.9, 0.9, 0.1)), # Default to yellow if there's no specific setting
        "custom_bg_color": Color(0.9, 0.9, 0.1, 0.3)
    })
    
    return patterns

Godot’s scripting language, GDScript, also has annotations for additional functionality. Here’s how you might highlight them:

var annotation_pattern = "@[A-Za-z_]\\w*"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Add annotation pattern
    patterns.append({
        "pattern": annotation_pattern,
        "type": "annotation",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/annotation_color",
            Color(0.4, 0.4, 0.9)), # Default to a soft blue
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

These annotations can be crucial for functionality like networking, so giving them a distinct highlight helps ensure they don’t go unnoticed.

Additionally, you can also adjust highlighting for different variable types, such as class member variables:

var member_variable_pattern = "self\.\\b\\w+\\b"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Add member variable pattern
    patterns.append({
        "pattern": member_variable_pattern,
        "type": "member_variable",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/member_variable_color",
            Color(0.5, 0.63, 0.94)), # Default to a distinct color variation from annotations
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

Such customizations make it clear at a glance which variables are local and which are part of the object’s state.

For languages that use different types of numbers, like binary or hexadecimal, you can include specific highlight rules for them as well:

var binary_pattern = "\\b0b[01]+\\b"
var hexadecimal_pattern = "\\b0x[0-9A-Fa-f]+\\b"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Binary numbers
    patterns.append({
        "pattern": binary_pattern,
        "type": "number_binary",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/number_binary_color",
            Color(0.2, 0.8, 0.2)), # Greenish by default
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    # Hexadecimal numbers
    patterns.append({
        "pattern": hexadecimal_pattern,
        "type": "number_hex",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/number_hex_color",
            Color(0.8, 0.5, 0.2)), # Orangish by default
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

Implementing specific highlighting like this not only improves code readability but also caters to the nuances and best practices of the language you are writing with.

These examples demonstrate how effective a customized EditorSyntaxHighlighter can be in your coding practice within Godot. By leveraging such customizations, you’ll create an environment that best suits your development style, leading to improved code management and a smoother coding experience. Remember, as an integral part of Zenva, our mission is to empower our learners with high-quality content that propels them forward. Keep experimenting, and you’ll soon have an editor that feels uniquely yours, enhancing your ability to create great games and interactive experiences with Godot 4.

We’ve covered how to highlight various language constructs, but it’s also important to ensure that your custom highlighter can handle edge cases and provide a more comprehensive experience. Let’s look into some scenarios that might require special attention and how to manage them.

One common requirement is to account for multiline comments or strings. Here’s how you might extend your syntax highlighter to recognize multiline strings:

var multiline_string_pattern_begin = "\"\"\""
var multiline_string_pattern_end = "\"\"\""

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Multiline string opening
    patterns.append({
        "pattern": multiline_string_pattern_begin,
        "type": "string",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/string_color"),
        "start_sequence": true
    })
    
    # Multiline string ending
    patterns.append({
        "pattern": multiline_string_pattern_end,
        "type": "string",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/string_color"),
        "end_sequence": true
    })
    
    return patterns

Here we use the start_sequence and end_sequence flags to indicate that these patterns mark the beginning and the end of a multiline string, respectively.

Developers often use regular expressions in their code, which can be complex and difficult to read. Special highlighting for regex patterns could be invaluable. Here’s an example:

var regex_pattern = "r'/(.+)/'"
func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # Regular expressions
    patterns.append({
        "pattern": regex_pattern,
        "type": "regex",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/regex_color",
            Color(0.8, 0.3, 0.8)), # A purple-like color by default
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

If your custom language supports interpolation within strings, you can create a separate highlight for that too:

var string_interpolation_pattern = "\\$\\{[^}]+\\}"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()
    
    # String interpolations
    patterns.append({
        "pattern": string_interpolation_pattern,
        "type": "interpolation",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/interpolation_color",
            Color(0.2, 0.7, 0.3)), # A distinct green color by default
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

Language-specific directives or pragmas are another aspect that could benefit from explicit highlighting:

var pragma_pattern = "\\#[A-Za-z_]+"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()

    # Pragmas or directives
    patterns.append({
        "pattern": pragma_pattern,
        "type": "pragma",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/pragma_color",
            Color(0.6, 0.6, 0.2)), # A yellowish color for visibility
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

Lastly, for a scripting language that supports decorators or annotations that modify function behavior, differentiating them makes the code more immediately understandable:

var decorator_pattern = "@\\b[A-Za-z_]+\\b"

func _get_highlighting_patterns():
    var patterns = super()._get_highlighting_patterns()

    # Decorators
    patterns.append({
        "pattern": decorator_pattern,
        "type": "decorator",
        "color": EditorSettings.get_singleton().get("text_editor/highlighting/decorator_color",
            Color(0.8, 0.4, 0.0)), # A distinct orange color for decorators
        "custom_bg_color": Color(0, 0, 0, 0)
    })
    
    return patterns

Recognizing and highlighting these unique aspects of your custom language will make the script editor more helpful and insightful to your development process. As your language or use cases evolve, continue refining and adding new patterns to your syntax highlighting class — it’s a responsive process tailored to improve your coding experience.

By implementing these specialized highlighting rules, your scripts will become significantly easier to navigate and understand. Plus, by equipping your Godot editor with these capabilities, you’re setting yourself up to write clearer and more maintainable code. Remember, in Zenva, we always strive to arm our learners with the knowledge they need to excel in their programming journey — and mastering tools like Godot’s EditorSyntaxHighlighter is a shining example of that commitment.

Continuing Your Godot Journey

Embarking on the path of customizing and mastering the Godot 4 editor is just the beginning. We firmly believe in lifelong learning and continuous improvement, which is why we encourage you to keep expanding your game development skills. Our Godot Game Development Mini-Degree is an excellent way to dive deeper into the versatile world of Godot.

This collection of comprehensive courses will guide you through creating cross-platform games using a project-based approach, ensuring that you not only learn the theories but also apply them in practical scenarios. You’ll gain valuable hands-on experience with various game types and mechanics, from RPGs to RTS and platformers, enhancing your portfolio with a wide range of real Godot projects. Whether you’re just starting out or looking to polish your skills, our mini-degree is tailored to support your growth in the game development industry.

To explore an even broader spectrum of tools and topics in Godot, check out our extensive array of Godot courses. Each is designed to provide flexible and in-depth learning experiences that cater to both beginners and seasoned developers. Continue your journey with us at Zenva, and let us help you go from enthusiast to professional, one course at a time.

Conclusion

In wrapping up this tutorial on the intricacies of the EditorSyntaxHighlighter in Godot 4, remember that the key to efficient and enjoyable game development lies in the tools you wield. By taking the time to refine your syntax highlighting, you improve not just the aesthetics of your code, but its readability and your productivity. Never underestimate the power of a tailored coding environment as it can make all the difference in your development journey.

We hope this tutorial has sparked your curiosity and deepened your understanding of how to create a more personalized coding experience in Godot. Continue your adventure in game development with our Godot Game Development Mini-Degree, and harness the full potential of this game engine. Stick with Zenva, and let’s code the future of gaming together.

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.