Editor/CodeEditor.Cursor.cs
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace Editor.CodeEditors;
[Title( "Cursor" )]
public class Cursor : ICodeEditor
{
public void OpenFile( string path, int? line, int? column )
{
var codeWorkspace = $"{Environment.CurrentDirectory}/s&box.code-workspace";
CreateWorkspace( codeWorkspace );
Launch( $"\"{codeWorkspace}\" -g \"{path}:{line}:{column}\"" );
}
public void OpenSolution()
{
var codeWorkspace = $"{Environment.CurrentDirectory}/s&box.code-workspace";
CreateWorkspace( codeWorkspace );
// Need to wrap the code workspace in quotes, but CreateWorkspace doesn't need that
Launch( $"\"{codeWorkspace}\"" );
}
public void OpenAddon( Project addon )
{
var projectPath = (addon != null) ? addon.GetRootPath() : "";
Launch( $"\"{projectPath}\"" );
}
public bool IsInstalled() => !string.IsNullOrEmpty( GetLocation() );
private static void Launch( string arguments )
{
var startInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = GetLocation(),
Arguments = arguments,
CreateNoWindow = true,
};
System.Diagnostics.Process.Start( startInfo );
}
private static void CreateWorkspace( string path )
{
StringBuilder builder = new();
builder.AppendLine( "{" );
builder.AppendLine( " \"folders\": [" );
foreach ( var addon in EditorUtility.Projects.GetAll() )
{
if ( !addon.Active ) continue;
builder.AppendLine( " {" );
builder.AppendLine( $" \"name\": \"{addon.Config.Ident}\"," );
builder.AppendLine( $" \"path\": \"{addon.GetRootPath().Replace( @"\", @"\\" )}\"," );
builder.AppendLine( " }," );
}
builder.AppendLine( " ]" );
// You need the C# extension to do anything
// builder.AppendLine( " \"extensions\": {" );
// builder.AppendLine( " \"recommendations\": [" );
// builder.AppendLine( " \"ms-dotnettools.csharp\"" );
// builder.AppendLine( " ]," );
// builder.AppendLine( " }" );
// Settings: make sure we're using .net 6 and that roslyn analyzers are on (they never fucking are)
// builder.AppendLine( " \"settings\": {" );
// builder.AppendLine( " \"omnisharp.useModernNet\": true," );
// builder.AppendLine( " \"omnisharp.enableRoslynAnalyzers\": true" );
// builder.AppendLine( " }" );
builder.AppendLine( "}" );
File.WriteAllText( path, builder.ToString() );
}
static string Location;
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>" )]
private static string GetLocation()
{
if ( Location != null )
{
return Location;
}
string value = null;
using ( var key = Registry.ClassesRoot.OpenSubKey( @"Applications\\Cursor.exe\\shell\\open\\command" ) )
{
value = key?.GetValue( "" ) as string;
}
if ( value == null )
{
return null;
}
// Given `"C:\Users\<user>\AppData\Local\Programs\cursor\Cursor.exe" "%1"` grab the first bit
Regex rgx = new Regex( "\"(.*)\" \".*\"", RegexOptions.IgnoreCase );
var matches = rgx.Matches( value );
if ( matches.Count == 0 || matches[0].Groups.Count < 2 )
{
return null;
}
Location = matches[0].Groups[1].Value;
return Location;
}
}