From fb0120d33805d446bdedab9c77f771864c2ac973 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 14 Sep 2024 12:09:50 +0800 Subject: [PATCH] refactor: terminal/shell integration (#471) --- src/Commands/GenerateCommitMessage.cs | 2 +- src/Models/OpenAI.cs | 2 +- src/Models/Shell.cs | 10 - src/Models/ShellOrTerminal.cs | 68 +++++ src/Native/Linux.cs | 116 ++------ src/Native/MacOS.cs | 20 +- src/Native/OS.cs | 38 +-- src/Native/Windows.cs | 149 ++++------ .../Images/ShellIcons/deepin-terminal.png | Bin 0 -> 3073 bytes src/Resources/Images/ShellIcons/foot.png | Bin 0 -> 1631 bytes .../Images/ShellIcons/gnome-terminal.png | Bin 0 -> 1482 bytes src/Resources/Images/ShellIcons/item2.png | Bin 0 -> 2160 bytes src/Resources/Images/ShellIcons/konsole.png | Bin 0 -> 3190 bytes .../Images/ShellIcons/lxterminal.png | Bin 0 -> 2858 bytes .../Images/ShellIcons/mac-terminal.png | Bin 0 -> 2252 bytes .../Images/ShellIcons/mate-terminal.png | Bin 0 -> 3809 bytes .../Images/ShellIcons/xfce4-terminal.png | Bin 0 -> 1147 bytes src/Resources/Locales/de_DE.axaml | 9 +- src/Resources/Locales/en_US.axaml | 13 +- src/Resources/Locales/fr_FR.axaml | 9 +- src/Resources/Locales/pt_BR.axaml | 9 +- src/Resources/Locales/zh_CN.axaml | 13 +- src/Resources/Locales/zh_TW.axaml | 13 +- src/ViewModels/Preference.cs | 87 +++--- src/Views/Preference.axaml | 273 ++++++++++-------- src/Views/Preference.axaml.cs | 39 ++- src/Views/WorkingCopy.axaml.cs | 2 +- 27 files changed, 445 insertions(+), 427 deletions(-) delete mode 100644 src/Models/Shell.cs create mode 100644 src/Models/ShellOrTerminal.cs create mode 100644 src/Resources/Images/ShellIcons/deepin-terminal.png create mode 100644 src/Resources/Images/ShellIcons/foot.png create mode 100644 src/Resources/Images/ShellIcons/gnome-terminal.png create mode 100644 src/Resources/Images/ShellIcons/item2.png create mode 100644 src/Resources/Images/ShellIcons/konsole.png create mode 100644 src/Resources/Images/ShellIcons/lxterminal.png create mode 100644 src/Resources/Images/ShellIcons/mac-terminal.png create mode 100644 src/Resources/Images/ShellIcons/mate-terminal.png create mode 100644 src/Resources/Images/ShellIcons/xfce4-terminal.png diff --git a/src/Commands/GenerateCommitMessage.cs b/src/Commands/GenerateCommitMessage.cs index b5c978d3..e71fb0b9 100644 --- a/src/Commands/GenerateCommitMessage.cs +++ b/src/Commands/GenerateCommitMessage.cs @@ -108,7 +108,7 @@ namespace SourceGit.Commands if (rsp != null && rsp.Choices.Count > 0) return rsp.Choices[0].Message.Content; - return string.Empty; + return string.Empty; } private string _repo; diff --git a/src/Models/OpenAI.cs b/src/Models/OpenAI.cs index 192459c7..2619f299 100644 --- a/src/Models/OpenAI.cs +++ b/src/Models/OpenAI.cs @@ -123,7 +123,7 @@ namespace SourceGit.Models reader.Wait(); return JsonSerializer.Deserialize(reader.Result, JsonCodeGen.Default.OpenAIChatResponse); - } + } catch { if (cancellation.IsCancellationRequested) diff --git a/src/Models/Shell.cs b/src/Models/Shell.cs deleted file mode 100644 index 9960d136..00000000 --- a/src/Models/Shell.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SourceGit.Models -{ - public enum Shell - { - Default = 0, - PowerShell, - CommandPrompt, - DefaultShellOfWindowsTerminal, - } -} diff --git a/src/Models/ShellOrTerminal.cs b/src/Models/ShellOrTerminal.cs new file mode 100644 index 00000000..fa3a207b --- /dev/null +++ b/src/Models/ShellOrTerminal.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; + +using Avalonia.Media.Imaging; +using Avalonia.Platform; + +namespace SourceGit.Models +{ + public class ShellOrTerminal + { + public string Type { get; set; } + public string Name { get; set; } + public string Exec { get; set; } + + public Bitmap Icon + { + get + { + var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/ShellIcons/{Type}.png", UriKind.RelativeOrAbsolute)); + return new Bitmap(icon); + } + } + + public static readonly List Supported; + + static ShellOrTerminal() + { + if (OperatingSystem.IsWindows()) + { + Supported = new List() + { + new ShellOrTerminal("git-bash", "Git Bash", "bash.exe"), + new ShellOrTerminal("pwsh", "PowerShell", "pwsh.exe|powershell.exe"), + new ShellOrTerminal("cmd", "Command Prompt", "cmd.exe"), + new ShellOrTerminal("wt", "Windows Terminal", "wt.exe") + }; + } + else if (OperatingSystem.IsMacOS()) + { + Supported = new List() + { + new ShellOrTerminal("mac-terminal", "Terminal", ""), + new ShellOrTerminal("iterm2", "iTerm", ""), + }; + } + else + { + Supported = new List() + { + new ShellOrTerminal("gnome-terminal", "Gnome Terminal", "gnome-terminal"), + new ShellOrTerminal("konsole", "Konsole", "konsole"), + new ShellOrTerminal("xfce4-terminal", "Xfce4 Terminal", "xfce4-terminal"), + new ShellOrTerminal("lxterminal", "LXTerminal", "lxterminal"), + new ShellOrTerminal("deepin-terminal", "Deepin Terminal", "deepin-terminal"), + new ShellOrTerminal("mate-terminal", "MATE Terminal", "mate-terminal"), + new ShellOrTerminal("foot", "Foot", "foot"), + }; + } + } + + public ShellOrTerminal(string type, string name, string exec) + { + Type = type; + Name = name; + Exec = exec; + } + } +} diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index 1b33cc5d..9537a39a 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -11,29 +11,6 @@ namespace SourceGit.Native [SupportedOSPlatform("linux")] internal class Linux : OS.IBackend { - class Terminal - { - public string FilePath { get; set; } - public string OpenArgFormat { get; set; } - - public Terminal(string exec, string fmt) - { - FilePath = exec; - OpenArgFormat = fmt; - } - - public void Open(string dir) - { - Process.Start(FilePath, string.Format(OpenArgFormat, dir)); - } - } - - public Linux() - { - _xdgOpenPath = FindExecutable("xdg-open"); - _terminal = FindTerminal(); - } - public void SetupApp(AppBuilder builder) { builder.With(new X11PlatformOptions() @@ -47,6 +24,20 @@ namespace SourceGit.Native return FindExecutable("git"); } + public string FindTerminal(Models.ShellOrTerminal shell) + { + var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty; + var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries); + foreach (var path in pathes) + { + var test = Path.Combine(path, shell.Exec); + if (File.Exists(test)) + return test; + } + + return string.Empty; + } + public List FindExternalTools() { var finder = new Models.ExternalToolsFinder(); @@ -61,50 +52,40 @@ namespace SourceGit.Native public void OpenBrowser(string url) { - if (string.IsNullOrEmpty(_xdgOpenPath)) - App.RaiseException("", $"Can NOT find `xdg-open` command!!!"); - else - Process.Start(_xdgOpenPath, $"\"{url}\""); + Process.Start("xdg-open", $"\"{url}\""); } public void OpenInFileManager(string path, bool select) { - if (string.IsNullOrEmpty(_xdgOpenPath)) - { - App.RaiseException("", $"Can NOT find `xdg-open` command!!!"); - return; - } - if (Directory.Exists(path)) { - Process.Start(_xdgOpenPath, $"\"{path}\""); + Process.Start("xdg-open", $"\"{path}\""); } else { var dir = Path.GetDirectoryName(path); if (Directory.Exists(dir)) - Process.Start(_xdgOpenPath, $"\"{dir}\""); + Process.Start("xdg-open", $"\"{dir}\""); } } public void OpenTerminal(string workdir) { - var dir = string.IsNullOrEmpty(workdir) ? "~" : workdir; - if (_terminal == null) - App.RaiseException(dir, $"Only supports gnome-terminal/konsole/xfce4-terminal/lxterminal/deepin-terminal/mate-terminal/foot!"); - else - _terminal.Open(dir); + if (string.IsNullOrEmpty(OS.ShellOrTerminal) || !File.Exists(OS.ShellOrTerminal)) + { + App.RaiseException(workdir, $"Can not found terminal! Please confirm that the correct shell/terminal has been configured."); + return; + } + + var startInfo = new ProcessStartInfo(); + startInfo.WorkingDirectory = string.IsNullOrEmpty(workdir) ? "~" : workdir; + startInfo.FileName = OS.ShellOrTerminal; + Process.Start(startInfo); } public void OpenWithDefaultEditor(string file) { - if (string.IsNullOrEmpty(_xdgOpenPath)) - { - App.RaiseException("", $"Can NOT find `xdg-open` command!!!"); - return; - } - - var proc = Process.Start(_xdgOpenPath, $"\"{file}\""); + var proc = Process.Start("xdg-open", $"\"{file}\""); if (proc != null) { proc.WaitForExit(); @@ -130,51 +111,10 @@ namespace SourceGit.Native return string.Empty; } - private Terminal FindTerminal() - { - var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty; - var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries); - foreach (var path in pathes) - { - var test = Path.Combine(path, "gnome-terminal"); - if (File.Exists(test)) - return new Terminal(test, "--working-directory=\"{0}\""); - - test = Path.Combine(path, "konsole"); - if (File.Exists(test)) - return new Terminal(test, "--workdir \"{0}\""); - - test = Path.Combine(path, "xfce4-terminal"); - if (File.Exists(test)) - return new Terminal(test, "--working-directory=\"{0}\""); - - test = Path.Combine(path, "lxterminal"); - if (File.Exists(test)) - return new Terminal(test, "--working-directory=\"{0}\""); - - test = Path.Combine(path, "deepin-terminal"); - if (File.Exists(test)) - return new Terminal(test, "--work-directory \"{0}\""); - - test = Path.Combine(path, "mate-terminal"); - if (File.Exists(test)) - return new Terminal(test, "--working-directory=\"{0}\""); - - test = Path.Combine(path, "foot"); - if (File.Exists(test)) - return new Terminal(test, "--working-directory=\"{0}\""); - } - - return null; - } - private string FindJetBrainsFleet() { var path = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet"; return File.Exists(path) ? path : FindExecutable("fleet"); } - - private string _xdgOpenPath = null; - private Terminal _terminal = null; } } diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index f68d7ac5..0ad608b2 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -24,6 +24,19 @@ namespace SourceGit.Native return File.Exists("/usr/bin/git") ? "/usr/bin/git" : string.Empty; } + public string FindTerminal(Models.ShellOrTerminal shell) + { + switch (shell.Type) + { + case "mac-terminal": + return "Terminal"; + case "iterm2": + return "iTerm"; + } + + return "InvalidTerminal"; + } + public List FindExternalTools() { var finder = new Models.ExternalToolsFinder(); @@ -53,12 +66,7 @@ namespace SourceGit.Native { var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); var dir = string.IsNullOrEmpty(workdir) ? home : workdir; - - var terminal = "Terminal"; - if (Directory.Exists("/Applications/iTerm.app")) - terminal = "iTerm"; - - Process.Start("open", $"-a {terminal} \"{dir}\""); + Process.Start("open", $"-a {OS.ShellOrTerminal} \"{dir}\""); } public void OpenWithDefaultEditor(string file) diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 0e1b8522..87655798 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -13,6 +13,7 @@ namespace SourceGit.Native void SetupApp(AppBuilder builder); string FindGitExecutable(); + string FindTerminal(Models.ShellOrTerminal shell); List FindExternalTools(); void OpenTerminal(string workdir); @@ -23,6 +24,7 @@ namespace SourceGit.Native public static string DataDir { get; private set; } = string.Empty; public static string GitExecutable { get; set; } = string.Empty; + public static string ShellOrTerminal { get; set; } = string.Empty; public static List ExternalTools { get; set; } = []; static OS() @@ -45,29 +47,6 @@ namespace SourceGit.Native } } - public static Models.Shell GetShell() - { - if (OperatingSystem.IsWindows()) - return (_backend as Windows)!.Shell; - - return Models.Shell.Default; - } - - public static bool SetShell(Models.Shell shell) - { - if (OperatingSystem.IsWindows()) - { - var windows = (_backend as Windows)!; - if (windows.Shell != shell) - { - windows.Shell = shell; - return true; - } - } - - return false; - } - public static void SetupApp(AppBuilder builder) { _backend.SetupApp(builder); @@ -95,6 +74,14 @@ namespace SourceGit.Native return _backend.FindGitExecutable(); } + public static void SetShellOrTerminal(Models.ShellOrTerminal shellOrTerminal) + { + if (shellOrTerminal == null) + ShellOrTerminal = string.Empty; + else + ShellOrTerminal = _backend.FindTerminal(shellOrTerminal); + } + public static void OpenInFileManager(string path, bool select = false) { _backend.OpenInFileManager(path, select); @@ -107,7 +94,10 @@ namespace SourceGit.Native public static void OpenTerminal(string workdir) { - _backend.OpenTerminal(workdir); + if (string.IsNullOrEmpty(ShellOrTerminal)) + App.RaiseException(workdir, $"Can not found terminal! Please confirm that the correct shell/terminal has been configured."); + else + _backend.OpenTerminal(workdir); } public static void OpenWithDefaultEditor(string file) diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 18326fa6..19362d0c 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -53,12 +53,6 @@ namespace SourceGit.Native [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)] private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags); - public Models.Shell Shell - { - get; - set; - } = Models.Shell.Default; - public void SetupApp(AppBuilder builder) { // Fix drop shadow issue on Windows 10 @@ -98,6 +92,51 @@ namespace SourceGit.Native return null; } + public string FindTerminal(Models.ShellOrTerminal shell) + { + switch (shell.Type) + { + case "git-bash": + if (string.IsNullOrEmpty(OS.GitExecutable)) + break; + + var binDir = Path.GetDirectoryName(OS.GitExecutable)!; + var bash = Path.Combine(binDir, "bash.exe"); + if (!File.Exists(bash)) + break; + + return bash; + case "pwsh": + var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey( + Microsoft.Win32.RegistryHive.LocalMachine, + Microsoft.Win32.RegistryView.Registry64); + + var pwsh = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\pwsh.exe"); + if (pwsh != null) + { + var path = pwsh.GetValue(null) as string; + if (File.Exists(path)) + return path; + } + + var pwshFinder = new StringBuilder("powershell.exe", 512); + if (PathFindOnPath(pwshFinder, null)) + return pwshFinder.ToString(); + + break; + case "cmd": + return "C:\\Windows\\System32\\cmd.exe"; + case "wt": + var wtFinder = new StringBuilder("wt.exe", 512); + if (PathFindOnPath(wtFinder, null)) + return wtFinder.ToString(); + + break; + } + + return string.Empty; + } + public List FindExternalTools() { var finder = new Models.ExternalToolsFinder(); @@ -119,56 +158,15 @@ namespace SourceGit.Native public void OpenTerminal(string workdir) { - if (string.IsNullOrEmpty(workdir) || !Path.Exists(workdir)) + if (string.IsNullOrEmpty(OS.ShellOrTerminal) || !File.Exists(OS.ShellOrTerminal)) { - workdir = "."; + App.RaiseException(workdir, $"Can not found terminal! Please confirm that the correct shell/terminal has been configured."); + return; } var startInfo = new ProcessStartInfo(); startInfo.WorkingDirectory = workdir; - - switch (Shell) - { - case Models.Shell.Default: - if (string.IsNullOrEmpty(OS.GitExecutable)) - { - App.RaiseException(workdir, $"Can NOT found bash.exe"); - return; - } - - var binDir = Path.GetDirectoryName(OS.GitExecutable)!; - var bash = Path.Combine(binDir, "bash.exe"); - if (!File.Exists(bash)) - { - App.RaiseException(workdir, $"Can NOT found bash.exe under '{binDir}'"); - return; - } - - startInfo.FileName = bash; - break; - case Models.Shell.PowerShell: - startInfo.FileName = ChoosePowerShell(); - startInfo.Arguments = startInfo.FileName.EndsWith("pwsh.exe") ? $"-WorkingDirectory \"{workdir}\" -Nologo" : "-Nologo"; - break; - case Models.Shell.CommandPrompt: - startInfo.FileName = "cmd"; - break; - case Models.Shell.DefaultShellOfWindowsTerminal: - var wt = FindWindowsTerminalApp(); - if (!File.Exists(wt)) - { - App.RaiseException(workdir, $"Can NOT found wt.exe on your system!"); - return; - } - - startInfo.FileName = wt; - startInfo.Arguments = $"-d \"{workdir}\""; - break; - default: - App.RaiseException(workdir, $"Bad shell configuration!"); - return; - } - + startInfo.FileName = OS.ShellOrTerminal; Process.Start(startInfo); } @@ -218,52 +216,6 @@ namespace SourceGit.Native DwmExtendFrameIntoClientArea(platformHandle.Handle, ref margins); } - // There are two versions of PowerShell : pwsh.exe (preferred) and powershell.exe (system default) - private string ChoosePowerShell() - { - if (!string.IsNullOrEmpty(_powershellPath)) - return _powershellPath; - - var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey( - Microsoft.Win32.RegistryHive.LocalMachine, - Microsoft.Win32.RegistryView.Registry64); - - var pwsh = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\pwsh.exe"); - if (pwsh != null) - { - var path = pwsh.GetValue(null) as string; - if (File.Exists(path)) - { - _powershellPath = path; - return _powershellPath; - } - } - - var finder = new StringBuilder("powershell.exe", 512); - if (PathFindOnPath(finder, null)) - { - _powershellPath = finder.ToString(); - return _powershellPath; - } - - return string.Empty; - } - - private string FindWindowsTerminalApp() - { - if (!string.IsNullOrEmpty(_wtPath)) - return _wtPath; - - var finder = new StringBuilder("wt.exe", 512); - if (PathFindOnPath(finder, null)) - { - _wtPath = finder.ToString(); - return _wtPath; - } - - return string.Empty; - } - #region EXTERNAL_EDITOR_FINDER private string FindVSCode() { @@ -385,8 +337,5 @@ namespace SourceGit.Native ILFree(pidl); } } - - private string _powershellPath = string.Empty; - private string _wtPath = string.Empty; } } diff --git a/src/Resources/Images/ShellIcons/deepin-terminal.png b/src/Resources/Images/ShellIcons/deepin-terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..78eef1b45238d462722d2c84c3485024db2c4192 GIT binary patch literal 3073 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 P00000NkvXXu0mjfy)wpu literal 0 HcmV?d00001 diff --git a/src/Resources/Images/ShellIcons/foot.png b/src/Resources/Images/ShellIcons/foot.png new file mode 100644 index 0000000000000000000000000000000000000000..c5dbd0a501861cf8b65c5573cd52c787361a0d2a GIT binary patch literal 1631 zcmaKsdt6Lu7{|{TO0(LsJEDlwRjg?$cGtyZJ!-vx?08Nk1BrJC0RZ}ZUC@qKTrZ(EO-XJr8Hh!Yay||La=F|d zL8Ax(Ujo@l z_$+JRm6VYgIwM{<#Mik1d59PSoE)4SSPsrCr-cve3Z_%cZ#pIrli~shfJst9EN8PL za0nt~k-GO_|1iV)&kWJ<{UL`s7VtwFlSJc4BuoNcUZ4j_;z+nuH;NSqQ#bVxAyE*h z)1)K?KU~Nl0VWn>DDgvDga{y%fCzSYG>hP~7uh?oD|q3P0AQlnhvUK9sT#-#6)`u= zO1OOr4e?C|xf9pkT$A)^+d+6ySYcuAd^3ykoE42TZorNDzgp&9^$_Q?Z2~;bIs0yJ zwhdDcJ%60W$Zb~yZ?ZAGuYN$vee4Xo)K3GR$mDyBed}b)>-zgu&YABKqQNZ{izOOV znME$g)OK|d!lnu8%XDKFXyyV?TH`-`J2dbYMY3-$td9~TC z?f&+6FJ3MzVoaLvnw7k<<;w>8_2{0rv^^``3=jEEobYP0-hRh`#rm3NW$kf}pUf7$ zHd9fk7UpW)Iu?bLe{t9X@UyO z6bFipv(H{uN|uUBBI^tiDq31v=-|A+&IM_1FsLb(ZNK!s@EJ&d-~60c^AS=u?W|05 z2eU)YncfjrtlaHoHu@sH>KNBR6g{{sYs*(VZhVF^rFAoJ0c6R1obNc~+PO+HcKeY) z;8B8wKB^QMoj0;hP17!K%d`1?f);zz-Ptv}bobZu+U4$EwT@I}I_FIGRoRlL))hj^ zkOR{_*ng>PjOpr@b+>4jO=PU$hql8;rbC8Jk7cUAU$Omp*G&_w8bn*0n_Q8XFU|Li zBQ&GDys?6Bqi(BU^jlU+?RJCsdkefzCRI#*c>lo23a0Yi)FW5N&nKqppIkEfb68F2 z>NUOw$i<+-x8;mmm-e(WtAo`piks8xGOm0dX;(4dx7Bn%Fev*hJH>ar*l4a8h39N) zhmTng-Yb1L_?bP!q=?Z$8~Wa@$yfUqq35HN78VyBiy3Jfodbut8PDuJ9m*`Oye~34 zOlI;1Zp*~?`_8f+NPvUt^_v6ghc8#3G1jLy$BlcXg@$juG_D+lU*yDS;$|oJHlCO| zoYmRa7tCp|>YEXxiA@@5JYl>6AbOX2hhDW*m*3RHwZ+lLrdQCsk8%9FOiWm+IZdr2 z9ZGFZ{{2RJS+nUnpFvrcPn@+HgFiW$Z*k+YBBqtnk3gqlZf>1BP+fJ_=)<4a5+=t- zG?<)zH?Oek^IYD#*iYTlMp~t-SddLAy{i7BcI0^Mkl~Vjaom@JWu=-sSJHOR6}w43 z=(oA-vT9p*MqAn=(5x)kP~g|nH=DNq*4f08)EGK5otM!?@vGg(U3$ufD{W_o-B2Ap z`nI@49vJp4zw}+w^$WWi&F?hEuj#k@WNl*ad2-k-rJa^&VtmM40n?hE{%;wyxA}GP zJuBO#-NoN?a!nPr$At%zCvQg6BMxl`7&Tmls(-C8y0@Mga-zDvo(3j6YHTcXLHTESbav1mu@|P>S{Gb9=eaN4S5|!b&El+N zv9@fnQ_oB*ATu*zAr#W!3MmsM#eG1U(5bb90PrKV1_t+%6NZROAI#R|9|;QW-> ai>*%ayOqb?>qLEPfDhM?bIEhtzJCDd2iQ9R literal 0 HcmV?d00001 diff --git a/src/Resources/Images/ShellIcons/gnome-terminal.png b/src/Resources/Images/ShellIcons/gnome-terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..f9edd2e32ae6cf0257299e70f9f8557bc38126b5 GIT binary patch literal 1482 zcmV;*1vUDKP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H102_2g zSaeirbZlh+L1cGfX>?&ANn>wrAXH^-aBN|8WwpEKKL7v#7<5HgbU}4=Xm4@=M@~;o zMIc0Fb7^O8AXH^xZD5XeegFUfQglUFbVF}&d2(rIXmkKWLm)wPbaH88b#!TOZY@)2 zVRB_bY-wv{AZT=Sa5^t9V{&C-bZK^FV{dJ3Z*FrgZ*pfZY-wX~5|q3MpdlikWZ^ai86m_xvUBIINtO{|mBH!hsom5fmjN_|z>+USipKCBX(~prm5{p6?H`Y&?_TdJsZ_`V%R5AMtBtP}V?EM~JMK zIPM4_gp^&6Y=5|nM-8_>?u!?~x4Kj3)(QDn0Zi4L(TAS^&Soksh?{rL6LMZDkD ziTe8cWcn2ueB1)%*IVuH;L_-C$Yk!vp{`C0j}D>z;C`s8Qehj%C0zhFuKjTx?{<8E z18=;I;h#s)($b9M{YNqMmn2&)R{AtbvkxAd=WKL0SIPZh^1{mK`u*RYhR|qP`INEZOKcvazqkPF~n|A(B!2WE1a=9!3 zK-bxMf%zmjJ9`rV(B0F4=Hfs}LN1p@S8pc(`vWcu%m^4CpTM?lEog1qi}T-oF5kn5 zpc@9p{+z&b&%aQ$of!ek%Xe^nd;%+)=KGLgGr+PetlU|_*tK!wwLH_#D+%7tYx#zo zb92x%4NFT)&@|1%eDffa$)K^Z5t+;bC=?0+u*9-uzYP*H5`u5>fMS@{#1z1?$Poay zLUAZsEUG5yWi>JdICiXWQZdba0EPf8hv8YsSO&p`l$zSp_fg+}EFye$_5c6? literal 0 HcmV?d00001 diff --git a/src/Resources/Images/ShellIcons/item2.png b/src/Resources/Images/ShellIcons/item2.png new file mode 100644 index 0000000000000000000000000000000000000000..16fbd3bd884d097cf5265973835e57db54f1eddb GIT binary patch literal 2160 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 literal 0 HcmV?d00001 diff --git a/src/Resources/Images/ShellIcons/lxterminal.png b/src/Resources/Images/ShellIcons/lxterminal.png new file mode 100644 index 0000000000000000000000000000000000000000..99f62683beb303641395115ce1f02fcdf035feb4 GIT binary patch literal 2858 zcmV+_3)S?AP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGh)&Kwv)&Y=jd7J6+&cUTimwu8+Bz~GorIKFNcMgR@p_EJ}|8e&0*?)Rf zbKnfXl`B`;ckI}aIdbGkBL%^${qCVuDyfGLALd`ae7W)5xpO(Mx(Y!7`0UiFQ-6E% z#tNg-9WWv`lpSCDVqyf229awn^T7M3WVyi{y(4$>lLV8JZ9Z%Y%-Zr9UUEN z*REaVyLa#Yg37mag9T@LQ{+~xT)9$x`Q=|!b8}iXq?JlFBvdMuP}HwVB+E2_AN3Zt5L6V%4nn9Zm*5JBX6Op>e3v`W9{ecHe?T%QEx=gZ8Pn~Vo?nbkErhM9@W>Ep&(3nBEk{5!)pg=Fcyp%hlK-D zv_AuO8)lW;%&djC`PVXws@wRvGA)I?8WV z&-UQpd)gGIJx}M4h$Xl`LG%*P z4ocC+Id+hp=lklB;t-9oCa0!oL+jJ2J~}$4>*|fjC19K~j``MiUIxjxVC^YxY>75D z2+yd#-ab0tr#x>K1`$hu1K@9Xa8Qb_o;jJu@lzcAp$#uRnaqIdCE*CdVj$KMFwXme z*?Dd=qH0fZ(>_aYeKV@R-w4Os-C`m}0F2YV^&R&G`l4B|-)7pYgK3D(YI^*}@b zK$ocC6!%4&>zSE?7Cu31KAB9aR4Nrp+ymm9sKxj;Dq;z+5F^^y;1mZ<8=g(*PiDiz z!@9kpp`m8Vpe$5CVr+uU;1p-ki3A)q%;%@|4v(*Q9im?gNF5&Vy7o|v>>=RE`6e7c9MEm0Lc8Blc zrFa*m!z@M$wQ1ig`>^|#lzvF@To;8{0r0fz_j-s2cp%rHE~i-x3y!nt$!BF>OgXlT zaS$2+bOP}R0$y(Lot-_1?TB;;Wu_DchKZNYfv$eJ97fz1g}^)TJ>9{B2X)GuUudUw zr+~}al#bhEu~NM2KD$q5(3l{%0lRnaj{K?2+-c$R<;%Z1cI;T^)~#FBt5>gdFaUcH zyByTU)>Q_0e=*C=FS89R2emC-^yu@Bj*h?TMhm_d0tmo?0|z=+ zty-m)EnDW*`eFbnMp}leKBx>x=NVDusAn*7xm->?d-iO80l*(g#Dy(rA%WivFvAdt zrGj@A-ajB1OKQc675ZMhsD%ZTM(d-v|G{Ble>W+_vi=nDq| z^Y-f1tAARvX3Z}t8*2M>5dfNmRx-dculUwGGZ zuxJbS!i5X}ZEI`Wj@iR^2H0G&e(`yNKT}{$Q#p73{P{Lru?UEMQ>X(vJ3HGbWw#e zn8NOj0O0HfunA@|8EuaqJ&Gf3lG^@$=gyt0w2}QAw+KqXcG=bDL{I>1kzuU5x2vn` zcXSN>hGw_YH`S>UEL3s(TJDIyzijQ}7+a9Yr&S$_Tc^`H0c+xJJh%@!x= zs>g3}sApRh4Eu|Lyq+aL5<=3xY|NQXb!@s8#Pe3I8*a2^15VU2>7Crk& zbp!$8AecXB0T7Ea?!jq+O!3+hv^V^4|Ni}omejxK8so~nAc{OmJSmkRppqeHQU-zP z60e05n?Tykeg>!UstV$GLjZWKLoj9@-vtB#_h6|YczB)z2}?ovIo;As)Z-B`HgAwj z_R*z5YSY083INkp#~pzHr&amIix>Z4p-68C#jIo3H-GK*Rtw=TL-=I~z{ZF+yd&T= zz>$e((GU6?8yi#9e}-+P~0+ztQ(B0>cQ5dGO@*u?46r?=4YxPxYT9W9YHWZURiY^6vWZEKgqXa}f*pa3wWAQyuKv$ctLfg~|S`$LkLz}kmckjik5 zMS}pB?KZwMEHf0+k@*16 z+hp;8-3G7?13NB-aGfnsvS!3_=G#E_A5^v>g#?wCP#-AuKPv2q1bVUCb^rhX07*qo IM6N<$f|+G^zW@LL literal 0 HcmV?d00001 diff --git a/src/Resources/Images/ShellIcons/mac-terminal.png b/src/Resources/Images/ShellIcons/mac-terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..569af756762b6ed784c7fa9909015807841c9fe9 GIT binary patch literal 2252 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 zq;+8Design-Anpassungen Fixe Tab-Breite in Titelleiste Verwende nativen Fensterrahmen + DIFF/MERGE TOOL + Installationspfad + Installationspfad zum Diff/Merge Tool + Tool ALLGEMEIN Beim Starten nach Updates suchen Sprache @@ -408,7 +412,6 @@ Benutzer Email Globale Git Benutzer Email Installationspfad - Shell Benutzername Globaler Git Benutzername Git Version @@ -421,10 +424,6 @@ Installationspfad zum GPG Programm Benutzer Signierungsschlüssel GPG Benutzer Signierungsschlüssel - DIFF/MERGE TOOL - Installationspfad - Installationspfad zum Diff/Merge Tool - Tool Remote löschen Ziel: Worktrees löschen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index c56bb3b5..72a6a8ba 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -399,6 +399,10 @@ Theme Overrides Use fixed tab width in titlebar Use native window frame + DIFF/MERGE TOOL + Install Path + Input path for diff/merge tool + Tool GENERAL Check for updates on startup Language @@ -413,7 +417,6 @@ User Email Global git user email Install Path - Shell User Name Global git user name Git version @@ -426,10 +429,10 @@ Input path for installed gpg program User Signing Key User's gpg signing key - DIFF/MERGE TOOL - Install Path - Input path for diff/merge tool - Tool + INTEGRATION + SHELL/TERMINAL + Shell/Terminal + Path Prune Remote Target: Prune Worktrees diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 702b5c5a..40df6d99 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -387,6 +387,10 @@ Dérogations de thème Utiliser des onglets de taille fixe dans la barre de titre Utiliser un cadre de fenêtre natif + OUTIL DIFF/MERGE + Chemin d'installation + Saisir le chemin d'installation de l'outil diff/merge + Outil GÉNÉRAL Vérifier les mises à jour au démarrage Language @@ -401,7 +405,6 @@ E-mail utilsateur E-mail utilsateur global Chemin d'installation - Shell Nom d'utilisateur Nom d'utilisateur global Version de Git @@ -414,10 +417,6 @@ Saisir le chemin d'installation vers le programme GPG Clé de signature de l'utilisateur Clé de signature GPG de l'utilisateur - OUTIL DIFF/MERGE - Chemin d'installation - Saisir le chemin d'installation de l'outil diff/merge - Outil Élaguer une branche distant Cible : Élaguer les Worktrees diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index ad3c6ed2..96cdda3e 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -381,6 +381,10 @@ Tema Sobrescrever Tema Usar largura fixa da aba na barra de título + FERRAMENTA DE DIF/MERGE + Caminho de Instalação + Insira o caminho para a ferramenta de dif/merge + Ferramenta GERAL Verificar atualizações na inicialização Idioma @@ -395,7 +399,6 @@ E-mail do Usuário E-mail global do usuário git Caminho de Instalação - Shell Nome do Usuário Nome global do usuário git Versão do Git @@ -408,10 +411,6 @@ Insira o caminho do programa gpg instalado Chave de Assinatura do Usuário Chave de assinatura gpg do usuário - FERRAMENTA DE DIF/MERGE - Caminho de Instalação - Insira o caminho para a ferramenta de dif/merge - Ferramenta Prunar Remoto Alvo: Podar Worktrees diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index aed1c259..6c8739fe 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -398,6 +398,10 @@ 主题自定义 主标签使用固定宽度 使用系统默认窗体样式 + 对比/合并工具 + 安装路径 + 填写工具可执行文件所在位置 + 工具 通用配置 启动时检测软件更新 显示语言 @@ -412,7 +416,6 @@ 邮箱 默认GIT用户邮箱 安装路径 - 终端Shell 用户名 默认GIT用户名 Git 版本 @@ -425,10 +428,10 @@ 签名程序所在路径 用户签名KEY 输入签名提交所使用的KEY - 对比/合并工具 - 安装路径 - 填写工具可执行文件所在位置 - 工具 + 第三方工具集成 + 终端/SHELL + 终端/SHELL + 安装路径 清理远程已删除分支 目标 : 清理工作树 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 7816b604..5549fe8c 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -398,6 +398,10 @@ 自訂主題 使用固定寬度的分頁標籤 使用系統原生預設視窗樣式 + 對比/合併工具 + 安裝路徑 + 填寫可執行檔案所在路徑 + 工具 一般設定 啟動時檢查軟體更新 顯示語言 @@ -412,7 +416,6 @@ 電子郵件 預設 Git 使用者電子郵件 安裝路徑 - 終端 Shell 使用者名稱 預設 Git 使用者名稱 Git 版本 @@ -425,10 +428,10 @@ 填寫 gpg.exe 所在路徑 使用者簽章金鑰 填寫簽章提交所使用的金鑰 - 對比/合併工具 - 安裝路徑 - 填寫可執行檔案所在路徑 - 工具 + 第三方工具集成 + 終端/SHELL + 終端/SHELL + 安裝路徑 清理遠端已刪除分支 目標: 清理工作區 diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index a81039af..6887e6c9 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -229,16 +229,6 @@ namespace SourceGit.ViewModels } } - public Models.Shell GitShell - { - get => Native.OS.GetShell(); - set - { - if (Native.OS.SetShell(value)) - OnPropertyChanged(); - } - } - public string GitDefaultCloneDir { get => _gitDefaultCloneDir; @@ -274,6 +264,59 @@ namespace SourceGit.ViewModels } } + public int ShellOrTerminal + { + get => _shellOrTerminal; + set + { + if (SetProperty(ref _shellOrTerminal, value)) + { + if (value >= 0 && value < Models.ShellOrTerminal.Supported.Count) + Native.OS.SetShellOrTerminal(Models.ShellOrTerminal.Supported[value]); + else + Native.OS.SetShellOrTerminal(null); + + OnPropertyChanged(nameof(ShellOrTerminalPath)); + } + } + } + + public string ShellOrTerminalPath + { + get => Native.OS.ShellOrTerminal; + set + { + if (value != Native.OS.ShellOrTerminal) + { + Native.OS.ShellOrTerminal = value; + OnPropertyChanged(); + } + } + } + + public int ExternalMergeToolType + { + get => _externalMergeToolType; + set + { + var changed = SetProperty(ref _externalMergeToolType, value); + if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMerger.Supported.Count) + { + var tool = Models.ExternalMerger.Supported[value]; + if (File.Exists(tool.Exec)) + ExternalMergeToolPath = tool.Exec; + else + ExternalMergeToolPath = string.Empty; + } + } + } + + public string ExternalMergeToolPath + { + get => _externalMergeToolPath; + set => SetProperty(ref _externalMergeToolPath, value); + } + public string OpenAIServer { get => Models.OpenAI.Server; @@ -313,29 +356,6 @@ namespace SourceGit.ViewModels } } - public int ExternalMergeToolType - { - get => _externalMergeToolType; - set - { - var changed = SetProperty(ref _externalMergeToolType, value); - if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMerger.Supported.Count) - { - var tool = Models.ExternalMerger.Supported[value]; - if (File.Exists(tool.Exec)) - ExternalMergeToolPath = tool.Exec; - else - ExternalMergeToolPath = string.Empty; - } - } - } - - public string ExternalMergeToolPath - { - get => _externalMergeToolPath; - set => SetProperty(ref _externalMergeToolPath, value); - } - public List RepositoryNodes { get; @@ -560,6 +580,7 @@ namespace SourceGit.ViewModels private string _gitDefaultCloneDir = string.Empty; + private int _shellOrTerminal = -1; private int _externalMergeToolType = 0; private string _externalMergeToolPath = string.Empty; } diff --git a/src/Views/Preference.axaml b/src/Views/Preference.axaml index 2ee1517d..3701e3eb 100644 --- a/src/Views/Preference.axaml +++ b/src/Views/Preference.axaml @@ -194,7 +194,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -280,31 +241,31 @@ - - - - - - - - - + - - - - - - - - - - - - - - - - - @@ -449,51 +375,142 @@ - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/Preference.axaml.cs b/src/Views/Preference.axaml.cs index e76fce2f..af70ee8e 100644 --- a/src/Views/Preference.axaml.cs +++ b/src/Views/Preference.axaml.cs @@ -183,7 +183,7 @@ namespace SourceGit.Views e.Handled = true; } - private async void SelectDefaultCloneDir(object _1, RoutedEventArgs _2) + private async void SelectDefaultCloneDir(object _, RoutedEventArgs e) { var options = new FolderPickerOpenOptions() { AllowMultiple = false }; try @@ -194,13 +194,15 @@ namespace SourceGit.Views ViewModels.Preference.Instance.GitDefaultCloneDir = selected[0].Path.LocalPath; } } - catch (Exception e) + catch (Exception ex) { - App.RaiseException(string.Empty, $"Failed to select default clone directory: {e.Message}"); + App.RaiseException(string.Empty, $"Failed to select default clone directory: {ex.Message}"); } + + e.Handled = true; } - private async void SelectGPGExecutable(object _1, RoutedEventArgs _2) + private async void SelectGPGExecutable(object _, RoutedEventArgs e) { var patterns = new List(); if (OperatingSystem.IsWindows()) @@ -219,14 +221,39 @@ namespace SourceGit.Views { GPGExecutableFile = selected[0].Path.LocalPath; } + + e.Handled = true; } - private async void SelectExternalMergeTool(object _1, RoutedEventArgs _2) + private async void SelectShellOrTerminal(object _, RoutedEventArgs e) + { + var type = ViewModels.Preference.Instance.ShellOrTerminal; + if (type == -1) + return; + + var shell = Models.ShellOrTerminal.Supported[type]; + var options = new FilePickerOpenOptions() + { + FileTypeFilter = [new FilePickerFileType(shell.Name) { Patterns = [shell.Exec] }], + AllowMultiple = false, + }; + + var selected = await StorageProvider.OpenFilePickerAsync(options); + if (selected.Count == 1) + { + ViewModels.Preference.Instance.ShellOrTerminalPath = selected[0].Path.LocalPath; + } + + e.Handled = true; + } + + private async void SelectExternalMergeTool(object _, RoutedEventArgs e) { var type = ViewModels.Preference.Instance.ExternalMergeToolType; if (type < 0 || type >= Models.ExternalMerger.Supported.Count) { ViewModels.Preference.Instance.ExternalMergeToolType = 0; + e.Handled = true; return; } @@ -242,6 +269,8 @@ namespace SourceGit.Views { ViewModels.Preference.Instance.ExternalMergeToolPath = selected[0].Path.LocalPath; } + + e.Handled = true; } private void SetIfChanged(Dictionary cached, string key, string value, string defValue) diff --git a/src/Views/WorkingCopy.axaml.cs b/src/Views/WorkingCopy.axaml.cs index 3ce63941..f8e4fa23 100644 --- a/src/Views/WorkingCopy.axaml.cs +++ b/src/Views/WorkingCopy.axaml.cs @@ -142,7 +142,7 @@ namespace SourceGit.Views App.RaiseException(null, "No files added to commit!"); } } - + e.Handled = true; } }