You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.4 KiB
138 lines
4.4 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Linq; |
|
using Unity.CodeEditor; |
|
|
|
namespace VSCodeEditor |
|
{ |
|
public interface IDiscovery |
|
{ |
|
CodeEditor.Installation[] PathCallback(); |
|
} |
|
|
|
public class VSCodeDiscovery : IDiscovery |
|
{ |
|
List<CodeEditor.Installation> m_Installations; |
|
|
|
public CodeEditor.Installation[] PathCallback() |
|
{ |
|
if (m_Installations == null) |
|
{ |
|
m_Installations = new List<CodeEditor.Installation>(); |
|
FindInstallationPaths(); |
|
} |
|
|
|
return m_Installations.ToArray(); |
|
} |
|
|
|
void FindInstallationPaths() |
|
{ |
|
string[] possiblePaths = |
|
#if UNITY_EDITOR_OSX |
|
{ |
|
"/Applications/Visual Studio Code.app", |
|
"/Applications/Visual Studio Code - Insiders.app" |
|
}; |
|
#elif UNITY_EDITOR_WIN |
|
{ |
|
GetProgramFiles() + @"/Microsoft VS Code/bin/code.cmd", |
|
GetProgramFiles() + @"/Microsoft VS Code/Code.exe", |
|
GetProgramFiles() + @"/Microsoft VS Code Insiders/bin/code-insiders.cmd", |
|
GetProgramFiles() + @"/Microsoft VS Code Insiders/Code.exe", |
|
GetLocalAppData() + @"/Programs/Microsoft VS Code/bin/code.cmd", |
|
GetLocalAppData() + @"/Programs/Microsoft VS Code/Code.exe", |
|
GetLocalAppData() + @"/Programs/Microsoft VS Code Insiders/bin/code-insiders.cmd", |
|
GetLocalAppData() + @"/Programs/Microsoft VS Code Insiders/Code.exe", |
|
}; |
|
#else |
|
{ |
|
"/usr/bin/code", |
|
"/bin/code", |
|
"/usr/local/bin/code", |
|
"/var/lib/flatpak/exports/bin/com.visualstudio.code", |
|
"/snap/current/bin/code", |
|
"/snap/bin/code" |
|
}; |
|
#endif |
|
var existingPaths = possiblePaths.Where(VSCodeExists).ToList(); |
|
if (!existingPaths.Any()) |
|
{ |
|
return; |
|
} |
|
|
|
var lcp = GetLongestCommonPrefix(existingPaths); |
|
switch (existingPaths.Count) |
|
{ |
|
case 1: |
|
{ |
|
var path = existingPaths.First(); |
|
m_Installations = new List<CodeEditor.Installation> |
|
{ |
|
new CodeEditor.Installation |
|
{ |
|
Path = path, |
|
Name = path.Contains("Insiders") |
|
? "Visual Studio Code Insiders" |
|
: "Visual Studio Code" |
|
} |
|
}; |
|
break; |
|
} |
|
case 2 when existingPaths.Any(path => !(path.Substring(lcp.Length).Contains("/") || path.Substring(lcp.Length).Contains("\\"))): |
|
{ |
|
goto case 1; |
|
} |
|
default: |
|
{ |
|
m_Installations = existingPaths.Select(path => new CodeEditor.Installation |
|
{ |
|
Name = $"Visual Studio Code Insiders ({path.Substring(lcp.Length)})", |
|
Path = path |
|
}).ToList(); |
|
|
|
break; |
|
} |
|
} |
|
} |
|
|
|
#if UNITY_EDITOR_WIN |
|
static string GetProgramFiles() |
|
{ |
|
return Environment.GetEnvironmentVariable("ProgramFiles")?.Replace("\\", "/"); |
|
} |
|
|
|
static string GetLocalAppData() |
|
{ |
|
return Environment.GetEnvironmentVariable("LOCALAPPDATA")?.Replace("\\", "/"); |
|
} |
|
#endif |
|
|
|
static string GetLongestCommonPrefix(List<string> paths) |
|
{ |
|
var baseLength = paths.First().Length; |
|
for (var pathIndex = 1; pathIndex < paths.Count; pathIndex++) |
|
{ |
|
baseLength = Math.Min(baseLength, paths[pathIndex].Length); |
|
for (var i = 0; i < baseLength; i++) |
|
{ |
|
if (paths[pathIndex][i] == paths[0][i]) continue; |
|
|
|
baseLength = i; |
|
break; |
|
} |
|
} |
|
|
|
return paths[0].Substring(0, baseLength); |
|
} |
|
|
|
static bool VSCodeExists(string path) |
|
{ |
|
#if UNITY_EDITOR_OSX |
|
return System.IO.Directory.Exists(path); |
|
#else |
|
return new FileInfo(path).Exists; |
|
#endif |
|
} |
|
} |
|
}
|
|
|