mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-23 05:05:00 +00:00
refactor: terminal/shell integration (#471)
This commit is contained in:
parent
817f8919fd
commit
fb0120d338
27 changed files with 445 additions and 427 deletions
|
@ -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<Models.ExternalTool> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Models.ExternalTool> 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)
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace SourceGit.Native
|
|||
void SetupApp(AppBuilder builder);
|
||||
|
||||
string FindGitExecutable();
|
||||
string FindTerminal(Models.ShellOrTerminal shell);
|
||||
List<Models.ExternalTool> 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<Models.ExternalTool> 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)
|
||||
|
|
|
@ -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<Models.ExternalTool> 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue