code_review!: PR #648

* rewrite `Models.ExternalTool` to use `_execArgsGenerator` instead of `OpenCmdArgs` and `ArgTransform`
* remove dependency of `System.Linq` due to AOT limitations
* since the `Visual Studio` is only available on Windows, use `TryAdd` directly.
* update `README.md`

BREAKING CHANGE: now the key in `external_editors.json` uses the same name with external tool.

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2024-11-04 10:02:20 +08:00
parent 1d0098703e
commit 6b348fbd1a
No known key found for this signature in database
3 changed files with 59 additions and 59 deletions

View file

@ -119,15 +119,15 @@ For other AI service:
This app supports open repository in external tools listed in the table below. This app supports open repository in external tools listed in the table below.
| Tool | Windows | macOS | Linux | KEY IN `external_editors.json` | | Tool | Windows | macOS | Linux |
|-------------------------------|---------|-------|-------|--------------------------------| |-------------------------------|---------|-------|-------|
| Visual Studio Code | YES | YES | YES | VSCODE | | Visual Studio Code | YES | YES | YES |
| Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS | | Visual Studio Code - Insiders | YES | YES | YES |
| VSCodium | YES | YES | YES | VSCODIUM | | VSCodium | YES | YES | YES |
| JetBrains Fleet | YES | YES | YES | FLEET | | Fleet | YES | YES | YES |
| Sublime Text | YES | YES | YES | SUBLIME_TEXT | | Sublime Text | YES | YES | YES |
| Zed | NO | YES | YES | ZED | | Zed | NO | YES | YES |
| Visual Studio | YES | YES | YES | VISUALSTUDIO | | Visual Studio | YES | NO | NO |
> [!NOTE] > [!NOTE]
> This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app. > This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app.
@ -135,7 +135,7 @@ This app supports open repository in external tools listed in the table below.
```json ```json
{ {
"tools": { "tools": {
"VSCODE": "D:\\VSCode\\Code.exe" "Visual Studio Code": "D:\\VSCode\\Code.exe"
} }
} }
``` ```

