Last active
February 7, 2025 18:47
-
-
Save AldeRoberge/79478dbeb268fe78f1a335539be33910 to your computer and use it in GitHub Desktop.
Right click Project folder to open in terminal. Supports Linux, Mac and Windows.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using UnityEditor; | |
using UnityEngine; | |
using Debug = UnityEngine.Debug; | |
namespace ADG.Scripts.Editor | |
{ | |
public static class OpenInTerminal | |
{ | |
private const string MENU_ITEM_PATH = "Assets/Open in Terminal/"; | |
private const int MENU_PRIORITY = 1000; | |
private static readonly Dictionary<string, TerminalInfo> WindowsTerminals = new() | |
{ | |
["cmd"] = new TerminalInfo("Command Prompt", "cmd.exe", "/K cd /d \"{0}\""), | |
["cmd_admin"] = new TerminalInfo("Command Prompt (Admin)", "cmd.exe", "/K cd /d \"{0}\"", true), | |
["powershell"] = new TerminalInfo("PowerShell", "powershell.exe", "-NoExit -Command Set-Location -Path \"{0}\""), | |
["powershell_admin"] = new TerminalInfo("PowerShell (Admin)", "powershell.exe", "-NoExit -Command Set-Location -Path \"{0}\"", true), | |
["wt"] = new TerminalInfo("Windows Terminal", "wt.exe", "-d \"{0}\""), | |
}; | |
private static readonly Dictionary<string, TerminalInfo> MacTerminals = new() | |
{ | |
["terminal"] = new TerminalInfo("Terminal", "open", "-a Terminal \"{0}\""), | |
["iterm"] = new TerminalInfo("iTerm", "open", "-a iTerm \"{0}\""), | |
}; | |
private static readonly Dictionary<string, TerminalInfo> LinuxTerminals = new() | |
{ | |
["gnome-terminal"] = new TerminalInfo("GNOME Terminal", "gnome-terminal", "--working-directory=\"{0}\""), | |
["konsole"] = new TerminalInfo("Konsole", "konsole", "--workdir \"{0}\""), | |
["xterm"] = new TerminalInfo("XTerm", "xterm", "-e 'cd \"{0}\" && bash'"), | |
}; | |
private static Dictionary<string, TerminalInfo> CurrentPlatformTerminals | |
{ | |
get | |
{ | |
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | |
return WindowsTerminals; | |
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | |
return MacTerminals; | |
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) | |
return LinuxTerminals; | |
Console.WriteLine($"Unsupported platform : {RuntimeInformation.OSDescription}"); | |
return new Dictionary<string, TerminalInfo>(); | |
} | |
} | |
private static string LastUsedTerminal | |
{ | |
get => EditorPrefs.GetString("OpenInTerminal_LastUsed", GetDefaultTerminal()); | |
set => EditorPrefs.SetString("OpenInTerminal_LastUsed", value); | |
} | |
#region Menu Items | |
[MenuItem(MENU_ITEM_PATH + "Default Terminal %&t", false, MENU_PRIORITY)] | |
private static void OpenInDefaultTerminal() | |
{ | |
OpenTerminalAtPath(GetSelectedPath(), LastUsedTerminal); | |
} | |
// Windows-specific menu items | |
#if UNITY_EDITOR_WIN | |
[MenuItem(MENU_ITEM_PATH + "Command Prompt", false, MENU_PRIORITY + 1)] | |
private static void OpenInCmd() => OpenTerminalAtPath(GetSelectedPath(), "cmd"); | |
[MenuItem(MENU_ITEM_PATH + "Command Prompt (Admin)", false, MENU_PRIORITY + 2)] | |
private static void OpenInCmdAdmin() => OpenTerminalAtPath(GetSelectedPath(), "cmd_admin"); | |
[MenuItem(MENU_ITEM_PATH + "PowerShell", false, MENU_PRIORITY + 3)] | |
private static void OpenInPowerShell() => OpenTerminalAtPath(GetSelectedPath(), "powershell"); | |
[MenuItem(MENU_ITEM_PATH + "PowerShell (Admin)", false, MENU_PRIORITY + 4)] | |
private static void OpenInPowerShellAdmin() => OpenTerminalAtPath(GetSelectedPath(), "powershell_admin"); | |
[MenuItem(MENU_ITEM_PATH + "Windows Terminal", false, MENU_PRIORITY + 5)] | |
private static void OpenInWindowsTerminal() => OpenTerminalAtPath(GetSelectedPath(), "wt"); | |
#endif | |
// macOS-specific menu items | |
#if UNITY_EDITOR_OSX | |
[MenuItem(MENU_ITEM_PATH + "Terminal", false, MENU_PRIORITY + 1)] | |
private static void OpenInMacTerminal() => OpenTerminalAtPath(GetSelectedPath(), "terminal"); | |
[MenuItem(MENU_ITEM_PATH + "iTerm", false, MENU_PRIORITY + 2)] | |
private static void OpenInITerm() => OpenTerminalAtPath(GetSelectedPath(), "iterm"); | |
#endif | |
// Linux-specific menu items | |
#if UNITY_EDITOR_LINUX | |
[MenuItem(MENU_ITEM_PATH + "GNOME Terminal", false, MENU_PRIORITY + 1)] | |
private static void OpenInGnomeTerminal() => OpenTerminalAtPath(GetSelectedPath(), "gnome-terminal"); | |
[MenuItem(MENU_ITEM_PATH + "Konsole", false, MENU_PRIORITY + 2)] | |
private static void OpenInKonsole() => OpenTerminalAtPath(GetSelectedPath(), "konsole"); | |
[MenuItem(MENU_ITEM_PATH + "XTerm", false, MENU_PRIORITY + 3)] | |
private static void OpenInXTerm() => OpenTerminalAtPath(GetSelectedPath(), "xterm"); | |
#endif | |
// Validation | |
[MenuItem(MENU_ITEM_PATH + "Default Terminal %&t", true)] | |
#if UNITY_EDITOR_WIN | |
[MenuItem(MENU_ITEM_PATH + "Command Prompt", true)] | |
[MenuItem(MENU_ITEM_PATH + "Command Prompt (Admin)", true)] | |
[MenuItem(MENU_ITEM_PATH + "PowerShell", true)] | |
[MenuItem(MENU_ITEM_PATH + "PowerShell (Admin)", true)] | |
[MenuItem(MENU_ITEM_PATH + "Windows Terminal", true)] | |
#endif | |
#if UNITY_EDITOR_OSX | |
[MenuItem(MENU_ITEM_PATH + "Terminal", true)] | |
[MenuItem(MENU_ITEM_PATH + "iTerm", true)] | |
#endif | |
#if UNITY_EDITOR_LINUX | |
[MenuItem(MENU_ITEM_PATH + "GNOME Terminal", true)] | |
[MenuItem(MENU_ITEM_PATH + "Konsole", true)] | |
[MenuItem(MENU_ITEM_PATH + "XTerm", true)] | |
#endif | |
private static bool ValidateOpenTerminal() | |
{ | |
return !string.IsNullOrEmpty(GetSelectedPath()); | |
} | |
#endregion | |
#region Path Handling | |
private static string GetSelectedPath() | |
{ | |
string path = AssetDatabase.GetAssetPath(Selection.activeObject); | |
if (string.IsNullOrEmpty(path)) | |
{ | |
return Application.dataPath; | |
} | |
// Convert to full path | |
path = Path.GetFullPath(path); | |
// If it's a file, get its directory | |
if (File.Exists(path)) | |
{ | |
path = Path.GetDirectoryName(path); | |
} | |
return path; | |
} | |
#endregion | |
#region Terminal Handling | |
private static void OpenTerminalAtPath(string path, string terminalKey) | |
{ | |
if (string.IsNullOrEmpty(path)) | |
{ | |
Debug.LogError("Invalid path specified."); | |
return; | |
} | |
var terminals = CurrentPlatformTerminals; | |
if (!terminals.TryGetValue(terminalKey, out var terminalInfo)) | |
{ | |
Debug.LogError($"Unsupported terminal: {terminalKey}"); | |
return; | |
} | |
try | |
{ | |
var psi = new ProcessStartInfo | |
{ | |
FileName = terminalInfo.ExecutablePath, | |
Arguments = string.Format(terminalInfo.ArgumentsFormat, path), | |
UseShellExecute = true, | |
CreateNoWindow = false | |
}; | |
if (terminalInfo.RunAsAdmin) | |
{ | |
psi.Verb = "runas"; | |
} | |
Process.Start(psi); | |
LastUsedTerminal = terminalKey; | |
} | |
catch (Exception ex) | |
{ | |
Debug.LogError($"Failed to open terminal: {ex.Message}"); | |
} | |
} | |
private static string GetDefaultTerminal() | |
{ | |
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | |
return "wt"; | |
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | |
return "terminal"; | |
return "gnome-terminal"; | |
} | |
#endregion | |
private class TerminalInfo | |
{ | |
public string DisplayName { get; } | |
public string ExecutablePath { get; } | |
public string ArgumentsFormat { get; } | |
public bool RunAsAdmin { get; } | |
public TerminalInfo(string displayName, string executablePath, string argumentsFormat, bool runAsAdmin = false) | |
{ | |
DisplayName = displayName; | |
ExecutablePath = executablePath; | |
ArgumentsFormat = argumentsFormat; | |
RunAsAdmin = runAsAdmin; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Was written by Claude 3.5 Sonnet after some proompting.