using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.Versioning; using Avalonia; using Avalonia.Dialogs; using Avalonia.Media; namespace SourceGit.Native { [SupportedOSPlatform("linux")] internal class Linux : OS.IBackend { class Terminal { public string FilePath { get; set; } = string.Empty; public string OpenArgFormat { get; set; } = string.Empty; 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 FontManagerOptions() { DefaultFamilyName = "fonts:SourceGit#JetBrains Mono", }); // Free-desktop file picker has an extra black background panel. builder.UseManagedSystemDialogs(); } public string FindGitExecutable() { return FindExecutable("git"); } public List FindExternalTools() { var finder = new Models.ExternalToolsFinder(); finder.VSCode(() => FindExecutable("code")); finder.VSCodeInsiders(() => FindExecutable("code-insiders")); finder.Fleet(FindJetBrainsFleet); finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox"); finder.SublimeText(() => FindExecutable("subl")); return finder.Founded; } public void OpenBrowser(string url) { if (string.IsNullOrEmpty(_xdgOpenPath)) App.RaiseException("", $"Can NOT find `xdg-open` command!!!"); else Process.Start(_xdgOpenPath, $"\"{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}\""); } else { var dir = Path.GetDirectoryName(path); if (Directory.Exists(dir)) { Process.Start(_xdgOpenPath, $"\"{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!"); else _terminal.Open(dir); } public void OpenWithDefaultEditor(string file) { if (string.IsNullOrEmpty(_xdgOpenPath)) { App.RaiseException("", $"Can NOT find `xdg-open` command!!!"); return; } var proc = Process.Start(_xdgOpenPath, $"\"{file}\""); proc.WaitForExit(); if (proc.ExitCode != 0) App.RaiseException("", $"Failed to open \"{file}\""); proc.Close(); } private string FindExecutable(string filename) { 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, filename); if (File.Exists(test)) { return test; } } 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}\""); } } 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 = string.Empty; private Terminal _terminal = null; } }