From 1196fabfc1f03d1cb3822ddb3f103ee2934ebd04 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 6 Apr 2024 15:31:13 +0800 Subject: [PATCH] feature: external editor supports Sublime Text --- README.md | 1 + src/Models/ExternalMergeTools.cs | 8 ++-- src/Native/Linux.cs | 31 ++++++++++++++ src/Native/MacOS.cs | 26 ++++++++++++ src/Native/Windows.cs | 39 ++++++++++++++++++ .../ExternalToolIcons/sublime_text.png | Bin 0 -> 15791 bytes 6 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 src/Resources/ExternalToolIcons/sublime_text.png diff --git a/README.md b/README.md index 99928589..351fecb0 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ This app supports open repository in external editors listed in the table below. | 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. diff --git a/src/Models/ExternalMergeTools.cs b/src/Models/ExternalMergeTools.cs index 4baab460..f07ef088 100644 --- a/src/Models/ExternalMergeTools.cs +++ b/src/Models/ExternalMergeTools.cs @@ -22,10 +22,10 @@ namespace SourceGit.Models new ExternalMergeTools(0, "Custom", "", "", ""), new ExternalMergeTools(1, "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(2, "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(3, "Visual Studio 2017/2019", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMergeTools(3, "Visual Studio 2017/2019/2022", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(4, "Tortoise Merge", "TortoiseMerge.exe;TortoiseGitMerge.exe", "-base:\"$BASE\" -theirs:\"$REMOTE\" -mine:\"$LOCAL\" -merged:\"$MERGED\"", "-base:\"$LOCAL\" -theirs:\"$REMOTE\""), new ExternalMergeTools(5, "KDiff3", "kdiff3.exe", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(6, "Beyond Compare 4", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMergeTools(6, "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(7, "WinMerge", "WinMergeU.exe", "-u -e \"$REMOTE\" \"$LOCAL\" \"$MERGED\"", "-u -e \"$LOCAL\" \"$REMOTE\""), }; } @@ -37,7 +37,7 @@ namespace SourceGit.Models new ExternalMergeTools(2, "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(3, "Visual Studio Code - Insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(4, "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(5, "Beyond Compare 4", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMergeTools(5, "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), }; } else if (OperatingSystem.IsLinux()) @@ -47,7 +47,7 @@ namespace SourceGit.Models new ExternalMergeTools(1, "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(2, "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), new ExternalMergeTools(3, "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(4, "Beyond Compare 4", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMergeTools(4, "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), }; } else diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index dd31e0c8..b56ac31a 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -71,6 +71,18 @@ namespace SourceGit.Native }); } + var sublime = FindSublimeText(); + if (!string.IsNullOrEmpty(sublime) && File.Exists(sublime)) + { + editors.Add(new Models.ExternalEditor + { + Name = "Sublime Text", + Icon = "sublime_text.png", + Executable = sublime, + OpenCmdArgs = "\"{0}\"", + }); + } + return editors; } @@ -187,6 +199,25 @@ namespace SourceGit.Native return string.Empty; } + + private string FindSublimeText() + { + if (File.Exists("/usr/bin/subl")) + { + return "/usr/bin/subl"; + } + + if (File.Exists("/usr/local/bin/subl")) + { + return "/usr/local/bin/subl"; + } + + var customPath = Environment.GetEnvironmentVariable("SUBLIME_TEXT_PATH"); + if (!string.IsNullOrEmpty(customPath)) + return customPath; + + return string.Empty; + } #endregion } } diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index ab9bc992..a695b7dc 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -68,6 +68,18 @@ namespace SourceGit.Native }); } + var sublime = FindSublimeText(); + if (!string.IsNullOrEmpty(sublime) && File.Exists(sublime)) + { + editors.Add(new Models.ExternalEditor + { + Name = "Sublime Text", + Icon = "sublime_text.png", + Executable = sublime, + OpenCmdArgs = "\"{0}\"", + }); + } + return editors; } @@ -150,6 +162,20 @@ namespace SourceGit.Native return string.Empty; } + + private string FindSublimeText() + { + if (File.Exists("/Applications/Sublime Text.app/Contents/SharedSupport/bin")) + { + return "/Applications/Sublime Text.app/Contents/SharedSupport/bin"; + } + + var customPath = Environment.GetEnvironmentVariable("SUBLIME_TEXT_PATH"); + if (!string.IsNullOrEmpty(customPath)) + return customPath; + + return string.Empty; + } #endregion } } diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index f91a6da5..e7ef0fd8 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -154,6 +154,18 @@ namespace SourceGit.Native }); } + var sublime = FindSublimeText(); + if (!string.IsNullOrEmpty(sublime) && File.Exists(sublime)) + { + editors.Add(new Models.ExternalEditor + { + Name = "Sublime Text", + Icon = "sublime_text.png", + Executable = sublime, + OpenCmdArgs = "\"{0}\"", + }); + } + return editors; } @@ -303,6 +315,33 @@ namespace SourceGit.Native return string.Empty; } + + private string FindSublimeText() + { + var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey( + Microsoft.Win32.RegistryHive.LocalMachine, + Microsoft.Win32.RegistryView.Registry64); + + var sublime = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sublime Text_is1"); + if (sublime != null) + { + var icon = sublime.GetValue("DisplayIcon") as string; + return Path.Combine(Path.GetDirectoryName(icon), "subl.exe"); + } + + var sublime3 = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sublime Text 3_is1"); + if (sublime3 != null) + { + var icon = sublime3.GetValue("DisplayIcon") as string; + return Path.Combine(Path.GetDirectoryName(icon), "subl.exe"); + } + + var customPath = Environment.GetEnvironmentVariable("SUBLIME_TEXT_PATH"); + if (!string.IsNullOrEmpty(customPath)) + return customPath; + + return string.Empty; + } #endregion private void OpenFolderAndSelectFile(string folderPath) diff --git a/src/Resources/ExternalToolIcons/sublime_text.png b/src/Resources/ExternalToolIcons/sublime_text.png new file mode 100644 index 0000000000000000000000000000000000000000..2296cecb95d51888aa11d4a1bb28dabc4b10951f GIT binary patch literal 15791 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 Dksd#H literal 0 HcmV?d00001