feature<VSCode>: supports to open repository with Visual Studio Code

This commit is contained in:
leo 2021-09-13 14:22:25 +08:00
parent 4a676e094d
commit 4456019968
8 changed files with 65 additions and 19 deletions

View file

@ -0,0 +1,26 @@
using System.Runtime.InteropServices;
using System.Text;
namespace SourceGit.Models {
/// <summary>
/// 用于在PATH中检测可执行文件
/// </summary>
public class ExecutableFinder {
// https://docs.microsoft.com/en-us/windows/desktop/api/shlwapi/nf-shlwapi-pathfindonpathw
// https://www.pinvoke.net/default.aspx/shlwapi.PathFindOnPath
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = false)]
private static extern bool PathFindOnPath([In, Out] StringBuilder pszFile, [In] string[] ppszOtherDirs);
/// <summary>
/// 从PATH中找到可执行文件路径
/// </summary>
/// <param name="exec"></param>
/// <returns></returns>
public static string Find(string exec) {
var builder = new StringBuilder(exec, 259);
var rs = PathFindOnPath(builder, null);
return rs ? builder.ToString() : null;
}
}
}

View file

@ -70,4 +70,6 @@
<Geometry x:Key="Icon.Remote.Add">M364 512h67v108h108v67h-108v108h-67v-108h-108v-67h108v-108zm298-64A107 107 0 01768 555C768 614 720 660 660 660h-108v-54h-108v-108h-94v108h-94c4-21 22-47 44-51l-1-12a75 75 0 0171-75a128 128 0 01239-7a106 106 0 0153-14z</Geometry> <Geometry x:Key="Icon.Remote.Add">M364 512h67v108h108v67h-108v108h-67v-108h-108v-67h108v-108zm298-64A107 107 0 01768 555C768 614 720 660 660 660h-108v-54h-108v-108h-94v108h-94c4-21 22-47 44-51l-1-12a75 75 0 0171-75a128 128 0 01239-7a106 106 0 0153-14z</Geometry>
<Geometry x:Key="Icon.Tag">M177 156c-22 5-33 17-36 37c-10 57-33 258-13 278l445 445c23 23 61 23 84 0l246-246c23-23 23-61 0-84l-445-445C437 120 231 145 177 156zM331 344c-26 26-69 26-95 0c-26-26-26-69 0-95s69-26 95 0C357 276 357 318 331 344z</Geometry> <Geometry x:Key="Icon.Tag">M177 156c-22 5-33 17-36 37c-10 57-33 258-13 278l445 445c23 23 61 23 84 0l246-246c23-23 23-61 0-84l-445-445C437 120 231 145 177 156zM331 344c-26 26-69 26-95 0c-26-26-26-69 0-95s69-26 95 0C357 276 357 318 331 344z</Geometry>
<Geometry x:Key="Icon.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</Geometry> <Geometry x:Key="Icon.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</Geometry>
<Geometry x:Key="Icon.VSCode">M719 85 388 417l-209-165L87 299v427l92 47 210-164L720 939 939 850V171zM186 610V412l104 104zm526 55L514 512l198-153z</Geometry>
</ResourceDictionary> </ResourceDictionary>

View file

@ -115,6 +115,7 @@
<sys:String x:Key="Text.CreateTag.Message.Placeholder">Optional.</sys:String> <sys:String x:Key="Text.CreateTag.Message.Placeholder">Optional.</sys:String>
<sys:String x:Key="Text.Dashboard.Explore">Open In File Browser</sys:String> <sys:String x:Key="Text.Dashboard.Explore">Open In File Browser</sys:String>
<sys:String x:Key="Text.Dashboard.VSCode">Open In Visual Studio Code</sys:String>
<sys:String x:Key="Text.Dashboard.Terminal">Open Git Bash</sys:String> <sys:String x:Key="Text.Dashboard.Terminal">Open Git Bash</sys:String>
<sys:String x:Key="Text.Dashboard.Search">Search Commit</sys:String> <sys:String x:Key="Text.Dashboard.Search">Search Commit</sys:String>
<sys:String x:Key="Text.Dashboard.Configure">Configure this repository</sys:String> <sys:String x:Key="Text.Dashboard.Configure">Configure this repository</sys:String>

View file

@ -114,6 +114,7 @@
<sys:String x:Key="Text.CreateTag.Message.Placeholder">选填</sys:String> <sys:String x:Key="Text.CreateTag.Message.Placeholder">选填</sys:String>
<sys:String x:Key="Text.Dashboard.Explore">在文件浏览器中打开</sys:String> <sys:String x:Key="Text.Dashboard.Explore">在文件浏览器中打开</sys:String>
<sys:String x:Key="Text.Dashboard.VSCode">在Visual Studio Code中打开</sys:String>
<sys:String x:Key="Text.Dashboard.Terminal">打开GIT终端</sys:String> <sys:String x:Key="Text.Dashboard.Terminal">打开GIT终端</sys:String>
<sys:String x:Key="Text.Dashboard.Search">查找提交</sys:String> <sys:String x:Key="Text.Dashboard.Search">查找提交</sys:String>
<sys:String x:Key="Text.Dashboard.Configure">配置本仓库</sys:String> <sys:String x:Key="Text.Dashboard.Configure">配置本仓库</sys:String>

View file

@ -194,7 +194,7 @@
<CheckBox <CheckBox
Grid.Row="9" Grid.Column="1" Grid.Row="9" Grid.Column="1"
Content="{DynamicResource Text.Preference.UseWindowsTerminal}" Content="{DynamicResource Text.Preference.UseWindowsTerminal}"
IsEnabled="{Binding ElementName=me, Path=EnableWindowsTerminal}" IsEnabled="{Binding ElementName=me, Path=HasWindowsTerminal}"
IsChecked="{Binding Source={x:Static models:Preference.Instance}, Path=General.UseWindowsTerminal, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static models:Preference.Instance}, Path=General.UseWindowsTerminal, Mode=TwoWay}"/>
<!-- Git Group --> <!-- Git Group -->

View file

@ -1,7 +1,6 @@
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.Runtime.InteropServices; using System.IO;
using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -16,21 +15,13 @@ namespace SourceGit.Views {
public string Email { get; set; } public string Email { get; set; }
public string CRLF { get; set; } public string CRLF { get; set; }
public string Version { get; set; } public string Version { get; set; }
public bool HasWindowsTerminal { get; set; }
const int MAX_PATH = 260;
// https://docs.microsoft.com/en-us/windows/desktop/api/shlwapi/nf-shlwapi-pathfindonpathw
// https://www.pinvoke.net/default.aspx/shlwapi.PathFindOnPath
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = false)]
private static extern bool PathFindOnPath([In, Out] StringBuilder pszFile, [In] string[] ppszOtherDirs);
public bool EnableWindowsTerminal { get; set; } = PathFindOnPath(new StringBuilder("wt.exe", MAX_PATH), null);
public Preference() { public Preference() {
UpdateGitInfo(false); UpdateGitInfo(false);
if (!EnableWindowsTerminal) { HasWindowsTerminal = Models.ExecutableFinder.Find("wt.exe") != null;
Models.Preference.Instance.General.UseWindowsTerminal = false; if (HasWindowsTerminal) Models.Preference.Instance.General.UseWindowsTerminal = false;
}
InitializeComponent(); InitializeComponent();
} }
@ -65,16 +56,15 @@ namespace SourceGit.Views {
} }
private void SelectGitPath(object sender, RoutedEventArgs e) { private void SelectGitPath(object sender, RoutedEventArgs e) {
var sb = new StringBuilder("git.exe", MAX_PATH); var initDir = Models.ExecutableFinder.Find("git.exe");
string dir = PathFindOnPath(sb, null) if (initDir == null) initDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
? sb.ToString() else initDir = Path.GetDirectoryName(initDir);
: Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var dialog = new OpenFileDialog { var dialog = new OpenFileDialog {
Filter = "Git Executable|git.exe", Filter = "Git Executable|git.exe",
FileName = "git.exe", FileName = "git.exe",
Title = App.Text("Preference.Dialog.GitExe"), Title = App.Text("Preference.Dialog.GitExe"),
InitialDirectory = dir, InitialDirectory = initDir,
CheckFileExists = true, CheckFileExists = true,
}; };

View file

@ -30,6 +30,14 @@
Icon="{DynamicResource Icon.Folder.Open}" Icon="{DynamicResource Icon.Folder.Open}"
ToolTip="{DynamicResource Text.Dashboard.Explore}" ToolTip="{DynamicResource Text.Dashboard.Explore}"
Click="Explore"/> Click="Explore"/>
<controls:IconButton
x:Name="btnOpenWithVSCode"
Visibility="Collapsed"
Margin="8,0"
Padding="0,9"
Icon="{DynamicResource Icon.VSCode}"
ToolTip="{DynamicResource Text.Dashboard.VSCode}"
Click="OpenInVSCode"/>
<controls:IconButton <controls:IconButton
Margin="8,0" Margin="8,0"
Padding="0,9" Padding="0,9"

View file

@ -56,6 +56,9 @@ namespace SourceGit.Views.Widgets {
InitializeComponent(); InitializeComponent();
InitPages(); InitPages();
var vscode = Models.ExecutableFinder.Find("code.cmd");
if (vscode != null) btnOpenWithVSCode.Visibility = Visibility.Visible;
var watcher = Models.Watcher.Get(repo.Path); var watcher = Models.Watcher.Get(repo.Path);
watcher.Navigate += NavigateTo; watcher.Navigate += NavigateTo;
watcher.BranchChanged += UpdateBranches; watcher.BranchChanged += UpdateBranches;
@ -309,6 +312,21 @@ namespace SourceGit.Views.Widgets {
e.Handled = true; e.Handled = true;
} }
private void OpenInVSCode(object sender, RoutedEventArgs e) {
var vscode = Models.ExecutableFinder.Find("code.cmd");
if (vscode == null) return;
vscode = Path.Combine(Path.GetDirectoryName(vscode), "..", "Code.exe");
Process.Start(new ProcessStartInfo {
WorkingDirectory = repo.Path,
FileName = vscode,
Arguments = $"\"{repo.Path}\"",
UseShellExecute = false,
});
e.Handled = true;
}
private void Terminal(object sender, RoutedEventArgs e) { private void Terminal(object sender, RoutedEventArgs e) {
var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe"); var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe");
if (!File.Exists(bash)) { if (!File.Exists(bash)) {