added arrow keys to move cursor in terminal

This commit is contained in:
Brazly
2026-02-16 20:20:23 +00:00
parent a7737b10e0
commit 1c9d43a5f7
2 changed files with 87 additions and 20 deletions

View File

@@ -46,6 +46,12 @@ func _input(event: InputEvent) -> void:
KEY_DOWN:
terminal.NavigateHistory(-1)
KEY_LEFT:
terminal.MoveCursorLeft()
KEY_RIGHT:
terminal.MoveCursorRight()
if event.unicode > 31:
var character = char(event.unicode)

View File

@@ -8,9 +8,11 @@ class_name TerminalControls
@onready var scroll: ScrollContainer = $MarginContainer/ScrollContainer
@export var terminalLine: RichTextLabel
var terminalHistory: Array[String] = []
var terminalHistory: Array[String] = [""]
var historyIndex: int = -1
var cursorIndexFromEnd: int = 0
var command: String
var directory: String = "~/"
var fileSystem: Dictionary = {
@@ -37,7 +39,7 @@ func _ready() -> void:
func _on_caret_timer_timeout() -> void:
caret.visible = !caret.visible
func reset_blink() -> void:
func ResetBlink() -> void:
caret.visible = true
blink_timer.start() # Resets the countdown
@@ -45,19 +47,37 @@ func reset_blink() -> void:
func InputChar(input) -> void:
if input == null:
return
else:
command = input
terminalLine.text += command
var fullText = terminalLine.text
var insertPos = fullText.length() - cursorIndexFromEnd
var before = fullText.left(insertPos)
var after = fullText.right(cursorIndexFromEnd)
terminalLine.text = before + input + after
UpdateCaretPos()
await get_tree().physics_frame
reset_blink()
ResetBlink()
func InputDelChar() -> void:
if terminalLine.text.length() > ("user@work " + directory).length() + 1:
terminalLine.text = terminalLine.text.left(-1)
var minLength = ("user@work " + directory).length() + 1
if terminalLine.text.length() <= minLength:
return
var fullText = terminalLine.text
var deletePos = fullText.length() - cursorIndexFromEnd
if deletePos > minLength:
var before = fullText.left(deletePos - 1)
var after = fullText.right(cursorIndexFromEnd)
terminalLine.text = before + after
UpdateCaretPos()
await get_tree().physics_frame
reset_blink()
ResetBlink()
func EnterCommand() -> void:
var fullText = terminalLine.text
@@ -70,6 +90,7 @@ func EnterCommand() -> void:
if userInput != "":
terminalHistory.append(userInput)
historyIndex = 0
cursorIndexFromEnd = 0
match parts[0]:
"ls", "list":
@@ -123,6 +144,33 @@ func EnterCommand() -> void:
UpdateCaretPos()
GetBottomScroll()
func MoveCursorLeft():
var full_text = terminalLine.get_parsed_text()
var last_newline_pos = full_text.rfind("\n")
# The prompt starts after the last newline (or at 0 if it's the first line)
var prompt_start_index = last_newline_pos + 1 if last_newline_pos != -1 else 0
var prompt_length = ("user@work " + directory + " ").length()
# The absolute index we aren't allowed to go before
var min_allowed_index = prompt_start_index + prompt_length
# Calculate current target index
var current_target = full_text.length() - cursorIndexFromEnd
if current_target > min_allowed_index:
cursorIndexFromEnd += 1
UpdateCaretPos()
ResetBlink()
func MoveCursorRight():
cursorIndexFromEnd = clampi(cursorIndexFromEnd - 1, 0, terminalLine.text.length())
UpdateCaretPos()
ResetBlink()
# --- History and FileSystem Helpers ---
func NavigateHistory(direction: int):
@@ -243,15 +291,28 @@ func GetBottomScroll():
scroll.set_deferred("scroll_vertical", scrollMax)
func UpdateCaretPos():
await get_tree().physics_frame
var visible_text = terminalLine.get_parsed_text()
var visibleText = terminalLine.get_parsed_text()
ruler.autowrap_mode =TextServer.AUTOWRAP_WORD_SMART
ruler.text = visible_text
ruler.text = visibleText
ruler.custom_minimum_size.x = terminalLine.size.x
ruler.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
var last_char_index = ruler.text.length() - 1
var char_rect = ruler.get_character_bounds(max(0, last_char_index))
caret.position.x = char_rect.end.x + 1
caret.position.y = terminalLine.get_content_height() - 50
var totalLen = visibleText.length()
var targetIndex = clampi(totalLen - cursorIndexFromEnd, 0, totalLen)
if totalLen == 0:
caret.position = Vector2.ZERO
return
var lastCharBounds = ruler.get_character_bounds(max(0, totalLen - 1))
var targetCharBounds = ruler.get_character_bounds(targetIndex)
if cursorIndexFromEnd == 0:
caret.position.x = lastCharBounds.end.x
caret.position.y = lastCharBounds.position.y
else:
caret.position.x = targetCharBounds.position.x
caret.position.y = targetCharBounds.position.y
caret.position.x += 1