oh-my-git/terminal.gd

214 lines
6 KiB
GDScript3
Raw Normal View History

2020-09-01 21:25:24 +02:00
extends Control
2020-06-10 18:25:41 +02:00
signal command_done
var thread
2020-09-01 19:59:07 +02:00
var history_position = 0
2020-09-25 12:29:48 +02:00
var git_commands = []
var git_commands_help = []
2020-09-01 19:59:07 +02:00
onready var input = $Rows/InputLine/Input
onready var output = $Rows/TopHalf/Output
onready var completions = $Rows/TopHalf/Completions
#export(NodePath) var repository_path
var repository
onready var command_dropdown = $Rows/InputLine/CommandDropdown
onready var main = get_tree().get_root().get_node("Main")
2020-09-01 21:25:24 +02:00
2020-09-14 19:25:57 +02:00
var premade_commands = [
'git commit --allow-empty -m "empty"',
'echo $RANDOM | git hash-object -w --stdin',
'git switch -c $RANDOM',
]
func _ready():
#repository.shell.connect("output", self, "receive_output")
2020-09-14 19:25:57 +02:00
for command in premade_commands:
command_dropdown.get_popup().add_item(command)
command_dropdown.get_popup().connect("id_pressed", self, "load_command")
2020-09-24 11:15:00 +02:00
var error = $TextEditor.connect("hide", self, "editor_closed")
if error != OK:
helpers.crash("Could not connect TextEditor's hide signal")
input.grab_focus()
2020-09-25 12:29:48 +02:00
var all_git_commands = game.global_shell.run("git help -a | grep \"^ \\+[a-z-]\\+ \" -o")
2020-09-25 12:29:48 +02:00
git_commands = Array(all_git_commands.split("\n"))
for i in range(git_commands.size()):
git_commands[i] = git_commands[i].strip_edges(true, true)
2020-09-25 12:29:48 +02:00
git_commands.pop_back()
var all_git_commands_help = game.global_shell.run("git help -a | grep \" [A-Z].\\+$\" -o")
git_commands_help = Array(all_git_commands_help.split("\n"))
for i in range(git_commands_help.size()):
git_commands_help[i] = git_commands_help[i].strip_edges(true, true)
git_commands_help.pop_back()
completions.hide()
2020-09-28 16:18:06 +02:00
history_position = game.state["history"].size()
2020-09-14 19:25:57 +02:00
func _input(event):
2020-09-28 16:18:06 +02:00
#print(game.state)
if game.state["history"].size() > 0:
if event.is_action_pressed("ui_up"):
if history_position > 0:
history_position -= 1
2020-09-28 16:18:06 +02:00
input.text = game.state["history"][history_position]
input.caret_position = input.text.length()
# This prevents the Input taking the arrow as a "skip to beginning" command.
get_tree().set_input_as_handled()
if event.is_action_pressed("ui_down"):
2020-09-28 16:18:06 +02:00
if history_position < game.state["history"].size()-1:
history_position += 1
2020-09-28 16:18:06 +02:00
input.text = game.state["history"][history_position]
input.caret_position = input.text.length()
get_tree().set_input_as_handled()
2020-09-28 17:10:21 +02:00
if event.is_action_pressed("tab_complete"):
if completions.visible:
completions.get_root().get_children().select(0)
get_tree().set_input_as_handled()
2020-09-14 19:25:57 +02:00
func load_command(id):
input.text = premade_commands[id]
input.caret_position = input.text.length()
func send_command(command):
2020-09-28 16:18:06 +02:00
game.state["history"].push_back(command)
game.save_state()
history_position = game.state["history"].size()
2020-09-01 19:59:07 +02:00
2020-09-11 10:33:44 +02:00
input.editable = false
completions.hide()
2020-09-11 10:33:44 +02:00
if thread != null:
thread.wait_to_finish()
thread = Thread.new()
thread.start(self, "run_command_in_a_thread", command)
func send_command_async(command):
2020-09-24 10:10:14 +02:00
#output.text += "$ "+command+"\n"
input.text = ""
2020-09-24 10:10:14 +02:00
#repository.shell.run_async(command)
$TCPServer.send(command+"\n")
func run_command_in_a_thread(command):
var o = repository.shell.run(command, false)
2020-09-01 21:25:24 +02:00
input.text = ""
input.editable = true
2020-09-29 17:05:04 +02:00
if o.length() <= 1000:
2020-09-29 17:05:04 +02:00
output.text = output.text + "$ " + command + "\n" + o
else:
$Pager/Text.text = o
$Pager.popup()
emit_signal("command_done")
#repository.update_everything()
func receive_output(text):
output.text += text
2020-09-24 10:10:14 +02:00
repository.update_everything()
func clear():
output.text = ""
2020-09-10 12:03:46 +02:00
func editor_closed():
input.grab_focus()
2020-09-25 12:04:45 +02:00
func regenerate_completions_menu(new_text):
var comp = generate_completions(new_text)
completions.clear()
var filtered_comp = []
for c in comp:
if c != new_text:
filtered_comp.push_back(c)
if filtered_comp.size() == 0:
completions.hide()
else:
completions.show()
var _root = completions.create_item()
for c in filtered_comp:
var child = completions.create_item()
child.set_text(0, c)
if c.split(" ").size() >= 2:
var subcommand = c.split(" ")[1]
var idx = git_commands.find(subcommand)
if idx >= 0:
child.set_text(1, git_commands_help[idx])
2020-09-25 12:04:45 +02:00
func relevant_subcommands():
var result = {}
2020-09-28 16:18:06 +02:00
for h in game.state["history"]:
var parts = Array(h.split(" "))
if parts[0] == "git":
var subcommand = parts[1]
if git_commands.has(subcommand):
if not result.has(subcommand):
result[subcommand] = 0
result[subcommand] += 1
# Convert to format [["add", 3], ["pull", 5]].
var result_array = []
for r in result:
result_array.push_back([r, result[r]])
result_array.sort_custom(self, "sort_by_frequency_desc")
var plain_result = []
for r in result_array:
plain_result.push_back(r[0])
return plain_result
func sort_by_frequency_desc(a, b):
return a[1] > b[1]
2020-09-25 12:04:45 +02:00
func generate_completions(command):
2020-09-28 16:52:00 +02:00
var results = []
# Collect git commands.
2020-09-25 12:04:45 +02:00
if command.substr(0, 4) == "git ":
var rest = command.substr(4)
var subcommands = relevant_subcommands()
2020-09-25 12:04:45 +02:00
for sc in subcommands:
if sc.substr(0, rest.length()) == rest:
results.push_back("git "+sc)
2020-09-28 16:52:00 +02:00
# Part 1: Only autocomplete after git subcommand.
# Part2: Prevent autocompletion to only show filename at the beginning of a command.
if !(command.substr(0,4) == "git " and command.split(" ").size() <= 2) and command.split(" ").size() > 1:
var last_word = Array(command.split(" ")).pop_back()
var file_string = repository.shell.run("find -type f")
var files = file_string.split("\n")
files = Array(files)
# The last entry is an empty string, remove it.
files.pop_back()
for file_path in files:
file_path = file_path.substr(2)
if file_path.substr(0,4) != ".git" and file_path.substr(0,last_word.length()) == last_word:
results.push_back(command+file_path.substr(last_word.length()))
return results
2020-09-25 12:04:45 +02:00
func _input_changed(new_text):
call_deferred("regenerate_completions_menu", new_text)
func _completion_selected():
var item = completions.get_selected()
input.text = item.get_text(0)
input.emit_signal("text_changed", input.text)
#completions.hide()
input.grab_focus()
input.caret_position = input.text.length()
func editor_saved():
emit_signal("command_done")