Skip to content

Instantly share code, notes, and snippets.

@timsonner
Last active April 4, 2023 11:21
Show Gist options
  • Select an option

  • Save timsonner/bcd60dceb4389ae514f77e18c2074757 to your computer and use it in GitHub Desktop.

Select an option

Save timsonner/bcd60dceb4389ae514f77e18c2074757 to your computer and use it in GitHub Desktop.
C#. Unity. System.Diagnostics library. Spawn system processes, TMP_InputField and TMP_Text. Mock Terminal.
using System.Diagnostics;
using System.IO;
using System.Threading;
using TMPro;
using UnityEngine;
public class Terminal : MonoBehaviour
{
public TMP_InputField inputField;
public TMP_Text outputText;
public TMP_Text outputTextCurrentDirectory;
public TMP_Text outputTextCommandEntered;
private string currentDirectory = Directory.GetCurrentDirectory();
private Process process;
private SynchronizationContext mainThreadContext;
private Process processToKill;
private void Awake()
{
mainThreadContext = SynchronizationContext.Current;
}
private void Start()
{
inputField.onEndEdit.AddListener(SendCommand);
outputTextCurrentDirectory.text = currentDirectory;
}
private void Update()
{
if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.C))
{
// Plus 1 hack...
string killCommand = "kill " + (processToKill.Id + 1);
SendCommand(killCommand);
mainThreadContext.Post(_ => outputTextCommandEntered.text += "\n" + killCommand, null);
}
}
private void SendCommand(string command)
{
Thread thread = new(() =>
{
process = new Process();
processToKill = process;
// Handle directory changes
if (command.Split(' ')[0] == "cd")
{
currentDirectory = command[3..];
print("Changing directory to: " + currentDirectory);
mainThreadContext.Post(_ => outputTextCurrentDirectory.text = currentDirectory, null);
mainThreadContext.Post(_ => inputField.text = "", null);
}
process.StartInfo.FileName = "/bin/bash";
process.StartInfo.Arguments = "-c \"cd " + currentDirectory + " && " + command + "\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += (sender, args) =>
{
if (args.Data != null)
{
mainThreadContext.Post(_ => outputText.text += "\n" + args.Data, null);
mainThreadContext.Post(_ => outputTextCurrentDirectory.text = currentDirectory, null);
mainThreadContext.Post(_ => inputField.text = "", null);
mainThreadContext.Post(_ => outputTextCommandEntered.text += "\n" + command + " " + process.Id, null);
}
};
process.ErrorDataReceived += (sender, args) =>
{
if (args.Data != null)
{
mainThreadContext.Post(_ => outputText.text += "\n" + args.Data, null);
mainThreadContext.Post(_ => outputTextCurrentDirectory.text = currentDirectory, null);
mainThreadContext.Post(_ => inputField.text = "", null);
mainThreadContext.Post(_ => outputTextCommandEntered.text += "\n" + command + " " + process.Id, null);
}
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
});
thread.Start();
}
}
@timsonner
Copy link
Author

timsonner commented Mar 18, 2023

Todo:

  • - IO stream handling for commands like ping or top.

  • - Keyboard interupt handlers; ctrl-c for instance.

  • - Clear input field "On End Edit", eg. when user hits enter.

  • - Handle directory changes, eg. "cd ~/"

  • - Fix the way user input is parsed. A command like echo "foo" > bar breaks command call.

  • - Backround image and green text, because its kewl.

@timsonner
Copy link
Author

all items complete

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment