diff --git a/README.md b/README.md index 351fecb0..9af7f471 100644 --- a/README.md +++ b/README.md @@ -53,20 +53,20 @@ For **Linux** users: * Maybe you need to set environment variable `AVALONIA_SCREEN_SCALE_FACTORS`. See https://github.com/AvaloniaUI/Avalonia/wiki/Configuring-X11-per-monitor-DPI. * Modify `SourceGit.desktop.template` (replace SOURCEGIT_LOCAL_FOLDER with real path) and move it into `~/.local/share/applications`. -## External Editors +## External Tools -This app supports open repository in external editors listed in the table below. +This app supports open repository in external tools listed in the table below. -| Editor | Windows | macOS | Linux | Environment Variable | +| Tool | Windows | macOS | Linux | Environment Variable | | --- | --- | --- | --- | --- | | Visual Studio Code | YES | YES | YES | VSCODE_PATH | | Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS_PATH | | JetBrains Fleet | YES | YES | YES | FLEET_PATH | | Sublime Text | YES | YES | YES | SUBLIME_TEXT_PATH | -You can set the given environment variable for special editor if it can NOT be found by this app automatically. +You can set the given environment variable for special tool if it can NOT be found by this app automatically. -## Screen Shots +## Screenshots * Dark Theme diff --git a/src/Models/ExternalEditor.cs b/src/Models/ExternalTool.cs similarity index 86% rename from src/Models/ExternalEditor.cs rename to src/Models/ExternalTool.cs index 094d0a5f..5383a6bf 100644 --- a/src/Models/ExternalEditor.cs +++ b/src/Models/ExternalTool.cs @@ -5,7 +5,7 @@ using System.IO; namespace SourceGit.Models { - public class ExternalEditor + public class ExternalTool { public string Name { get; set; } = string.Empty; public string Icon { get; set; } = string.Empty; @@ -24,13 +24,13 @@ namespace SourceGit.Models } } - public class ExternalEditorFinder + public class ExternalToolsFinder { - public List Editors + public List Founded { get; private set; - } = new List(); + } = new List(); public void VSCode(Func platform_finder) { @@ -52,7 +52,7 @@ namespace SourceGit.Models TryAdd("Sublime Text", "sublime_text.png", "\"{0}\"", "SUBLIME_TEXT_PATH", platform_finder); } - private void TryAdd(string name, string icon, string args, string env, Func finder) + public void TryAdd(string name, string icon, string args, string env, Func finder) { var path = Environment.GetEnvironmentVariable(env); if (string.IsNullOrEmpty(path) || !File.Exists(path)) @@ -62,7 +62,7 @@ namespace SourceGit.Models return; } - Editors.Add(new ExternalEditor + Founded.Add(new ExternalTool { Name = name, Icon = icon, diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index 56d42306..df5d753f 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -31,14 +31,14 @@ namespace SourceGit.Native return string.Empty; } - public List FindExternalEditors() + public List FindExternalTools() { - var finder = new Models.ExternalEditorFinder(); + var finder = new Models.ExternalToolsFinder(); finder.VSCode(() => "/usr/share/code/code"); finder.VSCodeInsiders(() => "/usr/share/code-insiders/code-insiders"); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet"); finder.SublimeText(() => File.Exists("/usr/bin/subl") ? "/usr/bin/subl" : "/usr/local/bin/subl"); - return finder.Editors; + return finder.Founded; } public void OpenBrowser(string url) diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index ac864986..28519e40 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -28,14 +28,14 @@ namespace SourceGit.Native return string.Empty; } - public List FindExternalEditors() + public List FindExternalTools() { - var finder = new Models.ExternalEditorFinder(); + var finder = new Models.ExternalToolsFinder(); finder.VSCode(() => "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"); finder.VSCodeInsiders(() => "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/Applications/Fleet.app/Contents/MacOS/Fleet"); finder.SublimeText(() => "/Applications/Sublime Text.app/Contents/SharedSupport/bin"); - return finder.Editors; + return finder.Founded; } public void OpenBrowser(string url) diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 61a33ed6..03b98e6d 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -12,7 +12,7 @@ namespace SourceGit.Native void SetupApp(AppBuilder builder); string FindGitExecutable(); - List FindExternalEditors(); + List FindExternalTools(); void OpenTerminal(string workdir); void OpenInFileManager(string path, bool select); @@ -21,7 +21,8 @@ namespace SourceGit.Native } public static string GitExecutable { get; set; } = string.Empty; - public static List ExternalEditors { get; set; } = new List(); + public static bool UsePowershellOnWindows { get; set; } = false; + public static List ExternalTools { get; set; } = new List(); static OS() { @@ -42,7 +43,7 @@ namespace SourceGit.Native throw new Exception("Platform unsupported!!!"); } - ExternalEditors = _backend.FindExternalEditors(); + ExternalTools = _backend.FindExternalTools(); } public static void SetupApp(AppBuilder builder) diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 78fef704..1b5af417 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -54,6 +54,16 @@ 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 Windows() + { + 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"); + _powershellPath = pwsh != null ? pwsh.GetValue(null) as string : "powershell"; + } + public void SetupApp(AppBuilder builder) { builder.With(new FontManagerOptions() @@ -114,14 +124,14 @@ namespace SourceGit.Native return null; } - public List FindExternalEditors() + public List FindExternalTools() { - var finder = new Models.ExternalEditorFinder(); + var finder = new Models.ExternalToolsFinder(); finder.VSCode(FindVSCode); finder.VSCodeInsiders(FindVSCodeInsiders); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe"); finder.SublimeText(FindSublimeText); - return finder.Editors; + return finder.Founded; } public void OpenBrowser(string url) @@ -133,19 +143,27 @@ namespace SourceGit.Native public void OpenTerminal(string workdir) { - var binDir = Path.GetDirectoryName(OS.GitExecutable); - var bash = Path.Combine(binDir, "bash.exe"); - if (!File.Exists(bash)) - { - App.RaiseException(string.IsNullOrEmpty(workdir) ? "" : workdir, $"Can NOT found bash.exe under '{binDir}'"); - return; - } - - var startInfo = new ProcessStartInfo(); - startInfo.UseShellExecute = true; - startInfo.FileName = bash; + var startInfo = new ProcessStartInfo() { UseShellExecute = true }; if (!string.IsNullOrEmpty(workdir) && Path.Exists(workdir)) startInfo.WorkingDirectory = workdir; + + if (OS.UsePowershellOnWindows) + { + startInfo.FileName = _powershellPath; + } + else + { + var binDir = Path.GetDirectoryName(OS.GitExecutable); + var bash = Path.Combine(binDir, "bash.exe"); + if (!File.Exists(bash)) + { + App.RaiseException(string.IsNullOrEmpty(workdir) ? "" : workdir, $"Can NOT found bash.exe under '{binDir}'"); + return; + } + + startInfo.FileName = bash; + } + Process.Start(startInfo); } @@ -281,5 +299,7 @@ namespace SourceGit.Native ILFree(pidl); } } + + private string _powershellPath = string.Empty; } } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 68e57b4c..08b41c0a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -268,6 +268,7 @@ Install Path User Name Global git user name + Use Powershell instead of Git bash Git version GPG SIGNING Commit GPG signing diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 79cf9973..8f03755b 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -268,6 +268,7 @@ 安装路径 用户名 默认GIT用户名 + 使用PowerShell替代Git Bash Git 版本 GPG签名 启用提交签名 diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index ee8f96a9..7d97ba4f 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -219,6 +219,19 @@ namespace SourceGit.ViewModels } } + public bool UsePowershellOnWindows + { + get => Native.OS.UsePowershellOnWindows; + set + { + if (Native.OS.UsePowershellOnWindows != value) + { + Native.OS.UsePowershellOnWindows = value; + OnPropertyChanged(nameof(UsePowershellOnWindows)); + } + } + } + public int ExternalMergeToolType { get => _externalMergeToolType; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 61f034ff..89740d7d 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -287,10 +287,10 @@ namespace SourceGit.ViewModels Native.OS.OpenTerminal(_fullpath); } - public ContextMenu CreateContextMenuForExternalEditors() + public ContextMenu CreateContextMenuForExternalTools() { - var editors = Native.OS.ExternalEditors; - if (editors.Count == 0) + var tools = Native.OS.ExternalTools; + if (tools.Count == 0) { App.RaiseException(_fullpath, "No available external editors found!"); return null; @@ -300,16 +300,16 @@ namespace SourceGit.ViewModels menu.Placement = PlacementMode.BottomEdgeAlignedLeft; RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality); - foreach (var editor in editors) + foreach (var tool in tools) { - var dupEditor = editor; - var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{dupEditor.Icon}", UriKind.RelativeOrAbsolute)); + var dupTool = tool; + var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{dupTool.Icon}", UriKind.RelativeOrAbsolute)); var item = new MenuItem(); - item.Header = App.Text("Repository.OpenIn", dupEditor.Name); + item.Header = App.Text("Repository.OpenIn", dupTool.Name); item.Icon = new Image { Width = 16, Height = 16, Source = new Bitmap(icon) }; item.Click += (o, e) => { - dupEditor.Open(_fullpath); + dupTool.Open(_fullpath); e.Handled = true; }; diff --git a/src/Views/Preference.axaml b/src/Views/Preference.axaml index 24d10e8d..49cd30f2 100644 --- a/src/Views/Preference.axaml +++ b/src/Views/Preference.axaml @@ -231,7 +231,7 @@ - + + + diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 4bfb98a6..d618ea4c 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -22,7 +22,7 @@ - diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index 858f5f3d..43d9ee11 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -61,11 +61,11 @@ namespace SourceGit.Views InitializeComponent(); } - private void OnOpenWithExternalEditor(object sender, RoutedEventArgs e) + private void OnOpenWithExternalTools(object sender, RoutedEventArgs e) { if (sender is Button button && DataContext is ViewModels.Repository repo) { - var menu = repo.CreateContextMenuForExternalEditors(); + var menu = repo.CreateContextMenuForExternalTools(); if (menu != null) { menu.Open(button);