From 18a4b02c3eeaa768e5ec2151a960d8208ad4b3b8 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Fri, 23 Feb 2024 12:09:03 +0000 Subject: [PATCH] Add script formatting plugin Requires gdtoolkit to be installed on the system --- addons/format_on_save/LICENSE | 21 ++++++++ addons/format_on_save/format_on_save.gd | 70 +++++++++++++++++++++++++ addons/format_on_save/plugin.cfg | 6 +++ project.godot | 2 +- 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 addons/format_on_save/LICENSE create mode 100644 addons/format_on_save/format_on_save.gd create mode 100644 addons/format_on_save/plugin.cfg diff --git a/addons/format_on_save/LICENSE b/addons/format_on_save/LICENSE new file mode 100644 index 0000000..250f450 --- /dev/null +++ b/addons/format_on_save/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ryan Haskell-Glatz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/format_on_save/format_on_save.gd b/addons/format_on_save/format_on_save.gd new file mode 100644 index 0000000..e5ba809 --- /dev/null +++ b/addons/format_on_save/format_on_save.gd @@ -0,0 +1,70 @@ +@tool +class_name FormatOnSave extends EditorPlugin + +const SUCCESS: int = 0 +const AUTO_RELOAD_SETTING: String = "text_editor/behavior/files/auto_reload_scripts_on_external_change" +var original_auto_reload_setting: bool + + +# LIFECYCLE EVENTS +func _enter_tree(): + activate_auto_reload_setting() + resource_saved.connect(on_resource_saved) + + +func _exit_tree(): + resource_saved.disconnect(on_resource_saved) + restore_original_auto_reload_setting() + + +# CALLED WHEN A SCRIPT IS SAVED +func on_resource_saved(resource: Resource): + if resource is Script: + var script: Script = resource + var current_script = get_editor_interface().get_script_editor().get_current_script() + var text_edit: CodeEdit = ( + get_editor_interface().get_script_editor().get_current_editor().get_base_editor() + ) + + # Prevents other unsaved scripts from overwriting the active one + if current_script == script: + var filepath: String = ProjectSettings.globalize_path(resource.resource_path) + + # Run gdformat + var exit_code = OS.execute("gdformat", [filepath]) + + # Replace source_code with formatted source_code + if exit_code == SUCCESS: + var formatted_source = FileAccess.get_file_as_string(resource.resource_path) + FormatOnSave.reload_script(text_edit, formatted_source) + + +# Workaround until this PR is merged: +# https://github.com/godotengine/godot/pull/83267 +# Thanks, @KANAjetzt 💖 +static func reload_script(text_edit: TextEdit, source_code: String) -> void: + var column := text_edit.get_caret_column() + var row := text_edit.get_caret_line() + var scroll_position_h := text_edit.get_h_scroll_bar().value + var scroll_position_v := text_edit.get_v_scroll_bar().value + + text_edit.text = source_code + text_edit.set_caret_column(column) + text_edit.set_caret_line(row) + text_edit.scroll_horizontal = scroll_position_h + text_edit.scroll_vertical = scroll_position_v + + text_edit.tag_saved_version() + + +# For this workaround to work, we need to disable the "Reload/Resave" pop-up +func activate_auto_reload_setting(): + var settings := get_editor_interface().get_editor_settings() + original_auto_reload_setting = settings.get(AUTO_RELOAD_SETTING) + settings.set(AUTO_RELOAD_SETTING, true) + + +# If the plugin is disabled, let's attempt to restore the original editor setting +func restore_original_auto_reload_setting(): + var settings := get_editor_interface().get_editor_settings() + settings.set(AUTO_RELOAD_SETTING, original_auto_reload_setting) diff --git a/addons/format_on_save/plugin.cfg b/addons/format_on_save/plugin.cfg new file mode 100644 index 0000000..0fec65c --- /dev/null +++ b/addons/format_on_save/plugin.cfg @@ -0,0 +1,6 @@ +[plugin] +name="Format on Save" +description="Runs `gdformat` on save to automatically format your GD script as you code." +author="Ryan Haskell-Glatz" +version="1.2.0" +script="format_on_save.gd" diff --git a/project.godot b/project.godot index 7830548..56274df 100644 --- a/project.godot +++ b/project.godot @@ -29,7 +29,7 @@ project/assembly_name="Character Controller" [editor_plugins] -enabled=PackedStringArray("res://addons/qodot/plugin.cfg") +enabled=PackedStringArray("res://addons/format_on_save/plugin.cfg", "res://addons/qodot/plugin.cfg") [input]