/// <summary> /// Determines if the input matches any registered scanners, and invokes the scanner callback if a match is found. /// This method will also invoke the <see cref="InputResultDelegate"/> callback if a scanner is found /// </summary> /// <param name="input"></param> /// <param name="ctx"></param> /// <param name="callback"></param> public bool ScanInput(string input, IContextObject ctx, InputResultDelegate callback) { ThrowIfDisposed(); if (_scanners.Count == 0) { return(false); } ScannerData scanner = _scanners.FirstOrDefault(s => s.Pattern.Matches(input)); if (scanner != null) { bool remove = false; object result = scanner.Callback.Invoke(ctx, input, new LightweightParser(ctx), ref remove); callback?.Invoke(InputResult.Scanner, result); if (remove) { _scanners.Remove(scanner); } return(true); } return(false); }
/// <summary> /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run /// </summary> /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param> /// <param name="input">The original input string</param> /// <param name="additionalArgs">Any additional arguments to be added to the end of the argument list</param> /// <param name="metadata">CommandMetadata containing information used to parse and execute</param> /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param> /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param> /// <param name="callback">Reference to a method used as a callback when processing completes</param> public Parser(CommandRegistry registry, string input, IEnumerable <object> additionalArgs, CommandMetadata metadata, CommandExecutorData exeData, IContextObject ctx, InputResultDelegate callback) : base(registry, input, additionalArgs, metadata, exeData, ctx, callback) { }
private void PipeThreadCallback(string[] inputs, InputResultDelegate callback, IContextObject ctx) { object output = null; for (int i = 0; i < inputs.Length; i++) { string input = $"{inputs[i]}".Trim(); CommandMetadata metadata; lock (_lock) { //Lock the metadata collection, and grab the first metadata that has a matching executor List <CommandMetadata> metadatas = _metadata.Where(m => m.GetFirstOrDefaultExecutorData(input) != null).ToList(); metadata = metadatas.FirstOrDefault(); } if (metadata == null) { //No command matches, so ignore this entire piped input callback.Invoke(InputResult.Unhandled, null); break; } CommandExecutorData exeData = metadata.GetFirstOrDefaultExecutorData(input); RegexString trigger = exeData.ExecutorAttribute.CommandMatcher; input = trigger.RemoveMatchedString(input); object[] arguments = null; if (output != null) { //If there's output from a previous command, append it to the arguments for this command arguments = new[] { output }; } AbstractParser parser; if (i == inputs.Length - 1) { //We only want the final parsing to invoke the parser callback parser = _registry.GetParser(_registry, input, arguments, metadata, exeData, ctx, callback); } else { parser = _registry.GetParser(_registry, input, arguments, metadata, exeData, ctx, null); } //Threads are joined for synchronous behaviour. Running each command concurrently (and thus potentially out of order) will not work here. Thread thread = parser.GetThread(); thread.Start(); thread.Join(); //Set output so that it's appended to the end of the next input output = parser.Output; } }
/// <summary> /// Returns an instance of the parser that is currently registered. /// </summary> /// <param name="registry">Registry to be used by the parser</param> /// <param name="input">String input provided to the parser</param> /// <param name="args">Additional arguments to be used by the parser</param> /// <param name="metadata">Metadata to be used by the parser</param> /// <param name="exeData">CommandExecutorData to be used by the parser</param> /// <param name="ctx">Context to be used by the parser</param> /// <param name="callback">Callback method to be invoked when the parser completes</param> public AbstractParser GetParser(CommandRegistry registry, string input, IEnumerable <object> args, CommandMetadata metadata, CommandExecutorData exeData, IContextObject ctx, InputResultDelegate callback) { ThrowIfDisposed(); return((AbstractParser)Activator.CreateInstance(_parser, registry, input, args, metadata, exeData, ctx, callback)); }
public static UiDialogHandle Show( string msg, string value = null, ButtonType buttonType = ButtonType.Ok, InputResultDelegate callback = null, string customOkName = null) { UiDialogHandle handle; { var builtin = UiManager.Instance.FindFromDialogRoot("InputBox"); if (builtin != null) { handle = UiManager.Instance.ShowModalTemplate(builtin.gameObject); } else { var msgBoxPrefab = Resources.Load("InputBox") as GameObject; handle = UiManager.Instance.ShowModalPrefab(msgBoxPrefab); } } if (callback != null) { handle.Hidden += (dlg, returnValue) => callback((string)returnValue); } var msgBox = (UiInputBox)handle.Dialog; msgBox.MessageText.text = msg; msgBox.ValueInput.text = value ?? ""; var b0 = msgBox.Buttons[0]; var b0Text = b0.transform.Find("Text").GetComponent <Text>(); var b1 = msgBox.Buttons[1]; var b1Text = b1.transform.Find("Text").GetComponent <Text>(); b1.gameObject.SetActive(buttonType != ButtonType.Ok); switch (buttonType) { case ButtonType.Ok: b0Text.text = customOkName ?? "Ok"; b0.onClick.AddListener(() => msgBox.OnButtonClick(true)); break; case ButtonType.OkCancel: b0Text.text = customOkName ?? "Ok"; b0.onClick.AddListener(() => msgBox.OnButtonClick(true)); b1Text.text = "Cancel"; b1.onClick.AddListener(() => msgBox.OnButtonClick(false)); break; } return(handle); }
/// <summary> /// Adds a command to the command queue, ready to be executed /// </summary> public void QueueInputHandling(string input, IContextObject ctx, InputResultDelegate callback) { ThrowIfDisposed(); if (!ScanInput(input, ctx, callback)) { _queue.Enqueue(new QueueData(input, callback, ctx)); //Set the MRE so that our parser thread knows there's data _mre.Set(); } }
public static UiDialogHandle Show( string msg, string value = null, ButtonType buttonType = ButtonType.Ok, InputResultDelegate callback = null, string customOkName = null) { UiDialogHandle handle; { var builtin = UiManager.Instance.FindFromDialogRoot("InputBox"); if (builtin != null) { handle = UiManager.Instance.ShowModalTemplate(builtin.gameObject); } else { var msgBoxPrefab = Resources.Load("InputBox") as GameObject; handle = UiManager.Instance.ShowModalPrefab(msgBoxPrefab); } } if (callback != null) handle.Hidden += (dlg, returnValue) => callback((string)returnValue); var msgBox = (UiInputBox)handle.Dialog; msgBox.MessageText.text = msg; msgBox.ValueInput.text = value ?? ""; var b0 = msgBox.Buttons[0]; var b0Text = b0.transform.Find("Text").GetComponent<Text>(); var b1 = msgBox.Buttons[1]; var b1Text = b1.transform.Find("Text").GetComponent<Text>(); b1.gameObject.SetActive(buttonType != ButtonType.Ok); switch (buttonType) { case ButtonType.Ok: b0Text.text = customOkName ?? "Ok"; b0.onClick.AddListener(() => msgBox.OnButtonClick(true)); break; case ButtonType.OkCancel: b0Text.text = customOkName ?? "Ok"; b0.onClick.AddListener(() => msgBox.OnButtonClick(true)); b1Text.text = "Cancel"; b1.onClick.AddListener(() => msgBox.OnButtonClick(false)); break; } return handle; }
/// <summary> /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run /// </summary> /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param> /// <param name="input">The original input string</param> /// <param name="additionalArgs">Enumerable of objects to be parsed</param> /// <param name="metadata">CommandMetadata containing information used to parse and execute</param> /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param> /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param> /// <param name="callback">Reference to a method to be invoked when parsing completes</param> public AbstractParser(CommandRegistry registry, string input, IEnumerable <object> additionalArgs, CommandMetadata metadata, CommandExecutorData exeData, IContextObject ctx, InputResultDelegate callback) { Registry = registry; Input = input; AdditionalArgs = additionalArgs; Metadata = metadata; ExecutorData = exeData; Context = ctx; Callback = callback; }
internal QueueData(string input, InputResultDelegate callback, IContextObject ctx) { Input = input; Callback = callback; Context = ctx; }
/// <summary> /// Queues an input for handling /// </summary> /// <param name="input">The string from which command data will be parsed</param> /// <param name="ctx">A context object which is passed to the command method, and is used to convert data types</param> /// <param name="callback">A callback method for when the command completes</param> /// <returns></returns> public void HandleInput(string input, IContextObject ctx, InputResultDelegate callback) { ThrowIfDisposed(); _queue.QueueInputHandling(input, ctx, callback); }