View file

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -14,17 +13,13 @@ namespace SourceGit.Models
public class ExternalTool public class ExternalTool
{ {
public string Name { get; private set; } public string Name { get; private set; }
public string Executable { get; private set; }
public string OpenCmdArgs { get; private set; }
public Bitmap IconImage { get; private set; } = null; public Bitmap IconImage { get; private set; } = null;
public Func<string, string> ArgTransform { get; private set; }
public ExternalTool(string name, string icon, string executable, string openCmdArgs, Func<string, string> argsTransform) public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null)
{ {
Name = name; Name = name;
Executable = executable; _execFile = execFile;
OpenCmdArgs = openCmdArgs; _execArgsGenerator = execArgsGenerator ?? (repo => $"\"{repo}\"");
ArgTransform = argsTransform ?? ((s) => s);
try try
{ {
@ -40,19 +35,17 @@ namespace SourceGit.Models
public void Open(string repo) public void Open(string repo)
{ {
string arguments = string.Format(OpenCmdArgs, repo);
if (ArgTransform != null)
arguments = ArgTransform.Invoke(arguments);
Process.Start(new ProcessStartInfo() Process.Start(new ProcessStartInfo()
{ {
WorkingDirectory = repo, WorkingDirectory = repo,
FileName = Executable, FileName = _execFile,
Arguments = arguments, Arguments = _execArgsGenerator.Invoke(repo),
UseShellExecute = false, UseShellExecute = false,
}); });
} }
private string _execFile = string.Empty;
private Func<string, string> _execArgsGenerator = null;
} }
public class JetBrainsState public class JetBrainsState
@ -118,67 +111,48 @@ namespace SourceGit.Models
_customPaths = new ExternalToolPaths(); _customPaths = new ExternalToolPaths();
} }
public void TryAdd(string name, string icon, string args, string key, Func<string> finder, Func<string, string> argsTransform = null) public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)
{ {
if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath)) if (_customPaths.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
{ {
Founded.Add(new ExternalTool(name, icon, customPath, args, argsTransform)); Founded.Add(new ExternalTool(name, icon, customPath, execArgsGenerator));
} }
else else
{ {
var path = finder(); var path = finder();
if (!string.IsNullOrEmpty(path) && File.Exists(path)) if (!string.IsNullOrEmpty(path) && File.Exists(path))
Founded.Add(new ExternalTool(name, icon, path, args, argsTransform)); Founded.Add(new ExternalTool(name, icon, path, execArgsGenerator));
} }
} }
public void VSCode(Func<string> platformFinder) public void VSCode(Func<string> platformFinder)
{ {
TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder); TryAdd("Visual Studio Code", "vscode", platformFinder);
} }
public void VSCodeInsiders(Func<string> platformFinder) public void VSCodeInsiders(Func<string> platformFinder)
{ {
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS", platformFinder); TryAdd("Visual Studio Code - Insiders", "vscode_insiders", platformFinder);
} }
public void VSCodium(Func<string> platformFinder) public void VSCodium(Func<string> platformFinder)
{ {
TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder); TryAdd("VSCodium", "codium", platformFinder);
} }
public void Fleet(Func<string> platformFinder) public void Fleet(Func<string> platformFinder)
{ {
TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder); TryAdd("Fleet", "fleet", platformFinder);
} }
public void SublimeText(Func<string> platformFinder) public void SublimeText(Func<string> platformFinder)
{ {
TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT", platformFinder); TryAdd("Sublime Text", "sublime_text", platformFinder);
} }
public void Zed(Func<string> platformFinder) public void Zed(Func<string> platformFinder)
{ {
TryAdd("Zed", "zed", "\"{0}\"", "ZED", platformFinder); TryAdd("Zed", "zed", platformFinder);
}
public void VisualStudio(Func<string> platformFinder)
{
TryAdd("Visual Studio", "vs", "\"{0}\"", "VISUALSTUDIO", platformFinder, VisualStudioTryFindSolution);
}
private static string VisualStudioTryFindSolution(string path)
{
try
{
if (Directory.GetFiles(path.Trim('\"'), "*.sln", SearchOption.AllDirectories).FirstOrDefault() is string solutionPath)
return Path.GetFullPath(solutionPath);
}
catch
{
// do nothing
}
return path;
} }
public void FindJetBrainsFromToolbox(Func<string> platformFinder) public void FindJetBrainsFromToolbox(Func<string> platformFinder)
@ -197,9 +171,7 @@ namespace SourceGit.Models
Founded.Add(new ExternalTool( Founded.Add(new ExternalTool(
$"{tool.DisplayName} {tool.DisplayVersion}", $"{tool.DisplayName} {tool.DisplayVersion}",
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB", supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
Path.Combine(tool.InstallLocation, tool.LaunchCommand), Path.Combine(tool.InstallLocation, tool.LaunchCommand)));
"\"{0}\"",
null));
} }
} }
} }

View file

@ -134,7 +134,7 @@ namespace SourceGit.Native
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe"); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox"); finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
finder.SublimeText(FindSublimeText); finder.SublimeText(FindSublimeText);
finder.VisualStudio(FindVisualStudio); finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
return finder.Founded; return finder.Founded;
} }
@ -325,7 +325,9 @@ namespace SourceGit.Native
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher) if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher)
{ {
// Get actual path to the executable // Get actual path to the executable
if (launcher.GetValue(string.Empty) is string CLSID && localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv && devenv.GetValue(string.Empty) is string localServer32) if (launcher.GetValue(string.Empty) is string CLSID &&
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
devenv.GetValue(string.Empty) is string localServer32)
{ {
return localServer32!.Trim('\"'); return localServer32!.Trim('\"');
} }
@ -348,5 +350,31 @@ namespace SourceGit.Native
ILFree(pidl); ILFree(pidl);
} }
} }
private string GenerateCommandlineArgsForVisualStudio(string repo)
{
var sln = FindVSSolutionFile(repo, 4);
return string.IsNullOrEmpty(sln) ? $"\"{repo}\"" : $"\"{sln}\"";
}
private string FindVSSolutionFile(string path, int leftDepth)
{
var found = Directory.GetFiles(path, "*.sln", SearchOption.TopDirectoryOnly);
if (found != null && found.Length > 0)
return Path.GetFullPath(found[0]);
if (leftDepth <= 0)
return null;
var subfolders = Directory.GetDirectories(path);
foreach (var subfolder in subfolders)
{
var first = FindVSSolutionFile(subfolder, leftDepth - 1);
if (!string.IsNullOrEmpty(first))
return first;
}
return null;
}
} }
} }