예제 #1
0
        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;
            }
        }
예제 #2
0
 /// <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));
 }
예제 #3
0
        private void ParserThreadCallback()
        {
            while (!_tokenSource.Token.IsCancellationRequested)
            {
                //Check if the MRE has been set
                if (!_mre.WaitOne(100))
                {
                    continue;
                }

                if (!_queue.TryDequeue(out QueueData data))
                {
                    _mre.Reset();
                    continue;
                }

                //The vertical bar is a pipe character. inputA | inputB = run command B with the output of command A
                string[] inputs = data.Input.Split('|');

                if (inputs.Length > 1)
                {
                    //If we have a piped command, send it off to a new thread to be handled,
                    //As each command needs to be handled in order
                    Thread pipeThread = new Thread(() => PipeThreadCallback(inputs, data.Callback, data.Context));
                    pipeThread.Start();
                    _mre.Set();
                    continue;
                }

                string input = data.Input; //We don't lower the data because case sensitivity is an option for command matching

                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)
                {
                    data.Callback?.Invoke(InputResult.Unhandled, null);

                    //No command matches, so ignore this input
                    _mre.Set();
                    continue;
                }

                CommandExecutorData exeData = metadata.GetFirstOrDefaultExecutorData(input);

                RegexString trigger = exeData.ExecutorAttribute.CommandMatcher;
                input = trigger.RemoveMatchedString(input).TrimStart();

                AbstractParser parser = _registry.GetParser(_registry, input, null, metadata, exeData, data.Context, data.Callback);

                try
                {
                    parser.Start();
                }
                finally
                {
                    //Our job is done, so prepare for the next input
                    _mre.Set();
                }
            }

            _mre.Dispose();
        }