using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Text.Json.Serialization; using System.Threading.Tasks; using Newtonsoft.Json; namespace CrossLangDevStudio; class CrossLangShell { private static CrossLangSettings? settings = null; public static CrossLangSettings Settings { get { if (settings != null) return settings; var config = CrossLangConfigDirectory; if (!string.IsNullOrWhiteSpace(config)) { var devStudioDir = Path.Combine(config, "DevStudio"); Directory.CreateDirectory(devStudioDir); var settingsFile = Path.Combine(devStudioDir, "Settings.json"); if (File.Exists(settingsFile)) { settings = JsonConvert.DeserializeObject(File.ReadAllText(settingsFile)); } } return settings is null ? settings = new CrossLangSettings() : settings; } } private static string _crosslang_config_dir = ""; public static string CrossLangConfigDirectory => string.IsNullOrWhiteSpace(_crosslang_config_dir) ? _crosslang_config_dir = GetCrossLangDirectory() : _crosslang_config_dir; public static List GetRecentProjects() { var config = CrossLangConfigDirectory; if (string.IsNullOrWhiteSpace(config)) return new List(); var devStudioDir = Path.Combine(config, "DevStudio"); Directory.CreateDirectory(devStudioDir); var configPath = Path.Combine(devStudioDir, "Recents.json"); if (File.Exists(configPath)) { var list = JsonConvert.DeserializeObject>(File.ReadAllText(configPath)); if (list is not null) return list; } return new List(); } public static void OpenFolderInFileManager(string path) { using (Process p = new Process()) { p.StartInfo.FileName = path; p.StartInfo.UseShellExecute = true; p.Start(); } } public static void EnsureRecent(string projectPath) { projectPath = Path.GetFullPath(projectPath).TrimEnd(Path.DirectorySeparatorChar); var recents = GetRecentProjects(); if (recents.Contains(projectPath)) { recents.Remove(projectPath); } recents.Insert(0, projectPath); if (recents.Count > 5) { recents.RemoveRange(5, recents.Count - 5); } var config = CrossLangConfigDirectory; if (string.IsNullOrWhiteSpace(config)) return; var devStudioDir = Path.Combine(config, "DevStudio"); Directory.CreateDirectory(devStudioDir); var configPath = Path.Combine(devStudioDir, "Recents.json"); File.WriteAllText(configPath, JsonConvert.SerializeObject(recents, Formatting.Indented)); } public static string GetRealPath(string exec) { foreach (var item in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator)) { var path = Path.Combine(item, exec); if (File.Exists(path)) return path; foreach (var ext in (Environment.GetEnvironmentVariable("PATHEXT") ?? "").Split(Path.PathSeparator)) { if (File.Exists(path + ext)) return path + ext; } } return ""; } public static string CrossLangPath { get { var path = GetRealPath("crosslang"); return path; } } public static bool HaveCrossLang { get { return !string.IsNullOrWhiteSpace(CrossLangPath); } } public static void BuildProjectInFolder(string folder) { OpenTerminal(false, folder, CrossLangPath, "build"); } public static void RunProjectInFolder(string folder) { OpenTerminal(true, folder, CrossLangPath, "run"); } public static void OpenTerminalInFolder(string folder) { if (OperatingSystem.IsLinux()) { OpenTerminal(false, folder, "", []); } } public static void OpenTerminal(bool keepOpen, string workingDirectory, string commandName, params string[] args) { var preferedTerminalCommand = Settings.PreferedTerminalCommand; if (!string.IsNullOrWhiteSpace(preferedTerminalCommand)) { var firstArgs = preferedTerminalCommand.Split(" "); using Process process = new(); process.StartInfo.UseShellExecute = false; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.FileName = firstArgs[0]; for (int i = 1; i < firstArgs.Length; i++) { process.StartInfo.ArgumentList.Add(firstArgs[i]); } foreach (var arg in args) process.StartInfo.ArgumentList.Add(arg); process.Start(); return; } if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD()) { string konsole = GetRealPath("konsole"); string gnome_terminal = GetRealPath("gnome-terminal"); string xterm = GetRealPath("xterm"); if (File.Exists(konsole)) { using Process process = new Process(); process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.FileName = konsole; process.StartInfo.UseShellExecute = false; if (commandName.Length != 0) { if (keepOpen) process.StartInfo.ArgumentList.Add("--hold"); process.StartInfo.ArgumentList.Add("-e"); process.StartInfo.ArgumentList.Add(commandName); foreach (var arg in args) { process.StartInfo.ArgumentList.Add(arg); } } process.Start(); } else if (File.Exists(gnome_terminal)) { } else if (File.Exists(xterm)) { } } else if (OperatingSystem.IsWindows()) { using Process process = new Process(); process.StartInfo.FileName = GetRealPath("cmd.exe"); if(commandName.Length > 0) process.StartInfo.ArgumentList.Add(keepOpen ? "/K" : "/C"); process.StartInfo.CreateNoWindow = false; process.StartInfo.UseShellExecute = false; process.StartInfo.WorkingDirectory = workingDirectory; if(commandName.Length > 0) process.StartInfo.ArgumentList.Add(commandName); foreach (var item in args) process.StartInfo.ArgumentList.Add(item); process.Start(); } } private static string GetCrossLangDirectory() { string path = CrossLangPath; if (string.IsNullOrWhiteSpace(path)) return ""; using Process process = new Process(); process.StartInfo.ArgumentList.Add("configdir"); process.StartInfo.FileName = path; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; if (process.Start()) { process.WaitForExit(); var text = process.StandardOutput.ReadToEnd(); return (text ?? "").Replace("\n", "").Replace("\r", ""); } return ""; } internal static bool CreateProject(string templateName, string path) { string cpath = CrossLangPath; if (string.IsNullOrWhiteSpace(cpath)) return false; using Process process = new Process(); process.StartInfo.ArgumentList.Add("new"); process.StartInfo.ArgumentList.Add(templateName); process.StartInfo.WorkingDirectory = path; process.StartInfo.FileName = cpath; process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; if (process.Start()) { process.WaitForExit(); return process.ExitCode == 0; } return false; } } public class CrossLangSettings { [JsonProperty("prefered_terminal_command")] public string PreferedTerminalCommand { get; set; } = ""; [JsonProperty("prefered_project_directory")] public string PreferedProjectDirectory { get; set; } = ""; [Newtonsoft.Json.JsonIgnore] public string ProjectDirectory { get { if (!string.IsNullOrWhiteSpace(PreferedProjectDirectory)) return PreferedProjectDirectory; string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "CrossLangProjects"); Directory.CreateDirectory(path); return path; } } }