Skip to content

Commit 6b348fb

Browse files
committed
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 <[email protected]>
1 parent 1d00987 commit 6b348fb

File tree

3 files changed

+59
-59
lines changed

3 files changed

+59
-59
lines changed

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,23 +119,23 @@ For other AI service:
119119

120120
This app supports open repository in external tools listed in the table below.
121121

122-
| Tool | Windows | macOS | Linux | KEY IN `external_editors.json` |
123-
|-------------------------------|---------|-------|-------|--------------------------------|
124-
| Visual Studio Code | YES | YES | YES | VSCODE |
125-
| Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS |
126-
| VSCodium | YES | YES | YES | VSCODIUM |
127-
| JetBrains Fleet | YES | YES | YES | FLEET |
128-
| Sublime Text | YES | YES | YES | SUBLIME_TEXT |
129-
| Zed | NO | YES | YES | ZED |
130-
| Visual Studio | YES | YES | YES | VISUALSTUDIO |
122+
| Tool | Windows | macOS | Linux |
123+
|-------------------------------|---------|-------|-------|
124+
| Visual Studio Code | YES | YES | YES |
125+
| Visual Studio Code - Insiders | YES | YES | YES |
126+
| VSCodium | YES | YES | YES |
127+
| Fleet | YES | YES | YES |
128+
| Sublime Text | YES | YES | YES |
129+
| Zed | NO | YES | YES |
130+
| Visual Studio | YES | NO | NO |
131131

132132
> [!NOTE]
133133
> 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.
134134
> To solve this problem you can add a file named `external_editors.json` in app data dir and provide the path directly. For example:
135135
```json
136136
{
137137
"tools": {
138-
"VSCODE": "D:\\VSCode\\Code.exe"
138+
"Visual Studio Code": "D:\\VSCode\\Code.exe"
139139
}
140140
}
141141
```

src/Models/ExternalTool.cs

Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Diagnostics;
44
using System.IO;
5-
using System.Linq;
65
using System.Text.Json;
76
using System.Text.Json.Serialization;
87

@@ -14,17 +13,13 @@ namespace SourceGit.Models
1413
public class ExternalTool
1514
{
1615
public string Name { get; private set; }
17-
public string Executable { get; private set; }
18-
public string OpenCmdArgs { get; private set; }
1916
public Bitmap IconImage { get; private set; } = null;
20-
public Func<string, string> ArgTransform { get; private set; }
2117

22-
public ExternalTool(string name, string icon, string executable, string openCmdArgs, Func<string, string> argsTransform)
18+
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null)
2319
{
2420
Name = name;
25-
Executable = executable;
26-
OpenCmdArgs = openCmdArgs;
27-
ArgTransform = argsTransform ?? ((s) => s);
21+
_execFile = execFile;
22+
_execArgsGenerator = execArgsGenerator ?? (repo => $"\"{repo}\"");
2823

2924
try
3025
{
@@ -40,19 +35,17 @@ public ExternalTool(string name, string icon, string executable, string openCmdA
4035

4136
public void Open(string repo)
4237
{
43-
string arguments = string.Format(OpenCmdArgs, repo);
44-
45-
if (ArgTransform != null)
46-
arguments = ArgTransform.Invoke(arguments);
47-
4838
Process.Start(new ProcessStartInfo()
4939
{
5040
WorkingDirectory = repo,
51-
FileName = Executable,
52-
Arguments = arguments,
41+
FileName = _execFile,
42+
Arguments = _execArgsGenerator.Invoke(repo),
5343
UseShellExecute = false,
5444
});
5545
}
46+
47+
private string _execFile = string.Empty;
48+
private Func<string, string> _execArgsGenerator = null;
5649
}
5750

5851
public class JetBrainsState
@@ -118,67 +111,48 @@ public ExternalToolsFinder()
118111
_customPaths = new ExternalToolPaths();
119112
}
120113

121-
public void TryAdd(string name, string icon, string args, string key, Func<string> finder, Func<string, string> argsTransform = null)
114+
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)
122115
{
123-
if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath))
116+
if (_customPaths.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
124117
{
125-
Founded.Add(new ExternalTool(name, icon, customPath, args, argsTransform));
118+
Founded.Add(new ExternalTool(name, icon, customPath, execArgsGenerator));
126119
}
127120
else
128121
{
129122
var path = finder();
130123
if (!string.IsNullOrEmpty(path) && File.Exists(path))
131-
Founded.Add(new ExternalTool(name, icon, path, args, argsTransform));
124+
Founded.Add(new ExternalTool(name, icon, path, execArgsGenerator));
132125
}
133126
}
134127

