public static async Task Main(string[] args) { var options = new DocoptNet.Docopt().Apply(Usage, args, version: "File system sorter sample app 1.0", exit: true); var inbox = options["<directory>"].ToString(); var outbox = options["--output"].ToString(); var errorBox = options["--failures"]?.ToString() ?? Path.Combine(options["<directory>"].ToString(), "failures"); EnsureDirectoryExists(inbox); EnsureDirectoryExists(outbox); EnsureDirectoryExists(errorBox); var cancellation = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => { Console.WriteLine("Cancelling processing..."); cancellation.Cancel(); }; var fileSorter = new FileSorter(outbox, errorBox); // Creates an EventingDocumentSource wrapping a FileSystemWatcher emitting // a new document into the pipeline whenever a document is created in the // inbox path. var filesystem = FileSystem.WatchForChanges(inbox, cancellation.Token); var pipeline = await WaivesApi.CreatePipelineAsync(new WaivesOptions { ClientId = "clientId", ClientSecret = "clientSecret" }, cancellation.Token); pipeline.WithDocumentsFrom(filesystem) .ClassifyWith(options["<classifier>"].ToString()) .Then(d => fileSorter.MoveDocument(d)) .OnDocumentError(e => fileSorter.HandleFailure(e)) .OnPipelineCompleted(() => Console.WriteLine("Processing completed, press any key to exit.")); try { await pipeline.RunAsync(cancellation.Token); } catch (PipelineException ex) { Console.WriteLine(ex); } }
/// <summary> /// Runs a command with the given console context. /// </summary> /// <param name="command">The command (including raw arguments) to parse and run.</param> /// <param name="console">The <see cref="ConsoleContext"/> to run the command in.</param> /// <returns>Whether the command was actually found.</returns> public bool RunCommand(string command, ConsoleContext console) { //First we need to parse the command string into something we can actually use as a query. var query = ParseCommand(command); //If query is null, don't try to run a command. There was no command. if (query == null) { return(false); } //If we get to this stage, the query is OK. Let's find a local command. var local = _localCommands.FirstOrDefault(x => x.Name == query.Name); //If this is null we'll send it off to the server. Well, I haven't implemented the server yet so we'll just return false. if (local == null) { if (!_server.Connected) { return(false); } using (var memstr = new MemoryStream()) { using (var writer = new BinaryWriter(memstr, Encoding.UTF8)) { writer.Write(query.Name); writer.Write(query.ArgumentTokens.Length); foreach (var token in query.ArgumentTokens) { writer.Write(token); } writer.Flush(); ManualResetEvent commandDone = new ManualResetEvent(false); Action <ServerBroadcastType, BinaryReader> terminalOutput = (req, r) => { if (req != ServerBroadcastType.TerminalOutput) { return; } int count = r.ReadInt32(); byte[] data = r.ReadBytes(count); string str = Encoding.UTF8.GetString(data); console.Write(str); if (str.ToCharArray().Contains((char)0x02)) { commandDone.Set(); } }; _server.BroadcastReceived += terminalOutput; Stream remoteSlave = null; Thread t = null; _server.SendMessage(ServerMessageType.TRM_INVOKE, memstr.ToArray(), (res, reader) => { if (res != ServerResponseType.REQ_SUCCESS) { console.WriteLine("Unexpected, unknown error."); return; } int remoteSlaveId = reader.ReadInt32(); remoteSlave = _remoteStreams.Open(remoteSlaveId); t = new Thread(() => { while (true) { try { char input = (char)console.StandardInput.BaseStream.ReadByte(); remoteSlave.WriteByte((byte)input); } catch (TerminationRequestException) { remoteSlave.WriteByte(0x02); remoteSlave.WriteByte((byte)'\n'); } } }); t.Start(); }).Wait(); commandDone.WaitOne(); CommandSucceeded?.Invoke(query.Name); _server.BroadcastReceived -= terminalOutput; t.Abort(); remoteSlave.Close(); } } return(true); } else { //So we have a command query, a console context, and a command. //What do we need next? Well, we need our argument dictionary. //We can use Docopt.Net and the ITerminalCommand.Usages property to get that. //First let's create a Dictionary<string, object> to store our arguments. var argumentStore = new Dictionary <string, object>(); //Next, we retrieve the usage string from the command. //The engine creates usage strings during initialization. var usage = _usages[local.Name]; //Then we pass it off to Docopt. var docoptArgs = new DocoptNet.Docopt().Apply(usage, query.ArgumentTokens, true, local.Name, false, false); //Now we just CTRL+C and CTRL+V from the debug console. foreach (var arg in docoptArgs) { if (arg.Value != null) { argumentStore.Add(arg.Key, arg.Value.Value); } else { argumentStore.Add(arg.Key, null); } } //Now we run the command - check for errors! try { local.Run(console, argumentStore); CommandSucceeded?.Invoke(query.Name); } catch (TerminationRequestException) { console.WriteLine("Killed."); return(true); } return(true); } }