Skip to content

Instantly share code, notes, and snippets.

@nekomimi-daimao
Last active May 16, 2023 09:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekomimi-daimao/8b9da4c1180604cb67a521c356a49990 to your computer and use it in GitHub Desktop.
Save nekomimi-daimao/8b9da4c1180604cb67a521c356a49990 to your computer and use it in GitHub Desktop.
Execute shell from UnityEditor
#if UNITY_EDITOR
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
// ReSharper disable MergeIntoNegatedPattern
// ReSharper disable once CheckNamespace
// ReSharper disable once IdentifierTypo
namespace Nekomimi.Daimao
{
public sealed class ShellExecutor : EditorWindow
{
#region GUI
[MenuItem("Window/ShellExecutor")]
private static void OpenWindow()
{
GetWindow<ShellExecutor>(nameof(ShellExecutor));
}
private void OnEnable()
{
SearchShell();
}
private static void Separator(int length = 4)
{
GUILayout.Box(string.Empty, GUILayout.ExpandWidth(true), GUILayout.Height(length));
}
private Vector2 _scrollPosition = Vector2.zero;
private void OnGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Result");
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
{
if (GUILayout.Button(nameof(ClearResult)))
{
ClearResult();
}
if (GUILayout.Button("CopyClipboard"))
{
GUIUtility.systemCopyBuffer = Result;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.LabelField(_currentShell);
Separator();
EditorGUILayout.LabelField(Result,
GUILayout.MinHeight(80),
GUILayout.ExpandHeight(true)
);
Separator();
EditorGUILayout.LabelField("Options");
_option = EditorGUILayout.TextField(_option);
EditorGUILayout.Space();
EditorGUILayout.LabelField("ShellList");
EditorGUILayout.Space();
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
foreach (var fileInfo in _shellArray)
{
if (GUILayout.Button(fileInfo.Name))
{
ExecuteShell(fileInfo, _option);
}
}
EditorGUILayout.EndScrollView();
}
#endregion
#region Result
private string _result = nameof(Result);
private string Result
{
get => _result;
set
{
if (string.Equals(_result, value))
{
return;
}
Repaint();
_result = value;
}
}
private void ClearResult()
{
Result = string.Empty;
_currentShell = string.Empty;
}
private string _currentShell;
#endregion
#region ExecuteShell
private const int ProcessLimitMs = 60000;
private string _option;
private void ExecuteShell(FileSystemInfo fileInfo, string option)
{
ClearResult();
_currentShell = fileInfo.Name;
Result = fileInfo.Name;
var psi = new ProcessStartInfo
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WorkingDirectory = Application.dataPath,
FileName = "sh",
Arguments = $"{fileInfo.FullName} {option}"
};
try
{
using var process = Process.Start(psi);
if (process == null)
{
return;
}
process.WaitForExit(ProcessLimitMs);
Result = process.StandardOutput.ReadToEnd();
}
catch (Exception e)
{
Result = e.ToString();
}
}
#endregion
#region SearchShell
private FileInfo[] _shellArray = Array.Empty<FileInfo>();
private void SearchShell()
{
var shellDir =
new DirectoryInfo(Application.dataPath).Parent?.CreateSubdirectory("Shell");
if (shellDir == null || !shellDir.Exists)
{
return;
}
_shellArray = shellDir.GetFiles("*.sh");
}
#endregion
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment