12 Commits

Author SHA1 Message Date
boxqkrtm
8c1a4ac3e0 docs: update package.json
- Update version to 2.0.26
- Update changelog for workspace support
2025-11-02 13:06:17 +09:00
yahui.han
84578b3b24 code-workspace 2025-11-02 13:06:17 +09:00
boxqkrtm
38fecf55e4 Update README.md 2025-05-19 19:04:34 +09:00
boxqkrtm
284bebf8e7 Update package.json
Bump version 2.0.25
2025-05-19 18:53:11 +09:00
boxqkrtm
ff1c40049a Merge pull request #18 from zhust2003/master
Add macOS and Linux support for finding and reusing Cursor workspace instances
2025-05-19 18:52:25 +09:00
Dalton
334a52e789 Fix linux path 2025-05-10 11:56:31 +08:00
Dalton
0a7001698c Support macos and linux 2025-05-10 09:17:49 +08:00
boxqkrtm
0a98b387a9 Merge pull request #8 from zhust2003/master
feat: Support existing Cursor workspace detection (windows)
2025-04-24 13:41:37 +09:00
boxqkrtm
1228f59ed2 Update package.json
version change to 2.0.24
2025-04-24 13:41:23 +09:00
boxqkrtm
a24588a87a fix: Change package.json Name to Avoid Installation Warning 2025-04-24 13:33:25 +09:00
boxqkrtm
f1148f1205 fix: avoid launching cursor without folder context 2025-04-24 13:23:49 +09:00
Dalton
cac0c13658 Enhance Cursor instance management
Improve the handling of multiple Cursor instances by implementing better workspace detection and reuse of existing windows.
2025-03-20 18:40:05 +08:00
5 changed files with 214 additions and 14 deletions

View File

@@ -1,4 +1,10 @@
# Code Editor Package for Visual Studio
# Code Editor Package for Cursor
## [2.0.26] - 2025-11-02
Integration:
- Add workspace support
## [2.0.22] - 2023-10-03

View File

@@ -8,6 +8,13 @@ using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.ComponentModel;
using Debug = UnityEngine.Debug;
using System.IO;
using SimpleJSON;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Unity.VisualStudio.Editor
{
@@ -108,5 +115,99 @@ namespace Microsoft.Unity.VisualStudio.Editor
sb?.Append(data);
}
public static string[] GetProcessWorkspaces(Process process)
{
if (process == null)
return null;
try
{
var workspaces = new List<string>();
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string cursorStoragePath;
#if UNITY_EDITOR_OSX
cursorStoragePath = Path.Combine(userProfile, "Library", "Application Support", "cursor", "User", "workspaceStorage");
#elif UNITY_EDITOR_LINUX
cursorStoragePath = Path.Combine(userProfile, ".config", "Cursor", "User", "workspaceStorage");
#else
cursorStoragePath = Path.Combine(userProfile, "AppData", "Roaming", "cursor", "User", "workspaceStorage");
#endif
Debug.Log($"[Cursor] Looking for workspaces in: {cursorStoragePath}");
if (Directory.Exists(cursorStoragePath))
{
foreach (var workspaceDir in Directory.GetDirectories(cursorStoragePath))
{
try
{
var workspaceStatePath = Path.Combine(workspaceDir, "workspace.json");
if (File.Exists(workspaceStatePath))
{
var content = File.ReadAllText(workspaceStatePath);
if (!string.IsNullOrEmpty(content))
{
var workspace = JSONNode.Parse(content);
if (workspace != null)
{
var folder = workspace["folder"];
if (folder != null && !string.IsNullOrEmpty(folder.Value))
{
var workspacePath = folder.Value;
if (workspacePath.StartsWith("file:///"))
{
workspacePath = Uri.UnescapeDataString(workspacePath.Substring(8));
workspaces.Add(workspacePath);
}
}
}
}
}
var windowStatePath = Path.Combine(workspaceDir, "window.json");
if (File.Exists(windowStatePath))
{
var content = File.ReadAllText(windowStatePath);
if (!string.IsNullOrEmpty(content))
{
var windowState = JSONNode.Parse(content);
if (windowState != null)
{
var workspace = windowState["workspace"];
if (workspace != null && !string.IsNullOrEmpty(workspace.Value))
{
var workspacePath = workspace.Value;
if (workspacePath.StartsWith("file:///"))
{
workspacePath = Uri.UnescapeDataString(workspacePath.Substring(8));
workspaces.Add(workspacePath);
}
}
}
}
}
}
catch (Exception ex)
{
Debug.LogWarning($"[Cursor] Error reading workspace state file: {ex.Message}");
continue;
}
}
}
else
{
Debug.LogWarning($"[Cursor] Workspace storage directory not found: {cursorStoragePath}");
}
return workspaces.Distinct().ToArray();
}
catch (Exception ex)
{
Debug.LogError($"[Cursor] Error getting workspace directory: {ex.Message}");
return null;
}
}
}
}

View File

@@ -12,6 +12,7 @@ using System.Text.RegularExpressions;
using UnityEngine;
using SimpleJSON;
using IOPath = System.IO.Path;
using Debug = UnityEngine.Debug;
namespace Microsoft.Unity.VisualStudio.Editor {
internal class VisualStudioCursorInstallation : VisualStudioInstallation {
@@ -448,6 +449,73 @@ namespace Microsoft.Unity.VisualStudio.Editor {
}
}
private Process FindRunningCursorWithSolution(string solutionPath) {
var normalizedTargetPath = solutionPath.Replace('\\', '/').TrimEnd('/').ToLowerInvariant();
#if UNITY_EDITOR_WIN
// Keep as is for Windows platform since path already includes drive letter
#else
// Ensure path starts with / for macOS and Linux platforms
if (!normalizedTargetPath.StartsWith("/")) {
normalizedTargetPath = "/" + normalizedTargetPath;
}
#endif
var processes = new List<Process>();
// Get process name list based on different operating systems
#if UNITY_EDITOR_OSX
processes.AddRange(Process.GetProcessesByName("Cursor"));
processes.AddRange(Process.GetProcessesByName("Cursor Helper"));
#elif UNITY_EDITOR_LINUX
processes.AddRange(Process.GetProcessesByName("cursor"));
processes.AddRange(Process.GetProcessesByName("Cursor"));
#else
processes.AddRange(Process.GetProcessesByName("cursor"));
#endif
foreach (var process in processes) {
try {
var workspaces = ProcessRunner.GetProcessWorkspaces(process);
if (workspaces != null && workspaces.Length > 0) {
foreach (var workspace in workspaces) {
var normalizedWorkspaceDir = workspace.Replace('\\', '/').TrimEnd('/').ToLowerInvariant();
#if UNITY_EDITOR_WIN
// Keep as is for Windows platform
#else
// Ensure path starts with / for macOS and Linux platforms
if (!normalizedWorkspaceDir.StartsWith("/")) {
normalizedWorkspaceDir = "/" + normalizedWorkspaceDir;
}
#endif
if (string.Equals(normalizedWorkspaceDir, normalizedTargetPath, StringComparison.OrdinalIgnoreCase) ||
normalizedTargetPath.StartsWith(normalizedWorkspaceDir + "/", StringComparison.OrdinalIgnoreCase) ||
normalizedWorkspaceDir.StartsWith(normalizedTargetPath + "/", StringComparison.OrdinalIgnoreCase))
{
return process;
}
}
}
}
catch (Exception ex) {
Debug.LogError($"[Cursor] Error checking process: {ex}");
continue;
}
}
return null;
}
private static string TryFindWorkspace(string directory)
{
var files = Directory.GetFiles(directory, "*.code-workspace", SearchOption.TopDirectoryOnly);
if (files.Length == 0 || files.Length > 1)
return null;
return files[0];
}
public override bool Open(string path, int line, int column, string solution) {
line = Math.Max(1, line);
column = Math.Max(0, column);
@@ -455,10 +523,30 @@ namespace Microsoft.Unity.VisualStudio.Editor {
var directory = IOPath.GetDirectoryName(solution);
var application = Path;
ProcessRunner.Start(string.IsNullOrEmpty(path) ?
ProcessStartInfoFor(application, $"\"{directory}\"") :
ProcessStartInfoFor(application, $"\"{directory}\" -g \"{path}\":{line}:{column}"));
var workspace = TryFindWorkspace(directory);
workspace ??= directory;
directory = workspace;
var existingProcess = FindRunningCursorWithSolution(directory);
if (existingProcess != null) {
try {
var args = string.IsNullOrEmpty(path) ?
$"--reuse-window \"{directory}\"" :
$"--reuse-window -g \"{path}\":{line}:{column}";
ProcessRunner.Start(ProcessStartInfoFor(application, args));
return true;
}
catch (Exception ex) {
Debug.LogError($"[Cursor] Error using existing instance: {ex}");
}
}
var newArgs = string.IsNullOrEmpty(path) ?
$"--new-window \"{directory}\"" :
$"--new-window \"{directory}\" -g \"{path}\":{line}:{column}";
ProcessRunner.Start(ProcessStartInfoFor(application, newArgs));
return true;
}

View File

@@ -1,8 +1,13 @@
# How to install
<br>
- Unity->Window->Package Manager<br>
- Click "+" left corner<br>
- Add package from git URL<br>
- Insert <code>https://github.com/boxqkrtm/com.unity.ide.cursor.git</code><br>
- Add<br>
## How to install
- Unity -> Window -> Package Manager
- Click "+" at the top left corner
- Add package from git URL
- Insert `https://github.com/boxqkrtm/com.unity.ide.cursor.git`
- Add
- Done
> **Important Notice for Users Updating from Older Versions**
> Starting from version **v2.0.24**, the package name has been changed from
> `com.unity.ide.cursor` to `com.boxqkrtm.ide.cursor` to prevent potential issues with Unity regarding attribution.
> Violating these attribution rules may trigger warnings in Unity.
> If you experience errors during the update, please remove the existing package before reinstalling the new one to avoid conflicts.

View File

@@ -1,14 +1,14 @@
{
"name": "com.unity.ide.cursor",
"name": "com.boxqkrtm.ide.cursor",
"displayName": "Cursor Editor",
"description": "Cursor editor integration for supporting Cursor as code editor for unity. Adds support for generating csproj files for intellisense purposes, auto discovery of installations, etc.",
"version": "2.0.23",
"version": "2.0.26",
"unity": "2019.4",
"unityRelease": "25f1",
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
"_upm": {
"changelog": "Integration:\n\n- Add support for Cursor"
"changelog": "Integration:\n\n- Add workspace support"
}
}