From ebb527cb8b070f9509cc7864731096ef7cbc7ee3 Mon Sep 17 00:00:00 2001 From: Leroy Hopson Date: Mon, 12 Jul 2021 23:11:28 +0700 Subject: [PATCH] Terminal panel updates - Add TerminalSettings resource. - Init/load terminal settings from terminal panel. - Add terminal context menu (i.e. right-click PopupMenu). - Add shortcut to open a new terminal Ctrl+Shift+T and make terminal panel visible. --- .gitignore | 3 + .../terminal/editor_terminal.gd | 4 ++ .../settings/default_copy_shortcut.tres | 3 + .../default_new_terminal_shortcut.tres | 11 ++++ .../settings/default_paste_shortcut.tres | 3 + .../terminal/settings/terminal_settings.gd | 59 +++++++++++++++++ .../editor_plugins/terminal/terminal_panel.gd | 64 +++++++++++++++++++ .../terminal/terminal_panel.tscn | 18 ++++++ addons/godot_xterm/plugin.gd | 4 ++ 9 files changed, 169 insertions(+) create mode 100644 addons/godot_xterm/editor_plugins/terminal/settings/default_copy_shortcut.tres create mode 100644 addons/godot_xterm/editor_plugins/terminal/settings/default_new_terminal_shortcut.tres create mode 100644 addons/godot_xterm/editor_plugins/terminal/settings/default_paste_shortcut.tres create mode 100644 addons/godot_xterm/editor_plugins/terminal/settings/terminal_settings.gd diff --git a/.gitignore b/.gitignore index 2a5e378..c47b705 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ mono_crash.* addons/WAT test/results.xml test/test_metadata.json + +# GodotXterm-specific ignores +.gdxterm diff --git a/addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd b/addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd index c150c2c..c250f2d 100644 --- a/addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd +++ b/addons/godot_xterm/editor_plugins/terminal/editor_terminal.gd @@ -68,6 +68,10 @@ func _input(event): if not has_focus(): return + if event is InputEventKey: + if event.shift: + return + # We need to handle many input events otherwise keys such as TAB, ctrl, etc. # will trigger editor shortcuts when using them in the terminal. if event is InputEventKey: diff --git a/addons/godot_xterm/editor_plugins/terminal/settings/default_copy_shortcut.tres b/addons/godot_xterm/editor_plugins/terminal/settings/default_copy_shortcut.tres new file mode 100644 index 0000000..5227ddc --- /dev/null +++ b/addons/godot_xterm/editor_plugins/terminal/settings/default_copy_shortcut.tres @@ -0,0 +1,3 @@ +[gd_resource type="ShortCut" format=2] + +[resource] diff --git a/addons/godot_xterm/editor_plugins/terminal/settings/default_new_terminal_shortcut.tres b/addons/godot_xterm/editor_plugins/terminal/settings/default_new_terminal_shortcut.tres new file mode 100644 index 0000000..1cfc702 --- /dev/null +++ b/addons/godot_xterm/editor_plugins/terminal/settings/default_new_terminal_shortcut.tres @@ -0,0 +1,11 @@ +[gd_resource type="ShortCut" load_steps=2 format=2] + +[sub_resource type="InputEventKey" id=1] +shift = true +control = true +command = true +pressed = true +scancode = 84 + +[resource] +shortcut = SubResource( 1 ) diff --git a/addons/godot_xterm/editor_plugins/terminal/settings/default_paste_shortcut.tres b/addons/godot_xterm/editor_plugins/terminal/settings/default_paste_shortcut.tres new file mode 100644 index 0000000..5227ddc --- /dev/null +++ b/addons/godot_xterm/editor_plugins/terminal/settings/default_paste_shortcut.tres @@ -0,0 +1,3 @@ +[gd_resource type="ShortCut" format=2] + +[resource] diff --git a/addons/godot_xterm/editor_plugins/terminal/settings/terminal_settings.gd b/addons/godot_xterm/editor_plugins/terminal/settings/terminal_settings.gd new file mode 100644 index 0000000..df4a7f9 --- /dev/null +++ b/addons/godot_xterm/editor_plugins/terminal/settings/terminal_settings.gd @@ -0,0 +1,59 @@ +extends Resource + +enum FileType { + USE_SHELL_ENV, + CUSTOM_FILE, +} + +enum CWDType { + USE_PROJECT_DIRECTORY, + CUSTOM_CWD, +} + +### Shortcuts ### + +export (ShortCut) var new_terminal_shortcut = preload("./default_new_terminal_shortcut.tres") +export (ShortCut) var copy_shortcut = preload("./default_copy_shortcut.tres") +export (ShortCut) var paste_shortcut = preload("./default_paste_shortcut.tres") + +### Scroll settings ### + +# The maximum amount of lines the terminal keeps in its buffer. +export var scrollback_buffer_lines := 1000 +# If true, mouse wheel up and down can be used to scroll the terminal. +export var mouse_wheel_scroll := true +# Whether or not to display scroll bar. +export var show_scroll_bar := true + +# Copy/paste settings. +export var copy_on_selection := false + +# Font settings. +export var font_size: int = 14 +export var letter_spacing: int = 0 +export var line_height: float = 1.2 +export var ctrl_scroll_to_resize_font := true + +# Bell settings. +export var visual_bell := true +export var audio_bell := true +export var bell_sound: AudioStream = preload("../../../themes/audio/bell.wav") + +# Exec args. +export (FileType) var file_type := FileType.USE_SHELL_ENV +export var custom_file := "/bin/sh" + +export (CWDType) var cwd_type := CWDType.USE_PROJECT_DIRECTORY +export var custom_cwd := "" + +export var args := PoolStringArray() + +export var use_os_env := true +export var extra_env := { + TERM = "xterm-256color", + COLORTERM = "truecolor", +} + + +func _init(p_copy_on_selection := false): + copy_on_selection = p_copy_on_selection diff --git a/addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd b/addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd index 7731d3a..9beb3bc 100644 --- a/addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd +++ b/addons/godot_xterm/editor_plugins/terminal/terminal_panel.gd @@ -8,9 +8,22 @@ tool extends Control const EditorTerminal := preload("./editor_terminal.tscn") +const TerminalSettings := preload("./settings/terminal_settings.gd") + +const SETTINGS_FILE_PATH := "res://.gdxterm/settings.tres" + +enum TerminalPopupMenuOptions { + NEW_TERMINAL = 0, + COPY = 2, + PASTE = 3, + SELECT_ALL = 4, + CLEAR = 6, + KILL_TERMINAL = 7, +} # Has access to the EditorSettings singleton so it can dynamically generate the # terminal color scheme based on editor theme settings. +var editor_plugin: EditorPlugin var editor_interface: EditorInterface onready var editor_settings: EditorSettings = editor_interface.get_editor_settings() @@ -18,9 +31,11 @@ onready var tabs: Tabs = $VBoxContainer/TabbarContainer/Tabs onready var tabbar_container: HBoxContainer = $VBoxContainer/TabbarContainer onready var add_button: ToolButton = $VBoxContainer/TabbarContainer/Tabs/AddButton onready var tab_container: TabContainer = $VBoxContainer/TabContainer +onready var terminal_popup_menu: PopupMenu = $VBoxContainer/TerminalPopupMenu onready var ready := true var _theme := Theme.new() +var _settings: TerminalSettings var _tab_container_min_size @@ -29,7 +44,22 @@ func _ready(): _update_settings() +func _load_or_create_settings() -> void: + var dir := Directory.new() + + if not dir.dir_exists(SETTINGS_FILE_PATH.get_base_dir()): + dir.make_dir(SETTINGS_FILE_PATH.get_base_dir()) + + if not dir.file_exists(SETTINGS_FILE_PATH): + var settings := TerminalSettings.new() + ResourceSaver.save(SETTINGS_FILE_PATH, settings) + + _settings = load(SETTINGS_FILE_PATH) + + func _update_settings() -> void: + _load_or_create_settings() + var editor_scale: float = editor_interface.get_editor_scale() rect_min_size = Vector2(0, tabbar_container.rect_size.y + 182) * editor_scale @@ -77,6 +107,7 @@ func _on_AddButton_pressed(): tabs.add_tab(shell.get_file()) terminal.editor_settings = editor_settings terminal.set_anchors_preset(PRESET_WIDE) + terminal.connect("gui_input", self, "_on_TabContainer_gui_input") tab_container.add_child(terminal) terminal.pty.fork(shell) terminal.grab_focus() @@ -108,3 +139,36 @@ func _notification(what): _update_terminal_tabs() NOTIFICATION_WM_FOCUS_IN: _update_terminal_tabs() + + +func _input(event: InputEvent) -> void: + if not _settings or not event.is_pressed(): + return + + if _settings.new_terminal_shortcut and _settings.new_terminal_shortcut.shortcut: + if event.shortcut_match(_settings.new_terminal_shortcut.shortcut): + editor_plugin.make_bottom_panel_item_visible(self) + _on_AddButton_pressed() + + +func _on_TabContainer_gui_input(event): + if event is InputEventMouseButton and event.button_index == BUTTON_RIGHT: + terminal_popup_menu.rect_position = event.global_position + terminal_popup_menu.popup() + + +func _on_TerminalPopupMenu_id_pressed(id): + match id: + TerminalPopupMenuOptions.NEW_TERMINAL: + _on_AddButton_pressed() + TerminalPopupMenuOptions.PASTE: + if tabs.get_tab_count() > 0: + var terminal = tab_container.get_child(tab_container.current_tab) + for i in OS.clipboard.length(): + var event = InputEventKey.new() + event.unicode = ord(OS.clipboard[i]) + event.pressed = true + terminal._gui_input(event) + TerminalPopupMenuOptions.KILL_TERMINAL: + if tabs.get_tab_count() > 0: + _on_Tabs_tab_close(tabs.current_tab) diff --git a/addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn b/addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn index d672c12..9c3146c 100644 --- a/addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn +++ b/addons/godot_xterm/editor_plugins/terminal/terminal_panel.tscn @@ -84,6 +84,12 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="PopupMenu" type="PopupMenu" parent="VBoxContainer/TabbarContainer"] +margin_left = 906.0 +margin_right = 1024.0 +margin_bottom = 88.0 +items = [ "Kill", null, 0, false, false, 0, 0, null, "", false, "Kill Others", null, 0, false, false, 1, 0, null, "", false, "Kill to the Right", null, 0, false, false, 2, 0, null, "", false, "Kill All", null, 0, false, false, 3, 0, null, "", false ] + [node name="TabContainer" type="TabContainer" parent="VBoxContainer"] margin_top = 24.0 margin_right = 1024.0 @@ -95,6 +101,18 @@ custom_constants/top_margin = 0 custom_constants/side_margin = 0 tabs_visible = false +[node name="TerminalPopupMenu" type="PopupMenu" parent="VBoxContainer"] +margin_right = 193.0 +margin_bottom = 160.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +items = [ "New Terminal [Ctrl+Shift+T]", null, 0, false, false, 0, 0, null, "", false, "", null, 0, false, true, 1, 0, null, "", true, "Copy [Ctrl+Shift+C]", null, 0, false, false, 2, 0, null, "", false, "Paste [Ctrl+Shift+V]", null, 0, false, false, 3, 0, null, "", false, "Select All", null, 0, false, true, 4, 0, null, "", false, "", null, 0, false, false, 5, 0, null, "", true, "Clear", null, 0, false, true, 6, 0, null, "", false, "Kill Terminal", null, 0, false, false, 7, 0, null, "", false ] +__meta__ = { +"_edit_use_anchors_": false +} + [connection signal="tab_changed" from="VBoxContainer/TabbarContainer/Tabs" to="." method="_on_Tabs_tab_changed"] [connection signal="tab_close" from="VBoxContainer/TabbarContainer/Tabs" to="." method="_on_Tabs_tab_close"] [connection signal="pressed" from="VBoxContainer/TabbarContainer/Tabs/AddButton" to="." method="_on_AddButton_pressed"] +[connection signal="gui_input" from="VBoxContainer/TabContainer" to="." method="_on_TabContainer_gui_input"] +[connection signal="id_pressed" from="VBoxContainer/TerminalPopupMenu" to="." method="_on_TerminalPopupMenu_id_pressed"] diff --git a/addons/godot_xterm/plugin.gd b/addons/godot_xterm/plugin.gd index f6b5222..e3930d7 100644 --- a/addons/godot_xterm/plugin.gd +++ b/addons/godot_xterm/plugin.gd @@ -24,7 +24,10 @@ func _enter_tree(): "X11", "Server", "OSX": pty_script = load("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd") add_custom_type("PTY", "Node", pty_script, pty_icon) + var terminal_settings_script = preload("./editor_plugins/terminal/settings/terminal_settings.gd") + add_custom_type("TerminalSettings", "Resource", terminal_settings_script, null) terminal_panel = preload("./editor_plugins/terminal/terminal_panel.tscn").instance() + terminal_panel.editor_plugin = self terminal_panel.editor_interface = get_editor_interface() add_control_to_bottom_panel(terminal_panel, "Terminal") @@ -38,5 +41,6 @@ func _exit_tree(): if pty_supported: remove_custom_type("PTY") + remove_custom_type("TerminalSettings") remove_control_from_bottom_panel(terminal_panel) terminal_panel.free()