135128
public void VSCode(Func<string> platformFinder)
136129
{
137-
TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder);
130+
TryAdd("Visual Studio Code", "vscode", platformFinder);
138131
}
139132

140133
public void VSCodeInsiders(Func<string> platformFinder)
141134
{
142-
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS", platformFinder);
135+
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", platformFinder);
143136
}
144137

145138
public void VSCodium(Func<string> platformFinder)
146139
{
147-
TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder);
140+
TryAdd("VSCodium", "codium", platformFinder);
148141
}
149142

150143
public void Fleet(Func<string> platformFinder)
151144
{
152-
TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder);
145+
TryAdd("Fleet", "fleet", platformFinder);
153146
}
154147

155148
public void SublimeText(Func<string> platformFinder)
156149
{
157-
TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT", platformFinder);
150+
TryAdd("Sublime Text", "sublime_text", platformFinder);
158151
}
159152

160153
public void Zed(Func<string> platformFinder)
161154
{
162-
TryAdd("Zed", "zed", "\"{0}\"", "ZED", platformFinder);
163-
}
164-
165-
public void VisualStudio(Func<string> platformFinder)
166-
{
167-
TryAdd("Visual Studio", "vs", "\"{0}\"", "VISUALSTUDIO", platformFinder, VisualStudioTryFindSolution);
168-
}
169-
170-
private static string VisualStudioTryFindSolution(string path)
171-
{
172-
try
173-
{
174-
if (Directory.GetFiles(path.Trim('\"'), "*.sln", SearchOption.AllDirectories).FirstOrDefault() is string solutionPath)
175-
return Path.GetFullPath(solutionPath);
176-
}
177-
catch
178-
{
179-
// do nothing
180-
}
181-
return path;
155+
TryAdd("Zed", "zed", platformFinder);
182156
}
183157

184158
public void FindJetBrainsFromToolbox(Func<string> platformFinder)
@@ -197,9 +171,7 @@ public void FindJetBrainsFromToolbox(Func<string> platformFinder)
197171
Founded.Add(new ExternalTool(
198172
$"{tool.DisplayName} {tool.DisplayVersion}",
199173
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
200-
Path.Combine(tool.InstallLocation, tool.LaunchCommand),
201-
"\"{0}\"",
202-
null));
174+
Path.Combine(tool.InstallLocation, tool.LaunchCommand)));
203175
}
204176
}
205177
}

src/Native/Windows.cs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public string FindTerminal(Models.ShellOrTerminal shell)
134134
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
135135
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
136136
finder.SublimeText(FindSublimeText);
137-
finder.VisualStudio(FindVisualStudio);
137+
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
138138
return finder.Founded;
139139
}
140140

@@ -325,7 +325,9 @@ private string FindVisualStudio()
325325
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher)
326326
{
327327
// Get actual path to the executable
328-
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)
328+
if (launcher.GetValue(string.Empty) is string CLSID &&
329+
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
330+
devenv.GetValue(string.Empty) is string localServer32)
329331
{
330332
return localServer32!.Trim('\"');
331333
}
@@ -348,5 +350,31 @@ private void OpenFolderAndSelectFile(string folderPath)
348350
ILFree(pidl);
349351
}
350352
}
353+
354+
private string GenerateCommandlineArgsForVisualStudio(string repo)
355+
{
356+
var sln = FindVSSolutionFile(repo, 4);
357+
return string.IsNullOrEmpty(sln) ? $"\"{repo}\"" : $"\"{sln}\"";
358+
}
359+
360+
private string FindVSSolutionFile(string path, int leftDepth)
361+
{
362+
var found = Directory.GetFiles(path, "*.sln", SearchOption.TopDirectoryOnly);
363+
if (found != null && found.Length > 0)
364+
return Path.GetFullPath(found[0]);
365+
366+
if (leftDepth <= 0)
367+
return null;
368+
369+
var subfolders = Directory.GetDirectories(path);
370+
foreach (var subfolder in subfolders)
371+
{
372+
var first = FindVSSolutionFile(subfolder, leftDepth - 1);
373+
if (!string.IsNullOrEmpty(first))
374+
return first;
375+
}
376+
377+
return null;
378+
}
351379
}
352380
}

0 commit comments

Comments
 (0)