diff --git a/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd
new file mode 100644
index 0000000..b90cdc6
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd
@@ -0,0 +1,129 @@
+## Quick setup wizard window that we display when the user first enables the
+## plugin.
+@tool
+class_name QuickSetupWindow
+extends Window
+
+enum ButtonActions {
+ HELP,
+ REPORT_ISSUE,
+ INSTALL_UPDATE,
+ UNINSTALL,
+ UPDATE_ADDON,
+ OPEN_WEBSITE,
+}
+enum Settings {
+ FORMAT_ON_SAVE,
+ LINT_ON_SAVE,
+}
+
+signal button_pressed(action: ButtonActions)
+signal setting_change_requested(setting: Settings, value: Variant)
+
+@onready var _addon_version_label: Label = %AddonVersionLabel
+@onready var _formatter_version_label: Label = %FormatterVersionLabel
+
+@onready var _docs_button: Button = %DocsButton
+@onready var _issues_button: Button = %IssuesButton
+@onready var _formatter_install_button: Button = %FormatterInstallButton
+@onready var _formatter_uninstall_button: Button = %FormatterUninstallButton
+@onready var _addon_install_button: Button = %AddonInstallButton
+@onready var _format_on_save_toggle: CheckButton = %FormatOnSaveToggle
+@onready var _lint_on_save_toggle: CheckButton = %LintOnSaveToggle
+@onready var _quick_settings_icon: TextureRect = %QuickSettingsIcon
+@onready var _resources_icon: TextureRect = %ResourcesIcon
+@onready var _logo: TextureButton = %Logo
+
+var _addon_version := "-"
+var _formatter_version := "-"
+var _setting_states := { }
+
+
+func _ready() -> void:
+ var is_editing_scene := (Engine.is_editor_hint() and get_tree().edited_scene_root == self)
+ if not is_editing_scene:
+ var editor_scale := EditorInterface.get_editor_scale()
+ var button_icon_size := roundi(16.0 * editor_scale)
+ var section_icon_size := Vector2.ONE * 18.0 * editor_scale
+ _logo.custom_minimum_size = Vector2(96.0, 29.6) * editor_scale
+ for button: Button in [
+ _addon_install_button,
+ _formatter_install_button,
+ _formatter_uninstall_button,
+ _docs_button,
+ _issues_button,
+ ]:
+ button.add_theme_constant_override("icon_max_width", button_icon_size)
+ _quick_settings_icon.custom_maximum_size = section_icon_size
+ _resources_icon.custom_maximum_size = section_icon_size
+ _logo.pressed.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.OPEN_WEBSITE),
+ )
+
+ _addon_version_label.text = _addon_version
+ _formatter_version_label.text = _formatter_version
+
+ close_requested.connect(
+ func() -> void:
+ hide(),
+ )
+ _docs_button.button_down.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.HELP),
+ )
+ _issues_button.button_down.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.REPORT_ISSUE),
+ )
+ _formatter_install_button.button_down.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.INSTALL_UPDATE),
+ )
+ _formatter_uninstall_button.button_down.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.UNINSTALL),
+ )
+ _addon_install_button.button_down.connect(
+ func() -> void:
+ button_pressed.emit(ButtonActions.UPDATE_ADDON),
+ )
+ _format_on_save_toggle.toggled.connect(
+ func(state: bool) -> void:
+ setting_change_requested.emit(Settings.FORMAT_ON_SAVE, state),
+ )
+ _lint_on_save_toggle.toggled.connect(
+ func(state: bool) -> void:
+ setting_change_requested.emit(Settings.LINT_ON_SAVE, state),
+ )
+
+ _update_setting_ui()
+
+
+func set_addon_version(version: String) -> void:
+ _addon_version = version
+ if is_node_ready():
+ _addon_version_label.text = _addon_version
+
+
+func set_formatter_version(version: String) -> void:
+ _formatter_version = version
+ _formatter_uninstall_button.disabled = _formatter_version == "-"
+ if is_node_ready():
+ _formatter_version_label.text = _formatter_version
+
+
+func set_setting_state(setting: Settings, value: Variant) -> void:
+ _setting_states.set(setting, value)
+ if is_node_ready():
+ _update_setting_ui()
+
+
+func _update_setting_ui() -> void:
+ if _setting_states.has(Settings.FORMAT_ON_SAVE):
+ var state = _setting_states.get(Settings.FORMAT_ON_SAVE)
+ _format_on_save_toggle.button_pressed = state == true
+
+ if _setting_states.has(Settings.LINT_ON_SAVE):
+ var state = _setting_states.get(Settings.LINT_ON_SAVE)
+ _lint_on_save_toggle.button_pressed = state == true
diff --git a/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd.uid b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd.uid
new file mode 100644
index 0000000..386254a
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd.uid
@@ -0,0 +1 @@
+uid://chtdytdwey3un
diff --git a/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.tscn b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.tscn
new file mode 100644
index 0000000..3af9dda
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/editor/quick_setup_window.tscn
@@ -0,0 +1,418 @@
+[gd_scene format=3 uid="uid://2ffo6diluqkm"]
+
+[ext_resource type="Script" uid="uid://chtdytdwey3un" path="res://addons/GDQuest_GDScript_formatter/editor/quick_setup_window.gd" id="1_cku6i"]
+[ext_resource type="Texture2D" uid="uid://cp5vhsg54dmt5" path="res://addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg" id="1_hq2xi"]
+[ext_resource type="Texture2D" uid="uid://pfs8d8babvcu" path="res://addons/GDQuest_GDScript_formatter/images/icons/download.svg" id="3_cku6i"]
+[ext_resource type="Texture2D" uid="uid://bgwq4as8xi47j" path="res://addons/GDQuest_GDScript_formatter/images/icons/resources.svg" id="4_2dn7m"]
+[ext_resource type="Texture2D" uid="uid://ctpras52nelx3" path="res://addons/GDQuest_GDScript_formatter/images/icons/link.svg" id="4_yrmdb"]
+[ext_resource type="Texture2D" uid="uid://c25vn7jgshggh" path="res://addons/GDQuest_GDScript_formatter/images/icons/trash.svg" id="5_cx1jr"]
+[ext_resource type="Texture2D" uid="uid://dp30pekmsn6tt" path="res://addons/GDQuest_GDScript_formatter/images/icons/settings.svg" id="5_lrwqi"]
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2dn7m"]
+content_margin_left = 16.0
+content_margin_top = 16.0
+content_margin_right = 16.0
+content_margin_bottom = 16.0
+bg_color = Color(0.105882354, 0.105882354, 0.105882354, 1)
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cku6i"]
+content_margin_left = 4.0
+content_margin_top = 4.0
+content_margin_right = 12.0
+content_margin_bottom = 4.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_top_left = 8
+corner_radius_bottom_left = 8
+
+[sub_resource type="SystemFont" id="SystemFont_cx1jr"]
+font_names = PackedStringArray("Monospace")
+font_weight = 600
+subpixel_positioning = 0
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hq2xi"]
+content_margin_left = 4.0
+content_margin_top = 4.0
+content_margin_right = 12.0
+content_margin_bottom = 4.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_top_right = 8
+corner_radius_bottom_right = 8
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0pdmk"]
+content_margin_left = 8.0
+content_margin_top = 8.0
+content_margin_right = 8.0
+content_margin_bottom = 8.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_top_left = 8
+corner_radius_top_right = 8
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ciixy"]
+content_margin_left = 8.0
+content_margin_top = 8.0
+content_margin_right = 8.0
+content_margin_bottom = 8.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_bottom_right = 8
+corner_radius_bottom_left = 8
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yrmdb"]
+content_margin_left = 8.0
+content_margin_top = 8.0
+content_margin_right = 8.0
+content_margin_bottom = 8.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_top_left = 8
+corner_radius_top_right = 8
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cx1jr"]
+content_margin_left = 8.0
+content_margin_top = 8.0
+content_margin_right = 8.0
+content_margin_bottom = 8.0
+bg_color = Color(0.13333334, 0.13333334, 0.13333334, 1)
+corner_radius_bottom_right = 8
+corner_radius_bottom_left = 8
+
+[node name="QuickSetupWindow" type="Window" unique_id=1090372278]
+oversampling_override = 1.0
+title = "Quick setup"
+initial_position = 1
+size = Vector2i(432, 332)
+visible = false
+wrap_controls = true
+unresizable = true
+minimize_disabled = true
+maximize_disabled = true
+keep_title_visible = true
+script = ExtResource("1_cku6i")
+
+[node name="Container" type="PanelContainer" parent="." unique_id=1370421606]
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_styles/panel = SubResource("StyleBoxFlat_2dn7m")
+metadata/_edit_use_anchors_ = true
+
+[node name="Layout" type="VBoxContainer" parent="Container" unique_id=1291116102]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_constants/separation = 16
+
+[node name="Heading" type="VBoxContainer" parent="Container/Layout" unique_id=262249124]
+layout_mode = 2
+theme_override_constants/separation = 8
+
+[node name="Description" type="Label" parent="Container/Layout/Heading" unique_id=1472081466]
+unique_name_in_owner = true
+custom_minimum_size = Vector2(400, 0)
+layout_mode = 2
+size_flags_vertical = 0
+text = "Review the formatter version and choose the options you want to use."
+horizontal_alignment = 1
+vertical_alignment = 1
+autowrap_mode = 3
+
+[node name="Versions" type="HBoxContainer" parent="Container/Layout" unique_id=1913214120]
+layout_mode = 2
+size_flags_vertical = 0
+accessibility_name = "Versions"
+accessibility_description = "Addon and formatter versions"
+theme_override_constants/separation = 1
+accessibility_region = true
+
+[node name="Addon" type="PanelContainer" parent="Container/Layout/Versions" unique_id=502298473]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Addon version"
+accessibility_described_by_nodes = Array[NodePath]([NodePath("Layout/Meta/AddonVersionLabel")])
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("Layout/Meta/Title")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_cku6i")
+accessibility_region = true
+
+[node name="Layout" type="HBoxContainer" parent="Container/Layout/Versions/Addon" unique_id=330984618]
+layout_mode = 2
+theme_override_constants/separation = 16
+
+[node name="Meta" type="VBoxContainer" parent="Container/Layout/Versions/Addon/Layout" unique_id=1191408725]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme_override_constants/separation = -4
+
+[node name="Title" type="Label" parent="Container/Layout/Versions/Addon/Layout/Meta" unique_id=2142585577]
+layout_mode = 2
+size_flags_vertical = 0
+text = "Addon version"
+
+[node name="AddonVersionLabel" type="Label" parent="Container/Layout/Versions/Addon/Layout/Meta" unique_id=473625867]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_vertical = 0
+accessibility_live = 1
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("../Title")])
+theme_override_fonts/font = SubResource("SystemFont_cx1jr")
+text = "-"
+
+[node name="AddonInstallButton" type="Button" parent="Container/Layout/Versions/Addon/Layout" unique_id=866644622]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_vertical = 4
+tooltip_text = "Download the latest version
+from GitHub"
+theme_override_constants/icon_max_width = 16
+icon = ExtResource("4_yrmdb")
+icon_alignment = 1
+
+[node name="Formatter" type="PanelContainer" parent="Container/Layout/Versions" unique_id=64248743]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Formatter version"
+accessibility_described_by_nodes = Array[NodePath]([NodePath("Layout/Meta/FormatterVersionLabel")])
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("Layout/Meta/Title")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_hq2xi")
+accessibility_region = true
+
+[node name="Layout" type="HBoxContainer" parent="Container/Layout/Versions/Formatter" unique_id=1203026614]
+layout_mode = 2
+theme_override_constants/separation = 16
+
+[node name="Meta" type="VBoxContainer" parent="Container/Layout/Versions/Formatter/Layout" unique_id=376277655]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme_override_constants/separation = -4
+
+[node name="Title" type="Label" parent="Container/Layout/Versions/Formatter/Layout/Meta" unique_id=523014360]
+layout_mode = 2
+size_flags_vertical = 3
+text = "Formatter version"
+
+[node name="FormatterVersionLabel" type="Label" parent="Container/Layout/Versions/Formatter/Layout/Meta" unique_id=413169287]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_vertical = 2
+accessibility_live = 1
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("../Title")])
+theme_override_fonts/font = SubResource("SystemFont_cx1jr")
+text = "-"
+
+[node name="Actions" type="HBoxContainer" parent="Container/Layout/Versions/Formatter/Layout" unique_id=1352071696]
+layout_mode = 2
+size_flags_vertical = 4
+
+[node name="FormatterInstallButton" type="Button" parent="Container/Layout/Versions/Formatter/Layout/Actions" unique_id=44883375]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 4
+tooltip_text = "Installs or updates
+the formatter"
+theme_override_constants/icon_max_width = 16
+icon = ExtResource("3_cku6i")
+icon_alignment = 1
+
+[node name="FormatterUninstallButton" type="Button" parent="Container/Layout/Versions/Formatter/Layout/Actions" unique_id=905387703]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 4
+tooltip_text = "Removes the formatter
+from your system"
+theme_override_constants/icon_max_width = 16
+disabled = true
+icon = ExtResource("5_cx1jr")
+icon_alignment = 1
+
+[node name="SplitPanel" type="HBoxContainer" parent="Container/Layout" unique_id=451807448]
+layout_mode = 2
+theme_override_constants/separation = 8
+
+[node name="QuickSettings" type="VBoxContainer" parent="Container/Layout/SplitPanel" unique_id=762058636]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Resources"
+theme_override_constants/separation = 4
+accessibility_region = true
+
+[node name="Heading" type="HBoxContainer" parent="Container/Layout/SplitPanel/QuickSettings" unique_id=1746249992]
+layout_mode = 2
+size_flags_vertical = 0
+tooltip_text = "Quick access to the most
+commonly used settings.
+
+Need more? Find them
+under your Editor Settings."
+theme_override_constants/separation = 0
+
+[node name="QuickSettingsIcon" type="TextureRect" parent="Container/Layout/SplitPanel/QuickSettings/Heading" unique_id=29259362]
+unique_name_in_owner = true
+custom_maximum_size = Vector2(18, 18)
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 4
+texture = ExtResource("5_lrwqi")
+
+[node name="Label" type="Label" parent="Container/Layout/SplitPanel/QuickSettings/Heading" unique_id=1029108396]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 0
+theme_type_variation = &"HeaderSmall"
+text = "Quick settings"
+
+[node name="Items" type="VBoxContainer" parent="Container/Layout/SplitPanel/QuickSettings" unique_id=1642592454]
+layout_mode = 2
+theme_override_constants/separation = 1
+
+[node name="FormatOnSave" type="PanelContainer" parent="Container/Layout/SplitPanel/QuickSettings/Items" unique_id=1031168548]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+accessibility_name = "Format on save"
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_0pdmk")
+accessibility_region = true
+
+[node name="FormatOnSaveToggle" type="CheckButton" parent="Container/Layout/SplitPanel/QuickSettings/Items/FormatOnSave" unique_id=454317394]
+unique_name_in_owner = true
+layout_mode = 2
+tooltip_text = "Formats your code
+when the file is saved"
+text = "Format on save"
+flat = true
+
+[node name="LintOnSave" type="PanelContainer" parent="Container/Layout/SplitPanel/QuickSettings/Items" unique_id=1914659548]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+accessibility_name = "Lint on save"
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_ciixy")
+accessibility_region = true
+
+[node name="LintOnSaveToggle" type="CheckButton" parent="Container/Layout/SplitPanel/QuickSettings/Items/LintOnSave" unique_id=1467833312]
+unique_name_in_owner = true
+layout_mode = 2
+tooltip_text = "Checks your code
+for common mistakes when
+the file is saved"
+text = "Lint on save"
+flat = true
+
+[node name="Resources" type="VBoxContainer" parent="Container/Layout/SplitPanel" unique_id=455407789]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Resources"
+theme_override_constants/separation = 4
+accessibility_region = true
+
+[node name="Heading" type="HBoxContainer" parent="Container/Layout/SplitPanel/Resources" unique_id=2022780704]
+layout_mode = 2
+size_flags_vertical = 0
+theme_override_constants/separation = 0
+
+[node name="ResourcesIcon" type="TextureRect" parent="Container/Layout/SplitPanel/Resources/Heading" unique_id=2118555130]
+unique_name_in_owner = true
+custom_maximum_size = Vector2(18, 18)
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 4
+texture = ExtResource("4_2dn7m")
+
+[node name="Label" type="Label" parent="Container/Layout/SplitPanel/Resources/Heading" unique_id=545106214]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 0
+theme_type_variation = &"HeaderSmall"
+text = "Resources"
+
+[node name="Items" type="VBoxContainer" parent="Container/Layout/SplitPanel/Resources" unique_id=1998613279]
+layout_mode = 2
+theme_override_constants/separation = 1
+
+[node name="Docs" type="PanelContainer" parent="Container/Layout/SplitPanel/Resources/Items" unique_id=1340727308]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Documentation"
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("HBoxContainer/Meta/Title")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_yrmdb")
+accessibility_region = true
+
+[node name="HBoxContainer" type="HBoxContainer" parent="Container/Layout/SplitPanel/Resources/Items/Docs" unique_id=1417773300]
+layout_mode = 2
+size_flags_vertical = 0
+theme_override_constants/separation = 16
+
+[node name="Meta" type="VBoxContainer" parent="Container/Layout/SplitPanel/Resources/Items/Docs/HBoxContainer" unique_id=1182312636]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme_override_constants/separation = 0
+
+[node name="Title" type="Label" parent="Container/Layout/SplitPanel/Resources/Items/Docs/HBoxContainer/Meta" unique_id=764405891]
+layout_mode = 2
+size_flags_vertical = 3
+text = "Documentation"
+
+[node name="DocsButton" type="Button" parent="Container/Layout/SplitPanel/Resources/Items/Docs/HBoxContainer" unique_id=419240940]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_vertical = 4
+tooltip_text = "View documentation"
+theme_override_constants/icon_max_width = 16
+icon = ExtResource("4_yrmdb")
+icon_alignment = 1
+
+[node name="Issues" type="PanelContainer" parent="Container/Layout/SplitPanel/Resources/Items" unique_id=905390970]
+layout_mode = 2
+size_flags_horizontal = 3
+accessibility_name = "Issue tracker"
+accessibility_labeled_by_nodes = Array[NodePath]([NodePath("HBoxContainer/Meta/Title")])
+theme_override_styles/panel = SubResource("StyleBoxFlat_cx1jr")
+accessibility_region = true
+
+[node name="HBoxContainer" type="HBoxContainer" parent="Container/Layout/SplitPanel/Resources/Items/Issues" unique_id=910490745]
+layout_mode = 2
+size_flags_vertical = 4
+theme_override_constants/separation = 16
+
+[node name="Meta" type="VBoxContainer" parent="Container/Layout/SplitPanel/Resources/Items/Issues/HBoxContainer" unique_id=1364135114]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 4
+theme_override_constants/separation = 0
+
+[node name="Title" type="Label" parent="Container/Layout/SplitPanel/Resources/Items/Issues/HBoxContainer/Meta" unique_id=1975650866]
+layout_mode = 2
+size_flags_vertical = 2
+text = "Issue tracker"
+
+[node name="IssuesButton" type="Button" parent="Container/Layout/SplitPanel/Resources/Items/Issues/HBoxContainer" unique_id=1505520439]
+unique_name_in_owner = true
+layout_mode = 2
+size_flags_vertical = 4
+tooltip_text = "Report an issue"
+accessibility_name = "Report an issue"
+theme_override_constants/icon_max_width = 16
+icon = ExtResource("4_yrmdb")
+icon_alignment = 1
+
+[node name="Branding" type="CenterContainer" parent="Container/Layout" unique_id=1129641325]
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 8
+
+[node name="Logo" type="TextureButton" parent="Container/Layout/Branding" unique_id=1596880248]
+unique_name_in_owner = true
+custom_minimum_size = Vector2(96, 29.6)
+layout_mode = 2
+tooltip_text = "Visit GDQuest"
+mouse_default_cursor_shape = 2
+texture_normal = ExtResource("1_hq2xi")
+ignore_texture_size = true
+stretch_mode = 4
diff --git a/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg b/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg
new file mode 100644
index 0000000..6e5d120
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg
@@ -0,0 +1,27 @@
+
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg.import b/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg.import
new file mode 100644
index 0000000..6a253d2
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cp5vhsg54dmt5"
+path="res://.godot/imported/gdquest_logo.svg-3d69df92bc1269a9cd56d21bfb4e3dfd.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/gdquest_logo.svg"
+dest_files=["res://.godot/imported/gdquest_logo.svg-3d69df92bc1269a9cd56d21bfb4e3dfd.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/download.svg b/addons/GDQuest_GDScript_formatter/images/icons/download.svg
new file mode 100644
index 0000000..66d6681
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/download.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/download.svg.import b/addons/GDQuest_GDScript_formatter/images/icons/download.svg.import
new file mode 100644
index 0000000..bebee33
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/download.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://pfs8d8babvcu"
+path="res://.godot/imported/download.svg-d338a54db5cab704099d1a1b2a18a684.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/icons/download.svg"
+dest_files=["res://.godot/imported/download.svg-d338a54db5cab704099d1a1b2a18a684.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/link.svg b/addons/GDQuest_GDScript_formatter/images/icons/link.svg
new file mode 100644
index 0000000..10da18e
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/link.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/link.svg.import b/addons/GDQuest_GDScript_formatter/images/icons/link.svg.import
new file mode 100644
index 0000000..3b897af
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/link.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ctpras52nelx3"
+path="res://.godot/imported/link.svg-b137df11cbc30e911fb0835645149fef.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/icons/link.svg"
+dest_files=["res://.godot/imported/link.svg-b137df11cbc30e911fb0835645149fef.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/resources.svg b/addons/GDQuest_GDScript_formatter/images/icons/resources.svg
new file mode 100644
index 0000000..3ca9445
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/resources.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/resources.svg.import b/addons/GDQuest_GDScript_formatter/images/icons/resources.svg.import
new file mode 100644
index 0000000..cde1d0d
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/resources.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bgwq4as8xi47j"
+path="res://.godot/imported/resources.svg-c9d73a79fde4a2d7e788a9b272643ba4.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/icons/resources.svg"
+dest_files=["res://.godot/imported/resources.svg-c9d73a79fde4a2d7e788a9b272643ba4.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/settings.svg b/addons/GDQuest_GDScript_formatter/images/icons/settings.svg
new file mode 100644
index 0000000..c840125
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/settings.svg.import b/addons/GDQuest_GDScript_formatter/images/icons/settings.svg.import
new file mode 100644
index 0000000..228391e
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/settings.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dp30pekmsn6tt"
+path="res://.godot/imported/settings.svg-62cf3e99083bed9344103ef46d33eb2a.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/icons/settings.svg"
+dest_files=["res://.godot/imported/settings.svg-62cf3e99083bed9344103ef46d33eb2a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/trash.svg b/addons/GDQuest_GDScript_formatter/images/icons/trash.svg
new file mode 100644
index 0000000..a0052a0
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/trash.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/GDQuest_GDScript_formatter/images/icons/trash.svg.import b/addons/GDQuest_GDScript_formatter/images/icons/trash.svg.import
new file mode 100644
index 0000000..cba6eb3
--- /dev/null
+++ b/addons/GDQuest_GDScript_formatter/images/icons/trash.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c25vn7jgshggh"
+path="res://.godot/imported/trash.svg-a9a6e3eec301ddf3c41ade5e7d043c57.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/GDQuest_GDScript_formatter/images/icons/trash.svg"
+dest_files=["res://.godot/imported/trash.svg-a9a6e3eec301ddf3c41ade5e7d043c57.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=2.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/addons/GDQuest_GDScript_formatter/menu.gd b/addons/GDQuest_GDScript_formatter/menu.gd
index 1818cf3..65f71fe 100644
--- a/addons/GDQuest_GDScript_formatter/menu.gd
+++ b/addons/GDQuest_GDScript_formatter/menu.gd
@@ -1,19 +1,30 @@
## This module handles adding a menu to the script editor with formatter commands.
## It safely locates the script editor's menu bar and adds our custom menu.
@tool
+class_name FormatterMenu
extends Node
-signal menu_item_selected(command: String)
+enum MenuActions {
+ FORMAT_SCRIPT,
+ LINT_SCRIPT,
+ REORDER_CODE,
+ INSTALL_UPDATE,
+ UNINSTALL,
+ REPORT_ISSUE,
+ HELP,
+}
+
+signal menu_item_selected(action: MenuActions)
const MENU_TEXT = "Format"
const MENU_ITEMS = {
- "format_script": "Format Current Script",
- "lint_script": "Lint Current Script",
- "reorder_code": "Reorder Code",
- "install_update": "Install or Update Formatter",
- "uninstall": "Uninstall Formatter",
- "report_issue": "Report Issue",
- "help": "Help",
+ MenuActions.FORMAT_SCRIPT: "Format Current Script",
+ MenuActions.LINT_SCRIPT: "Lint Current Script",
+ MenuActions.REORDER_CODE: "Reorder Code",
+ MenuActions.INSTALL_UPDATE: "Install or Update Formatter",
+ MenuActions.UNINSTALL: "Uninstall Formatter",
+ MenuActions.REPORT_ISSUE: "Report Issue",
+ MenuActions.HELP: "Help",
}
var menu_button: MenuButton = null
@@ -101,21 +112,21 @@ func _populate_menu(show_uninstall: bool = true) -> void:
var current_item_index := 0
- popup_menu.add_item(MENU_ITEMS["format_script"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "format_script")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.FORMAT_SCRIPT], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.FORMAT_SCRIPT)
popup_menu.set_item_tooltip(
current_item_index,
"Run the GDScript Formatter over the current script",
)
current_item_index += 1
- popup_menu.add_item(MENU_ITEMS["lint_script"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "lint_script")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.LINT_SCRIPT], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.LINT_SCRIPT)
popup_menu.set_item_tooltip(current_item_index, "Check the current script for linting issues")
current_item_index += 1
- popup_menu.add_item(MENU_ITEMS["reorder_code"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "reorder_code")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.REORDER_CODE], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.REORDER_CODE)
popup_menu.set_item_tooltip(
current_item_index,
"Reorder the code elements in the current script according to the GDScript Style Guide",
@@ -127,8 +138,8 @@ func _populate_menu(show_uninstall: bool = true) -> void:
# That's why we have to increase it even on separators. Otherwise the
# tooltip will lose sync.
current_item_index += 2
- popup_menu.add_item(MENU_ITEMS["install_update"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "install_update")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.INSTALL_UPDATE], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.INSTALL_UPDATE)
popup_menu.set_item_tooltip(
current_item_index,
"Download the latest version of the GDScript Formatter",
@@ -136,8 +147,8 @@ func _populate_menu(show_uninstall: bool = true) -> void:
if show_uninstall:
current_item_index += 1
- popup_menu.add_item(MENU_ITEMS["uninstall"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "uninstall")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.UNINSTALL], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.UNINSTALL)
popup_menu.set_item_tooltip(
current_item_index,
"Remove the GDScript Formatter installed through this add-on from your computer",
@@ -147,13 +158,13 @@ func _populate_menu(show_uninstall: bool = true) -> void:
# Bumped index by 1 extra step because of the previous separator.
current_item_index += 2
- popup_menu.add_item(MENU_ITEMS["report_issue"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "report_issue")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.REPORT_ISSUE], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.REPORT_ISSUE)
popup_menu.set_item_tooltip(current_item_index, "Tell us about problems or bugs you found")
current_item_index += 1
- popup_menu.add_item(MENU_ITEMS["help"], current_item_index)
- popup_menu.set_item_metadata(current_item_index, "help")
+ popup_menu.add_item(MENU_ITEMS[MenuActions.HELP], current_item_index)
+ popup_menu.set_item_metadata(current_item_index, MenuActions.HELP)
popup_menu.set_item_tooltip(current_item_index, "Learn how to use the GDScript Formatter")
@@ -161,6 +172,5 @@ func _on_menu_item_pressed(id: int) -> void:
if not is_instance_valid(popup_menu):
return
- var command: String = popup_menu.get_item_metadata(id)
- if not command.is_empty():
- menu_item_selected.emit(command)
+ var action: MenuActions = popup_menu.get_item_metadata(id)
+ menu_item_selected.emit(action)
diff --git a/addons/GDQuest_GDScript_formatter/plugin.gd b/addons/GDQuest_GDScript_formatter/plugin.gd
index b143eb3..22e3a3f 100644
--- a/addons/GDQuest_GDScript_formatter/plugin.gd
+++ b/addons/GDQuest_GDScript_formatter/plugin.gd
@@ -10,6 +10,7 @@ extends EditorPlugin
const FormatterInstaller = preload("install_and_update.gd")
const FormatterMenu = preload("menu.gd")
+const QuickSetupWindowScene = preload("editor/quick_setup_window.tscn")
const EDITOR_SETTINGS_CATEGORY = "gdquest_gdscript_formatter/"
const SETTING_FORMAT_ON_SAVE = "format_on_save"
@@ -69,6 +70,7 @@ var DEFAULT_SETTINGS = {
SETTING_IGNORED_DIRECTORIES: PackedStringArray(["addons/"]),
}
+
## Which gutter lint icons are shown in.
## By default, gutter 0 is for breakpoints and 1 is for things like overrides.
const GUTTER_LINT_ICON_INDEX = 2
@@ -78,18 +80,23 @@ var connection_list: Array[Resource] = []
var installer: FormatterInstaller = null
var formatter_cache_dir: String
var menu: FormatterMenu = null
+var quick_setup_window: QuickSetupWindow = null
var _has_uninstall_command := false
var _has_formatter_command := false
var _has_format_command := false
var _has_lint_command := false
var _already_warned_about_reorder_on_save := false
var _already_warned_about_builtin_format_on_save := false
+var _setting_updated_via_quick_setup := false
# Used to auto detect changes to the project's .editorconfig file.
var _editorconfig_last_modified_time := -1
# Editorconfig allows setting rules per path glob. We track globs for the format
# on save rule here so users can enable it selectively for specific folders.
var _editorconfig_format_on_save_rules: Array[Dictionary] = []
+# Used to detect the formatter
+const FORMATTER_BINARY_NAME = "gdscript-formatter"
+
func _init() -> void:
migrate_format_mode_setting()
@@ -168,6 +175,26 @@ func migrate_format_mode_setting() -> void:
version = 2
+func _enable_plugin() -> void:
+ # This is called by Godot when the user enables the plugin in their project
+ # settings. Here we get version information about the formator program and
+ # the plugin itself to show in the quick setup window.
+ var plugin_config := ConfigFile.new()
+ var config_loaded := plugin_config.load(
+ get_script().resource_path.get_base_dir() + "/plugin.cfg"
+ )
+ if config_loaded == OK:
+ var addon_version = plugin_config.get_value("plugin", "version")
+ if addon_version:
+ quick_setup_window.set_addon_version(addon_version)
+ else:
+ push_error("Unable to load plugin config")
+
+ _update_formatter_version()
+ quick_setup_window.popup_centered()
+ _update_quick_setup_settings_display()
+
+
func _enter_tree() -> void:
formatter_cache_dir = EditorInterface.get_editor_paths().get_cache_dir().path_join("gdquest")
installer = FormatterInstaller.new(formatter_cache_dir)
@@ -183,6 +210,9 @@ func _enter_tree() -> void:
return
add_format_command()
add_lint_command()
+
+ _update_formatter_version()
+
# After installing the formatter we can add the menu option to show the uninstall command
if is_instance_valid(menu):
menu.update_menu(true),
@@ -192,6 +222,30 @@ func _enter_tree() -> void:
push_error("Formatter installation failed: ", error_message),
)
+ quick_setup_window = QuickSetupWindowScene.instantiate() as QuickSetupWindow
+ add_child(quick_setup_window)
+ quick_setup_window.button_pressed.connect(
+ func(action: QuickSetupWindow.ButtonActions) -> void:
+ match action:
+ QuickSetupWindow.ButtonActions.INSTALL_UPDATE:
+ installer.install_or_update_formatter()
+ QuickSetupWindow.ButtonActions.UNINSTALL:
+ uninstall_formatter()
+ QuickSetupWindow.ButtonActions.REPORT_ISSUE:
+ report_issue()
+ QuickSetupWindow.ButtonActions.HELP:
+ show_help()
+ QuickSetupWindow.ButtonActions.UPDATE_ADDON:
+ update_addon()
+ QuickSetupWindow.ButtonActions.OPEN_WEBSITE:
+ OS.shell_open("https://www.gdquest.com/")
+ )
+ quick_setup_window.setting_change_requested.connect(
+ func(setting: QuickSetupWindow.Settings, value: Variant) -> void:
+ _setting_updated_via_quick_setup = true
+ set_editor_setting(_get_quick_setup_setting_name(setting), value),
+ )
+
_has_formatter_command = has_command(get_editor_setting(SETTING_FORMATTER_PATH))
add_format_command()
add_lint_command()
@@ -208,6 +262,21 @@ func _enter_tree() -> void:
resource_saved.connect(_on_resource_saved)
+func _update_quick_setup_settings_display() -> void:
+ for setting: QuickSetupWindow.Settings in [QuickSetupWindow.Settings.FORMAT_ON_SAVE, QuickSetupWindow.Settings.LINT_ON_SAVE]:
+ var state = get_editor_setting(_get_quick_setup_setting_name(setting))
+ quick_setup_window.set_setting_state(setting, state)
+
+
+func _get_quick_setup_setting_name(setting: QuickSetupWindow.Settings) -> String:
+ match setting:
+ QuickSetupWindow.Settings.FORMAT_ON_SAVE:
+ return SETTING_FORMAT_ON_SAVE
+ QuickSetupWindow.Settings.LINT_ON_SAVE:
+ return SETTING_LINT_ON_SAVE
+ return ""
+
+
func _exit_tree() -> void:
resource_saved.disconnect(_on_resource_saved)
@@ -220,6 +289,9 @@ func _exit_tree() -> void:
installer.queue_free()
installer = null
+ quick_setup_window.queue_free()
+ quick_setup_window = null
+
if is_instance_valid(menu):
menu.menu_item_selected.disconnect(_on_menu_item_selected)
menu.remove_formatter_menu()
@@ -227,6 +299,15 @@ func _exit_tree() -> void:
menu = null
+func _notification(what: int) -> void:
+ var has_settings_changed = what == EditorSettings.NOTIFICATION_EDITOR_SETTINGS_CHANGED
+
+ if has_settings_changed and not _setting_updated_via_quick_setup:
+ _update_quick_setup_settings_display()
+
+ _setting_updated_via_quick_setup = false
+
+
func _shortcut_input(event: InputEvent) -> void:
var shortcut := get_editor_setting(SETTING_SHORTCUT) as Shortcut
if not is_instance_valid(shortcut):
@@ -550,6 +631,38 @@ func has_command(command: String) -> bool:
return exit_code == OK
+func _get_binary_path() -> String:
+ var binary_name := FORMATTER_BINARY_NAME
+
+ if OS.get_name().to_lower().contains("windows"):
+ binary_name = binary_name + ".exe"
+
+ return formatter_cache_dir.path_join(binary_name)
+
+
+func _update_formatter_version() -> void:
+ var binary_path = _get_binary_path()
+ if not FileAccess.file_exists(binary_path):
+ return
+
+ var version_stdout: Array = []
+ var exit_code = OS.execute(binary_path, ["--version"], version_stdout)
+ if exit_code != OK:
+ return
+
+ var formatter_version := ""
+ for index in version_stdout.size():
+ formatter_version += version_stdout[index]
+ if formatter_version.begins_with(FORMATTER_BINARY_NAME):
+ formatter_version = formatter_version.trim_prefix(FORMATTER_BINARY_NAME)
+ formatter_version = formatter_version.strip_edges()
+
+ if not formatter_version:
+ return
+
+ quick_setup_window.set_formatter_version(formatter_version)
+
+
func is_formatter_available() -> bool:
if _has_formatter_command:
return true
@@ -558,18 +671,12 @@ func is_formatter_available() -> bool:
func is_formatter_installed_locally() -> bool:
- var binary_name := "gdscript-formatter"
- if OS.get_name().to_lower().contains("windows"):
- binary_name = "gdscript-formatter.exe"
- var binary_path := formatter_cache_dir.path_join(binary_name)
+ var binary_path = _get_binary_path()
return FileAccess.file_exists(binary_path)
func uninstall_formatter() -> void:
- var binary_name := "gdscript-formatter"
- if OS.get_name().to_lower().contains("windows"):
- binary_name = "gdscript-formatter.exe"
- var binary_path := formatter_cache_dir.path_join(binary_name)
+ var binary_path = _get_binary_path()
if FileAccess.file_exists(binary_path):
DirAccess.remove_absolute(binary_path)
@@ -582,6 +689,7 @@ func uninstall_formatter() -> void:
add_format_command()
remove_uninstall_command()
add_uninstall_command()
+ quick_setup_window.set_formatter_version("-")
if is_instance_valid(menu):
menu.update_menu(false)
else:
@@ -617,24 +725,26 @@ func show_help() -> void:
OS.shell_open("https://www.gdquest.com/library/gdscript_formatter/")
-func _on_menu_item_selected(command: String) -> void:
- match command:
- "format_script":
+func update_addon() -> void:
+ OS.shell_open("https://github.com/GDQuest/GDScript-formatter/releases")
+
+
+func _on_menu_item_selected(action: FormatterMenu.MenuActions) -> void:
+ match action:
+ FormatterMenu.MenuActions.FORMAT_SCRIPT:
format_current_script()
- "lint_script":
+ FormatterMenu.MenuActions.LINT_SCRIPT:
lint_current_script()
- "reorder_code":
+ FormatterMenu.MenuActions.REORDER_CODE:
reorder_code()
- "install_update":
+ FormatterMenu.MenuActions.INSTALL_UPDATE:
installer.install_or_update_formatter()
- "uninstall":
+ FormatterMenu.MenuActions.UNINSTALL:
uninstall_formatter()
- "report_issue":
+ FormatterMenu.MenuActions.REPORT_ISSUE:
report_issue()
- "help":
+ FormatterMenu.MenuActions.HELP:
show_help()
- _:
- push_warning("Unsupported command sent from the menu: " + command)
## Reloads the code editor with new text while preserving editor state.