Пример #1
0
        internal OutputWriter(SearchCommand command, string originalCommand)
        {
            regularForeGround = Console.ForegroundColor; //using current
            hasOutputPath     = !string.IsNullOrEmpty(command.FileOutputPath);
            writeOutputFile   = command.OutputHtml || hasOutputPath;
            this.command      = command;

            if (!writeOutputFile)
            {
                return;
            }

            terms = command.Terms;

            if (command.OutputHtml)
            {
                var context = BrowsingContext.New(Configuration.Default);
                document = context.OpenNewAsync().Result;

                var style = document.CreateElement("style");
                style.TextContent = "pre > em { background-color: yellow }";
                document.Head.Append(style);

                output = document.CreateElement("pre");
                document.Body.Append(output);
            }
            else
            {
                textOut = new StringWriter();
            }

            WriteLine(originalCommand);
            WriteLine();
        }
Пример #2
0
        private static async Task Search(SearchCommand command, string originalCommand,
                                         Func <Youtube, IAsyncEnumerable <VideoSearchResult> > getResultsAsync)
        {
            var terms = command.Terms;

            if (!terms.Any())
            {
                Console.WriteLine("None of the terms contain anything but whitespace. I refuse to work like this!");
                return;
            }

            //inspired by https://johnthiriet.com/cancel-asynchronous-operation-in-csharp/
            using (var search = new CancellationTokenSource())
            {
                var searching = true;

                var cancel = Task.Run(async() =>  //start in background, don't wait for completion
                {
                    Console.WriteLine("Press any key to cancel");
                    Console.WriteLine();

                    /* wait for key or search to finish, non-blockingly; but only as long as to not cause perceivable lag
                     *  inspired by https://stackoverflow.com/a/5620647 and https://stackoverflow.com/a/23628232 */
                    while (searching && !Console.KeyAvailable)
                    {
                        await Task.Delay(200, search.Token);
                    }

                    if (Console.KeyAvailable)
                    {
                        Console.ReadKey(true);                       //consume cancel key without displaying it
                    }
                    if (searching)
                    {
                        search.Cancel();
                    }
                });

                var youtube = new Youtube(new JsonFileDataStore(GetCachePath()));
                var output  = new OutputWriter(command, originalCommand);

                try
                {
                    /* passing token into search implementations for them to react to cancellation,
                     *  see https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8#a-tour-through-async-enumerables*/
                    await foreach (var result in getResultsAsync(youtube).WithCancellation(search.Token))
                    {
                        output.DisplayVideoResult(result);
                    }
                }
                catch (OperationCanceledException) { Console.WriteLine("The search was cancelled."); }

                output.WriteOutputFile(() => GetFileStoragePath("out"));
                searching = false; //to complete the cancel task
                await cancel;      //just to rethrow possible exceptions
            }
        }