Skip to content

Commit fb0120d

Browse files
committed
refactor: terminal/shell integration (#471)
1 parent 817f891 commit fb0120d

27 files changed

+443
-425
lines changed

src/Commands/GenerateCommitMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private string GenerateSubject(string summary)
108108
if (rsp != null && rsp.Choices.Count > 0)
109109
return rsp.Choices[0].Message.Content;
110110

111-
return string.Empty;
111+
return string.Empty;
112112
}
113113

114114
private string _repo;

src/Models/OpenAI.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public static OpenAIChatResponse Chat(string prompt, string question, Cancellati
123123
reader.Wait();
124124

125125
return JsonSerializer.Deserialize(reader.Result, JsonCodeGen.Default.OpenAIChatResponse);
126-
}
126+
}
127127
catch
128128
{
129129
if (cancellation.IsCancellationRequested)

src/Models/Shell.cs

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/Models/ShellOrTerminal.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using Avalonia.Media.Imaging;
5+
using Avalonia.Platform;
6+
7+
namespace SourceGit.Models
8+
{
9+
public class ShellOrTerminal
10+
{
11+
public string Type { get; set; }
12+
public string Name { get; set; }
13+
public string Exec { get; set; }
14+
15+
public Bitmap Icon
16+
{
17+
get
18+
{
19+
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/ShellIcons/{Type}.png", UriKind.RelativeOrAbsolute));
20+
return new Bitmap(icon);
21+
}
22+
}
23+
24+
public static readonly List<ShellOrTerminal> Supported;
25+
26+
static ShellOrTerminal()
27+
{
28+
if (OperatingSystem.IsWindows())
29+
{
30+
Supported = new List<ShellOrTerminal>()
31+
{
32+
new ShellOrTerminal("git-bash", "Git Bash", "bash.exe"),
33+
new ShellOrTerminal("pwsh", "PowerShell", "pwsh.exe|powershell.exe"),
34+
new ShellOrTerminal("cmd", "Command Prompt", "cmd.exe"),
35+
new ShellOrTerminal("wt", "Windows Terminal", "wt.exe")
36+
};
37+
}
38+
else if (OperatingSystem.IsMacOS())
39+
{
40+
Supported = new List<ShellOrTerminal>()
41+
{
42+
new ShellOrTerminal("mac-terminal", "Terminal", ""),
43+
new ShellOrTerminal("iterm2", "iTerm", ""),
44+
};
45+
}
46+
else
47+
{
48+
Supported = new List<ShellOrTerminal>()
49+
{
50+
new ShellOrTerminal("gnome-terminal", "Gnome Terminal", "gnome-terminal"),
51+
new ShellOrTerminal("konsole", "Konsole", "konsole"),
52+
new ShellOrTerminal("xfce4-terminal", "Xfce4 Terminal", "xfce4-terminal"),
53+
new ShellOrTerminal("lxterminal", "LXTerminal", "lxterminal"),
54+
new ShellOrTerminal("deepin-terminal", "Deepin Terminal", "deepin-terminal"),
55+
new ShellOrTerminal("mate-terminal", "MATE Terminal", "mate-terminal"),
56+
new ShellOrTerminal("foot", "Foot", "foot"),
57+
};
58+
}
59+
}
60+
61+
public ShellOrTerminal(string type, string name, string exec)
62+
{
63+
Type = type;
64+
Name = name;
65+
Exec = exec;
66+
}
67+
}
68+
}

src/Native/Linux.cs

Lines changed: 28 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,6 @@ namespace SourceGit.Native
1111
[SupportedOSPlatform("linux")]
1212
internal class Linux : OS.IBackend
1313
{
14-
class Terminal
15-
{
16-
public string FilePath { get; set; }
17-
public string OpenArgFormat { get; set; }
18-
19-
public Terminal(string exec, string fmt)
20-
{
21-
FilePath = exec;
22-
OpenArgFormat = fmt;
23-
}
24-
25-
public void Open(string dir)
26-
{
27-
Process.Start(FilePath, string.Format(OpenArgFormat, dir));
28-
}
29-
}
30-
31-
public Linux()
32-
{
33-
_xdgOpenPath = FindExecutable("xdg-open");
34-
_terminal = FindTerminal();
35-
}
36-
3714
public void SetupApp(AppBuilder builder)
3815
{
3916
builder.With(new X11PlatformOptions()
@@ -47,6 +24,20 @@ public string FindGitExecutable()
4724
return FindExecutable("git");
4825
}
4926

27+
public string FindTerminal(Models.ShellOrTerminal shell)
28+
{
29+
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
30+
var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
31+
foreach (var path in pathes)
32+
{
33+
var test = Path.Combine(path, shell.Exec);
34+
if (File.Exists(test))
35+
return test;
36+
}
37+
38+
return string.Empty;
39+
}
40+
5041
public List<Models.ExternalTool> FindExternalTools()
5142
{
5243
var finder = new Models.ExternalToolsFinder();
@@ -61,50 +52,40 @@ public string FindGitExecutable()
6152

6253
public void OpenBrowser(string url)
6354
{
64-
if (string.IsNullOrEmpty(_xdgOpenPath))
65-
App.RaiseException("", $"Can NOT find `xdg-open` command!!!");
66-
else
67-
Process.Start(_xdgOpenPath, $"\"{url}\"");
55+
Process.Start("xdg-open", $"\"{url}\"");
6856
}
6957

7058
public void OpenInFileManager(string path, bool select)
7159
{
72-
if (string.IsNullOrEmpty(_xdgOpenPath))
73-
{
74-
App.RaiseException("", $"Can NOT find `xdg-open` command!!!");
75-
return;
76-
}
77-
7860
if (Directory.Exists(path))
7961
{
80-
Process.Start(_xdgOpenPath, $"\"{path}\"");
62+
Process.Start("xdg-open", $"\"{path}\"");
8163
}
8264
else
8365
{
8466
var dir = Path.GetDirectoryName(path);
8567
if (Directory.Exists(dir))
86-
Process.Start(_xdgOpenPath, $"\"{dir}\"");
68+
Process.Start("xdg-open", $"\"{dir}\"");
8769
}
8870
}
8971

9072
public void OpenTerminal(string workdir)
9173
{
92-
var dir = string.IsNullOrEmpty(workdir) ? "~" : workdir;
93-
if (_terminal == null)
94-
App.RaiseException(dir, $"Only supports gnome-terminal/konsole/xfce4-terminal/lxterminal/deepin-terminal/mate-terminal/foot!");
95-
else
96-
_terminal.Open(dir);
97-
}
98-
99-
public void OpenWithDefaultEditor(string file)
100-
{
101-
if (string.IsNullOrEmpty(_xdgOpenPath))
74+
if (string.IsNullOrEmpty(OS.ShellOrTerminal) || !File.Exists(OS.ShellOrTerminal))
10275
{
103-
App.RaiseException("", $"Can NOT find `xdg-open` command!!!");
76+
App.RaiseException(workdir, $"Can not found terminal! Please confirm that the correct shell/terminal has been configured.");
10477
return;
10578
}
10679

107-
var proc = Process.Start(_xdgOpenPath, $"\"{file}\"");
80+
var startInfo = new ProcessStartInfo();
81+
startInfo.WorkingDirectory = string.IsNullOrEmpty(workdir) ? "~" : workdir;
82+
startInfo.FileName = OS.ShellOrTerminal;
83+
Process.Start(startInfo);
84+
}
85+
86+
public void OpenWithDefaultEditor(string file)
87+
{
88+
var proc = Process.Start("xdg-open", $"\"{file}\"");
10889
if (proc != null)
10990
{
11091
proc.WaitForExit();
@@ -130,51 +111,10 @@ private string FindExecutable(string filename)
130111
return string.Empty;
131112
}
132113

133-
private Terminal FindTerminal()
134-
{
135-
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
136-
var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
137-
foreach (var path in pathes)
138-
{
139-
var test = Path.Combine(path, "gnome-terminal");
140-
if (File.Exists(test))
141-
return new Terminal(test, "--working-directory=\"{0}\"");
142-
143-
test = Path.Combine(path, "konsole");
144-
if (File.Exists(test))
145-
return new Terminal(test, "--workdir \"{0}\"");
146-
147-
test = Path.Combine(path, "xfce4-terminal");
148-
if (File.Exists(test))
149-
return new Terminal(test, "--working-directory=\"{0}\"");
150-
151-
test = Path.Combine(path, "lxterminal");
152-
if (File.Exists(test))
153-
return new Terminal(test, "--working-directory=\"{0}\"");
154-
155-
test = Path.Combine(path, "deepin-terminal");
156-
if (File.Exists(test))
157-
return new Terminal(test, "--work-directory \"{0}\"");
158-
159-
test = Path.Combine(path, "mate-terminal");
160-
if (File.Exists(test))
161-
return new Terminal(test, "--working-directory=\"{0}\"");
162-
163-
test = Path.Combine(path, "foot");
164-
if (File.Exists(test))
165-
return new Terminal(test, "--working-directory=\"{0}\"");
166-
}
167-
168-
return null;
169-
}
170-
171114
private string FindJetBrainsFleet()
172115
{
173116
var path = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet";
174117
return File.Exists(path) ? path : FindExecutable("fleet");
175118
}
176-
177-
private string _xdgOpenPath = null;
178-
private Terminal _terminal = null;
179119
}
180120
}

src/Native/MacOS.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ public string FindGitExecutable()
2424
return File.Exists("/usr/bin/git") ? "/usr/bin/git" : string.Empty;
2525
}
2626

27+
public string FindTerminal(Models.ShellOrTerminal shell)
28+
{
29+
switch (shell.Type)
30+
{
31+
case "mac-terminal":
32+
return "Terminal";
33+
case "iterm2":
34+
return "iTerm";
35+
}
36+
37+
return "InvalidTerminal";
38+
}
39+
2740
public List<Models.ExternalTool> FindExternalTools()
2841
{
2942
var finder = new Models.ExternalToolsFinder();
@@ -53,12 +66,7 @@ public void OpenTerminal(string workdir)
5366
{
5467
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
5568
var dir = string.IsNullOrEmpty(workdir) ? home : workdir;
56-
57-
var terminal = "Terminal";
58-
if (Directory.Exists("/Applications/iTerm.app"))
59-
terminal = "iTerm";
60-
61-
Process.Start("open", $"-a {terminal} \"{dir}\"");
69+
Process.Start("open", $"-a {OS.ShellOrTerminal} \"{dir}\"");
6270
}
6371

6472
public void OpenWithDefaultEditor(string file)

src/Native/OS.cs

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public interface IBackend
1313
void SetupApp(AppBuilder builder);
1414

1515
string FindGitExecutable();
16+
string FindTerminal(Models.ShellOrTerminal shell);
1617
List<Models.ExternalTool> FindExternalTools();
1718

1819
void OpenTerminal(string workdir);
@@ -23,6 +24,7 @@ public interface IBackend
2324

2425
public static string DataDir { get; private set; } = string.Empty;
2526
public static string GitExecutable { get; set; } = string.Empty;
27+
public static string ShellOrTerminal { get; set; } = string.Empty;
2628
public static List<Models.ExternalTool> ExternalTools { get; set; } = [];
2729

2830
static OS()
@@ -45,29 +47,6 @@ static OS()
4547
}
4648
}
4749

48-
public static Models.Shell GetShell()
49-
{
50-
if (OperatingSystem.IsWindows())
51-
return (_backend as Windows)!.Shell;
52-
53-
return Models.Shell.Default;
54-
}
55-
56-
public static bool SetShell(Models.Shell shell)
57-
{
58-
if (OperatingSystem.IsWindows())
59-
{
60-
var windows = (_backend as Windows)!;
61-
if (windows.Shell != shell)
62-
{
63-
windows.Shell = shell;
64-
return true;
65-
}
66-
}
67-
68-
return false;
69-
}
70-
7150
public static void SetupApp(AppBuilder builder)
7251
{
7352
_backend.SetupApp(builder);
@@ -95,6 +74,14 @@ public static string FindGitExecutable()
9574
return _backend.FindGitExecutable();
9675
}
9776

77+
public static void SetShellOrTerminal(Models.ShellOrTerminal shellOrTerminal)
78+
{
79+
if (shellOrTerminal == null)
80+
ShellOrTerminal = string.Empty;
81+
else
82+
ShellOrTerminal = _backend.FindTerminal(shellOrTerminal);
83+
}
84+
9885
public static void OpenInFileManager(string path, bool select = false)
9986
{
10087
_backend.OpenInFileManager(path, select);
@@ -107,7 +94,10 @@ public static void OpenBrowser(string url)
10794

10895
public static void OpenTerminal(string workdir)
10996
{
110-
_backend.OpenTerminal(workdir);
97+
if (string.IsNullOrEmpty(ShellOrTerminal))
98+
App.RaiseException(workdir, $"Can not found terminal! Please confirm that the correct shell/terminal has been configured.");
99+
else
100+
_backend.OpenTerminal(workdir);
111101
}
112102

113103
public static void OpenWithDefaultEditor(string file)

0 commit comments

Comments
 (0)