└── addons └── format_on_save ├── LICENSE ├── format_on_save.gd └── plugin.cfg /addons/format_on_save/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ryan Haskell-Glatz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /addons/format_on_save/format_on_save.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name FormatOnSave extends EditorPlugin 3 | 4 | const SUCCESS: int = 0 5 | const AUTO_RELOAD_SETTING: String = "text_editor/behavior/files/auto_reload_scripts_on_external_change" 6 | var original_auto_reload_setting: bool 7 | 8 | 9 | # LIFECYCLE EVENTS 10 | func _enter_tree(): 11 | activate_auto_reload_setting() 12 | resource_saved.connect(on_resource_saved) 13 | 14 | 15 | func _exit_tree(): 16 | resource_saved.disconnect(on_resource_saved) 17 | restore_original_auto_reload_setting() 18 | 19 | 20 | # CALLED WHEN A SCRIPT IS SAVED 21 | func on_resource_saved(resource: Resource): 22 | if resource is Script: 23 | var script: Script = resource 24 | var current_script = get_editor_interface().get_script_editor().get_current_script() 25 | var text_edit: CodeEdit = ( 26 | get_editor_interface().get_script_editor().get_current_editor().get_base_editor() 27 | ) 28 | 29 | # Prevents other unsaved scripts from overwriting the active one 30 | if current_script == script: 31 | var filepath: String = ProjectSettings.globalize_path(resource.resource_path) 32 | 33 | # Run gdformat 34 | var exit_code = OS.execute("gdformat", [filepath]) 35 | 36 | # Replace source_code with formatted source_code 37 | if exit_code == SUCCESS: 38 | var formatted_source = FileAccess.get_file_as_string(resource.resource_path) 39 | FormatOnSave.reload_script(text_edit, formatted_source) 40 | 41 | 42 | # Workaround until this PR is merged: 43 | # https://github.com/godotengine/godot/pull/83267 44 | # Thanks, @KANAjetzt 💖 45 | static func reload_script(text_edit: TextEdit, source_code: String) -> void: 46 | var column := text_edit.get_caret_column() 47 | var row := text_edit.get_caret_line() 48 | var scroll_position_h := text_edit.get_h_scroll_bar().value 49 | var scroll_position_v := text_edit.get_v_scroll_bar().value 50 | 51 | text_edit.text = source_code 52 | text_edit.set_caret_column(column) 53 | text_edit.set_caret_line(row) 54 | text_edit.scroll_horizontal = scroll_position_h 55 | text_edit.scroll_vertical = scroll_position_v 56 | 57 | text_edit.tag_saved_version() 58 | 59 | 60 | # For this workaround to work, we need to disable the "Reload/Resave" pop-up 61 | func activate_auto_reload_setting(): 62 | var settings := get_editor_interface().get_editor_settings() 63 | original_auto_reload_setting = settings.get(AUTO_RELOAD_SETTING) 64 | settings.set(AUTO_RELOAD_SETTING, true) 65 | 66 | 67 | # If the plugin is disabled, let's attempt to restore the original editor setting 68 | func restore_original_auto_reload_setting(): 69 | var settings := get_editor_interface().get_editor_settings() 70 | settings.set(AUTO_RELOAD_SETTING, original_auto_reload_setting) 71 | -------------------------------------------------------------------------------- /addons/format_on_save/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | name="Format on Save" 3 | description="Runs `gdformat` on save to automatically format your GD script as you code." 4 | author="Ryan Haskell-Glatz" 5 | version="1.2.0" 6 | script="format_on_save.gd" 7 | --------------------------------------------------------------------------------