Geen omschrijving
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.

VSCodeDiscovery.cs 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Unity.CodeEditor;
  6. namespace VSCodeEditor
  7. {
  8. public interface IDiscovery
  9. {
  10. CodeEditor.Installation[] PathCallback();
  11. }
  12. public class VSCodeDiscovery : IDiscovery
  13. {
  14. List<CodeEditor.Installation> m_Installations;
  15. public CodeEditor.Installation[] PathCallback()
  16. {
  17. if (m_Installations == null)
  18. {
  19. m_Installations = new List<CodeEditor.Installation>();
  20. FindInstallationPaths();
  21. }
  22. return m_Installations.ToArray();
  23. }
  24. void FindInstallationPaths()
  25. {
  26. string[] possiblePaths =
  27. #if UNITY_EDITOR_OSX
  28. {
  29. "/Applications/Visual Studio Code.app",
  30. "/Applications/Visual Studio Code - Insiders.app"
  31. };
  32. #elif UNITY_EDITOR_WIN
  33. {
  34. GetProgramFiles() + @"/Microsoft VS Code/bin/code.cmd",
  35. GetProgramFiles() + @"/Microsoft VS Code/Code.exe",
  36. GetProgramFiles() + @"/Microsoft VS Code Insiders/bin/code-insiders.cmd",
  37. GetProgramFiles() + @"/Microsoft VS Code Insiders/Code.exe",
  38. GetLocalAppData() + @"/Programs/Microsoft VS Code/bin/code.cmd",
  39. GetLocalAppData() + @"/Programs/Microsoft VS Code/Code.exe",
  40. GetLocalAppData() + @"/Programs/Microsoft VS Code Insiders/bin/code-insiders.cmd",
  41. GetLocalAppData() + @"/Programs/Microsoft VS Code Insiders/Code.exe",
  42. };
  43. #else
  44. {
  45. "/usr/bin/code",
  46. "/bin/code",
  47. "/usr/local/bin/code",
  48. "/var/lib/flatpak/exports/bin/com.visualstudio.code",
  49. "/snap/current/bin/code",
  50. "/snap/bin/code"
  51. };
  52. #endif
  53. var existingPaths = possiblePaths.Where(VSCodeExists).ToList();
  54. if (!existingPaths.Any())
  55. {
  56. return;
  57. }
  58. var lcp = GetLongestCommonPrefix(existingPaths);
  59. switch (existingPaths.Count)
  60. {
  61. case 1:
  62. {
  63. var path = existingPaths.First();
  64. m_Installations = new List<CodeEditor.Installation>
  65. {
  66. new CodeEditor.Installation
  67. {
  68. Path = path,
  69. Name = path.Contains("Insiders")
  70. ? "Visual Studio Code Insiders"
  71. : "Visual Studio Code"
  72. }
  73. };
  74. break;
  75. }
  76. case 2 when existingPaths.Any(path => !(path.Substring(lcp.Length).Contains("/") || path.Substring(lcp.Length).Contains("\\"))):
  77. {
  78. goto case 1;
  79. }
  80. default:
  81. {
  82. m_Installations = existingPaths.Select(path => new CodeEditor.Installation
  83. {
  84. Name = $"Visual Studio Code Insiders ({path.Substring(lcp.Length)})",
  85. Path = path
  86. }).ToList();
  87. break;
  88. }
  89. }
  90. }
  91. #if UNITY_EDITOR_WIN
  92. static string GetProgramFiles()
  93. {
  94. return Environment.GetEnvironmentVariable("ProgramFiles")?.Replace("\\", "/");
  95. }
  96. static string GetLocalAppData()
  97. {
  98. return Environment.GetEnvironmentVariable("LOCALAPPDATA")?.Replace("\\", "/");
  99. }
  100. #endif
  101. static string GetLongestCommonPrefix(List<string> paths)
  102. {
  103. var baseLength = paths.First().Length;
  104. for (var pathIndex = 1; pathIndex < paths.Count; pathIndex++)
  105. {
  106. baseLength = Math.Min(baseLength, paths[pathIndex].Length);
  107. for (var i = 0; i < baseLength; i++)
  108. {
  109. if (paths[pathIndex][i] == paths[0][i]) continue;
  110. baseLength = i;
  111. break;
  112. }
  113. }
  114. return paths[0].Substring(0, baseLength);
  115. }
  116. static bool VSCodeExists(string path)
  117. {
  118. #if UNITY_EDITOR_OSX
  119. return System.IO.Directory.Exists(path);
  120. #else
  121. return new FileInfo(path).Exists;
  122. #endif
  123. }
  124. }
  125. }