private bool ProcessPrompt(string cmd, List <PromptCommand> cmdList, IPromptConfiguration config) { Warning = string.Empty; var testCmd = cmd.ToLower(); foreach (var command in cmdList) { if (command.StartWith) { var test = $"{command.CommandText.ToLower().TrimEnd()} "; if (testCmd.StartsWith(test)) // Check with a space at the end. { return(RunCommand(command, cmd, config)); } } if (command.CommandText.ToLower() == testCmd) { return(RunCommand(command, cmd, config)); } } if (!string.IsNullOrEmpty(Warning)) { Console.WriteLine(Warning); } return(false); }
/// <summary> /// A asynchronous Run method for an REPL /// </summary> /// <param name="configuration">Prompt Configuration, null for using default settings</param> /// <param name="token">Cancellation Token, allows the task to exit nicely</param> /// <returns></returns> public static async Task RunAsync(IPromptConfiguration configuration = null, CancellationToken token = default) { var prompt = new Prompt(configuration); var cmd = string.Empty; while (!string.Equals(cmd, "exit", StringComparison.OrdinalIgnoreCase)) { var promptText = $"{prompt.Configuration.GetOption("PromptPreFix")}{prompt.CurrentFolder}{prompt.Configuration.GetOption("PromptPostFix")}"; // ReadLine is not await able, hence running as a Task.Run. Improve foreign project to // include ReadLine.ReadAsync( with CancellationToken) await Task.Run(() => cmd = ReadLine.Read(promptText), token); try { prompt.Run(cmd); } catch (Exception exception) { // Don't allow an exception to crash the application by a throw Console.WriteLine(exception); } } HistoryFile.Save(configuration); }
// Run the given command private bool RunCommand(PromptCommand pCmd, string commandText, IPromptConfiguration config) { var classInstance = GetCommandClassInstance(pCmd, config); if (classInstance == null) { return(false); // Something when wrong } if (pCmd.MethodInfo == null) { return(false); } var parameters = pCmd.MethodInfo.GetParameters(); if (parameters.Length == 0) { // Invoke with 'null' as the parameter array pCmd.MethodInfo.Invoke(classInstance, null); return(true); } // Remove the Command Text from the var parameterText = commandText.Remove(0, pCmd.CommandText.Length).Trim(); // Build a Parameter List to match the Parameters types of the Method // If the Last parameter is a string, the reminding text after the split can be considered part of that parameter // Split the text but all for escaped strings var parametersSplit = GetParameterString(parameters, parameterText); if (parametersSplit == null) { return(false); } var parameterList = new List <object>(); for (int i = 0; i < parameters.Length; i++) { var ob = Configuration.ParameterConvert(parametersSplit[i], parameters[i].ParameterType); if (ob == null) { Warning = "Failed parsing command, incorrect parameter type"; return(false); } parameterList.Add(ob); } pCmd.MethodInfo.Invoke(classInstance, parameterList.ToArray()); return(true); }
/// <summary> /// Saves Command Text History /// </summary> public static void Save(IPromptConfiguration config) { var historyFile = config.GetOption("HistoryFile"); if (string.IsNullOrEmpty(historyFile)) { return; } var history = ReadLine.GetHistory(); history = history.Distinct().ToList(); // Remove duplicates File.WriteAllLines(historyFile, history); }
/// <summary> /// Load Command Text History /// </summary> public static void Load(IPromptConfiguration config) { var historyFile = config.GetOption("HistoryFile"); if (string.IsNullOrEmpty(historyFile)) { return; } ReadLine.HistoryEnabled = true; if (!File.Exists(historyFile)) { return; } var history = File.ReadAllLines(historyFile); ReadLine.AddHistory(history); }
public Prompt(IPromptConfiguration configuration) { try { // If Configuration is null, use default settings Configuration = configuration ?? new PromptConfiguration(); ReadLine.HistoryEnabled = string.Equals(Configuration.GetOption("HistoryEnabled"), true.ToString()); BuildCommands.ScanForPrompt(this); HistoryFile.Load(configuration); } catch (Exception e) { // Don't allow an exception to crash the application by a throw // Show the error so that an developer can fix the problem. Console.WriteLine(e); } }
// Get the Class Instance for the command that is to be run private object GetCommandClassInstance(PromptCommand pCmd, IPromptConfiguration config) { // If this class instance exists in the configuration store then return it var classInstance = StoreCommandPromptClasses.FirstOrDefault(promptClass => promptClass.GetType() == pCmd.ClassType); if (classInstance != null) { // Great Work Class Instance Already created return(classInstance); } // We only Deal with the first Constructor (Restriction on current design) var constructorInfo = pCmd.ClassType.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).FirstOrDefault(); if (constructorInfo == null) { Console.WriteLine($"Cannot create of type {pCmd.ClassType} due to no public constructor"); return(null); // Cannot create class Whoops } // OtherWise, Create var constructorParameters = constructorInfo.GetParameters(); classInstance = constructorParameters.Length == 0 ? Activator.CreateInstance(pCmd.ClassType) // The order is important here, Lets hope Linq gets it right : Activator.CreateInstance(pCmd.ClassType, constructorInfo.GetParameters().Select(parameterInfo => InjectPromptClass(config, parameterInfo.ParameterType)).ToArray()); // If the Class has a Custom Attribute to keep this between commands, then store it in the configuration if (pCmd.KeepClassInstance) { StoreCommandPromptClasses.Add(classInstance); } return(classInstance); }
// Inject this Prompt class, use by internal commands like 'help' private object InjectPromptClass(IPromptConfiguration config, Type type) { return(type == typeof(Prompt) ? this : config.GetObjectOfType(type)); }