From 5b94f0063ff94a5efe9b8cb43a17004db3324983 Mon Sep 17 00:00:00 2001 From: Ethan Hann Date: Sun, 28 Aug 2022 18:19:47 -0700 Subject: [PATCH] Add async console write methods --- src/InEngine.Commands/AlwaysFail.cs | 3 +- src/InEngine.Core/AbstractCommand.cs | 32 +++++- src/InEngine.Core/Commands/CommandsPlugin.cs | 3 + src/InEngine.Core/Commands/Echo.cs | 6 +- src/InEngine.Core/Commands/Sleep.cs | 13 ++- src/InEngine.Core/IO/IConsoleWrite.cs | 45 ++++++++ src/InEngine.Core/IO/IWrite.cs | 22 ---- src/InEngine.Core/IO/Write.cs | 115 +++++++++++-------- 8 files changed, 154 insertions(+), 85 deletions(-) create mode 100644 src/InEngine.Core/IO/IConsoleWrite.cs delete mode 100644 src/InEngine.Core/IO/IWrite.cs diff --git a/src/InEngine.Commands/AlwaysFail.cs b/src/InEngine.Commands/AlwaysFail.cs index b052d7f..0dd0931 100644 --- a/src/InEngine.Commands/AlwaysFail.cs +++ b/src/InEngine.Commands/AlwaysFail.cs @@ -1,4 +1,5 @@ -using System; +using System.Threading.Tasks; +using System; using InEngine.Core; using InEngine.Core.Exceptions; diff --git a/src/InEngine.Core/AbstractCommand.cs b/src/InEngine.Core/AbstractCommand.cs index a3ed4cb..ef462ef 100644 --- a/src/InEngine.Core/AbstractCommand.cs +++ b/src/InEngine.Core/AbstractCommand.cs @@ -44,7 +44,11 @@ public virtual void Run() { } - public virtual async Task RunAsync() => await Task.Run(Run).ConfigureAwait(false); + public virtual async Task RunAsync() + { + Run(); + await Task.CompletedTask; + } public virtual async Task RunWithLifeCycle() { @@ -110,18 +114,38 @@ public virtual async Task Execute(IJobExecutionContext context) #endregion - #region Console output + #region Console Output public IConsoleWrite Info(object val) => Write.Info(val); public IConsoleWrite Warning(object val) => Write.Warning(val); public IConsoleWrite Error(object val) => Write.Error(val); public IConsoleWrite Line(object val) => Write.Line(val); - public IConsoleWrite ColoredLine(object val, ConsoleColor consoleColor) => Write.ColoredLine(val, consoleColor); + public IConsoleWrite LineWithColor(object val, ConsoleColor consoleColor) => Write.LineWithColor(val, consoleColor); public IConsoleWrite InfoText(object val) => Write.InfoText(val); public IConsoleWrite WarningText(object val) => Write.WarningText(val); public IConsoleWrite ErrorText(object val) => Write.ErrorText(val); public IConsoleWrite Text(object val) => Write.Text(val); - public IConsoleWrite ColoredText(object val, ConsoleColor consoleColor) => Write.ColoredText(val, consoleColor); + + public IConsoleWrite TextWithColor(object val, ConsoleColor consoleColor, bool writeLine) => + Write.TextWithColor(val, consoleColor, writeLine); + + public async Task NewlineAsync(int count = 1) => await Write.NewlineAsync(count); + public async Task InfoAsync(object val) => await Write.InfoAsync(val); + public async Task WarningAsync(object val) => await Write.WarningAsync(val); + public async Task ErrorAsync(object val) => await Write.ErrorAsync(val); + public async Task LineAsync(object val) => await Write.LineAsync(val); + + public async Task LineWithColorAsync(object val, ConsoleColor consoleColor) => + await Write.LineWithColorAsync(val, consoleColor); + + public async Task InfoTextAsync(object val) => await Write.InfoTextAsync(val); + public async Task WarningTextAsync(object val) => await Write.WarningTextAsync(val); + public async Task ErrorTextAsync(object val) => await Write.ErrorTextAsync(val); + public async Task TextAsync(object val) => await Write.TextAsync(val); + + public async Task TextWithColorAsync(object val, ConsoleColor consoleColor, bool writeLine = false) => + await Write.TextWithColorAsync(val, consoleColor, writeLine); + public IConsoleWrite Newline(int count = 1) => Write.Newline(count); public string FlushBuffer() => Write.FlushBuffer(); public void ToFile(string path, string text, bool shouldAppend = false) => Write.ToFile(path, text, shouldAppend); diff --git a/src/InEngine.Core/Commands/CommandsPlugin.cs b/src/InEngine.Core/Commands/CommandsPlugin.cs index 21d77e4..defc9b8 100644 --- a/src/InEngine.Core/Commands/CommandsPlugin.cs +++ b/src/InEngine.Core/Commands/CommandsPlugin.cs @@ -9,4 +9,7 @@ public class CommandPlugin : AbstractPlugin [VerbOption("exec", HelpText = "Execute an external program.")] public Exec Exec { get; set; } + + [VerbOption("sleep", HelpText = "Sleep (in seconds)")] + public Sleep Sleep { get; set; } } \ No newline at end of file diff --git a/src/InEngine.Core/Commands/Echo.cs b/src/InEngine.Core/Commands/Echo.cs index 8f644ed..e80c73d 100644 --- a/src/InEngine.Core/Commands/Echo.cs +++ b/src/InEngine.Core/Commands/Echo.cs @@ -1,4 +1,6 @@ -using CommandLine; +using System; +using System.Threading.Tasks; +using CommandLine; namespace InEngine.Core.Commands; @@ -16,5 +18,5 @@ public Echo() [Option("text", HelpText = "The text to echo.")] public string VerbatimText { get; init; } - public override void Run() => Line(VerbatimText); + public override async Task RunAsync() => await LineAsync(VerbatimText); } \ No newline at end of file diff --git a/src/InEngine.Core/Commands/Sleep.cs b/src/InEngine.Core/Commands/Sleep.cs index 49334ba..7b12d69 100644 --- a/src/InEngine.Core/Commands/Sleep.cs +++ b/src/InEngine.Core/Commands/Sleep.cs @@ -3,14 +3,17 @@ namespace InEngine.Core.Commands; +using CommandLine; + public class Sleep : AbstractCommand { - public int MillisecondsTimeout { get; set; } + [Option("duration", HelpText = "The number of seconds to sleep.")] + public int DurationInSeconds { get; set; } - public override void Run() + public override async Task RunAsync() { - Warning("Going to sleep..."); - Thread.Sleep(MillisecondsTimeout); - Info("Done sleeping!"); + await WarningAsync("Going to sleep..."); + Thread.Sleep(DurationInSeconds * 1000); + await InfoAsync("Done sleeping!"); } } \ No newline at end of file diff --git a/src/InEngine.Core/IO/IConsoleWrite.cs b/src/InEngine.Core/IO/IConsoleWrite.cs new file mode 100644 index 0000000..80f2369 --- /dev/null +++ b/src/InEngine.Core/IO/IConsoleWrite.cs @@ -0,0 +1,45 @@ +using System; + +namespace InEngine.Core.IO; + +using System.Threading.Tasks; + +public interface IConsoleWrite +{ + #region Sync Methods + + IConsoleWrite Newline(int count = 1); + IConsoleWrite Info(object val); + IConsoleWrite Warning(object val); + IConsoleWrite Error(object val); + IConsoleWrite Line(object val); + IConsoleWrite LineWithColor(object val, ConsoleColor consoleColor); + + IConsoleWrite InfoText(object val); + IConsoleWrite WarningText(object val); + IConsoleWrite ErrorText(object val); + IConsoleWrite Text(object val); + IConsoleWrite TextWithColor(object val, ConsoleColor consoleColor, bool writeLine = false); + + #endregion + + #region Async Methods + + Task NewlineAsync(int count = 1); + Task InfoAsync(object val); + Task WarningAsync(object val); + Task ErrorAsync(object val); + Task LineAsync(object val); + Task LineWithColorAsync(object val, ConsoleColor consoleColor); + + Task InfoTextAsync(object val); + Task WarningTextAsync(object val); + Task ErrorTextAsync(object val); + Task TextAsync(object val); + Task TextWithColorAsync(object val, ConsoleColor consoleColor, bool writeLine = false); + + #endregion + + string FlushBuffer(); + void ToFile(string path, string text, bool shouldAppend = false); +} \ No newline at end of file diff --git a/src/InEngine.Core/IO/IWrite.cs b/src/InEngine.Core/IO/IWrite.cs deleted file mode 100644 index 8155666..0000000 --- a/src/InEngine.Core/IO/IWrite.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace InEngine.Core.IO; - -public interface IConsoleWrite -{ - IConsoleWrite Newline(int count = 1); - IConsoleWrite Info(object val); - IConsoleWrite Warning(object val); - IConsoleWrite Error(object val); - IConsoleWrite Line(object val); - IConsoleWrite ColoredLine(object val, ConsoleColor consoleColor); - - IConsoleWrite InfoText(object val); - IConsoleWrite WarningText(object val); - IConsoleWrite ErrorText(object val); - IConsoleWrite Text(object val); - IConsoleWrite ColoredText(object val, ConsoleColor consoleColor); - - string FlushBuffer(); - void ToFile(string path, string text, bool shouldAppend = false); -} \ No newline at end of file diff --git a/src/InEngine.Core/IO/Write.cs b/src/InEngine.Core/IO/Write.cs index 5ddaea4..8622c9e 100644 --- a/src/InEngine.Core/IO/Write.cs +++ b/src/InEngine.Core/IO/Write.cs @@ -2,29 +2,29 @@ using System.Collections.Generic; using System.IO; using System.Threading; +using System.Threading.Tasks; namespace InEngine.Core.IO; public class Write : IConsoleWrite { - static readonly Mutex consoleOutputLock = new Mutex(); - static readonly Mutex fileOutputLock = new Mutex(); + private static readonly Mutex ConsoleOutputLock = new(); + public static readonly Mutex FileOutputLock = new(); public ConsoleColor InfoColor { get; set; } = ConsoleColor.Green; public ConsoleColor WarningColor { get; set; } = ConsoleColor.Yellow; public ConsoleColor ErrorColor { get; set; } = ConsoleColor.Red; public ConsoleColor LineColor { get; set; } = ConsoleColor.White; - public List Buffer { get; set; } = new List(); + public List Buffer { get; set; } = new(); public bool IsBufferEnabled { get; set; } public Write() : this(true) { } - public Write(bool isBufferEnabled) - { - IsBufferEnabled = isBufferEnabled; - } + public Write(bool isBufferEnabled) => IsBufferEnabled = isBufferEnabled; + + #region Sync Methods public IConsoleWrite Newline(int count = 1) { @@ -33,77 +33,90 @@ public IConsoleWrite Newline(int count = 1) return this; } - public IConsoleWrite Info(object val) - { - return ColoredLine(val, InfoColor); - } + public IConsoleWrite Info(object val) => LineWithColor(val, InfoColor); + public IConsoleWrite Error(object val) => LineWithColor(val, ErrorColor); + public IConsoleWrite Warning(object val) => LineWithColor(val, WarningColor); + public IConsoleWrite Line(object val) => LineWithColor(val, LineColor); - public IConsoleWrite Error(object val) + public IConsoleWrite LineWithColor(object val, ConsoleColor consoleColor) { - return ColoredLine(val, ErrorColor); + TextWithColor(val, consoleColor, true); + return this; } - public IConsoleWrite Warning(object val) - { - return ColoredLine(val, WarningColor); - } + public IConsoleWrite InfoText(object val) => TextWithColor(val, InfoColor); + public IConsoleWrite ErrorText(object val) => TextWithColor(val, ErrorColor); + public IConsoleWrite WarningText(object val) => TextWithColor(val, WarningColor); + public IConsoleWrite Text(object val) => TextWithColor(val, LineColor); - public IConsoleWrite Line(object val) + public IConsoleWrite TextWithColor(object val, ConsoleColor consoleColor, bool writeLine = false) { - return ColoredLine(val, LineColor); - } + var text = BeginWriting(val, consoleColor); - public IConsoleWrite ColoredLine(object val, ConsoleColor consoleColor) - { - WriteColoredLineOrText(val, consoleColor, true); + if (writeLine) + Console.WriteLine(val); + else + Console.Write(val); + + EndWriting(text, writeLine); return this; } - public IConsoleWrite InfoText(object val) - { - return ColoredText(val, InfoColor); - } + #endregion - public IConsoleWrite ErrorText(object val) - { - return ColoredText(val, ErrorColor); - } + #region Async Methods - public IConsoleWrite WarningText(object val) + public async Task NewlineAsync(int count = 1) { - return ColoredText(val, WarningColor); + for (var i = 0; i < count; i++) + await Console.Out.WriteLineAsync(); } - public IConsoleWrite Text(object val) + public async Task InfoAsync(object val) => await LineWithColorAsync(val, InfoColor); + public async Task ErrorAsync(object val) => await LineWithColorAsync(val, ErrorColor); + public async Task WarningAsync(object val) => await LineWithColorAsync(val, WarningColor); + public async Task LineAsync(object val) => await LineWithColorAsync(val, LineColor); + + public async Task LineWithColorAsync(object val, ConsoleColor consoleColor) => + await TextWithColorAsync(val, consoleColor, true); + + public async Task InfoTextAsync(object val) => await TextWithColorAsync(val, InfoColor); + public async Task ErrorTextAsync(object val) => await TextWithColorAsync(val, ErrorColor); + public async Task WarningTextAsync(object val) => await TextWithColorAsync(val, WarningColor); + public async Task TextAsync(object val) => await TextWithColorAsync(val, LineColor); + + public async Task TextWithColorAsync(object val, ConsoleColor consoleColor, bool writeLine = false) { - return ColoredText(val, LineColor); + var text = BeginWriting(val, consoleColor); + + if (writeLine) + await Console.Out.WriteLineAsync(text); + else + await Console.Out.WriteAsync(text); + + EndWriting(text, writeLine); } - public IConsoleWrite ColoredText(object val, ConsoleColor consoleColor) + #endregion + + protected string BeginWriting(object val, ConsoleColor consoleColor) { - WriteColoredLineOrText(val, consoleColor, false); - return this; + ConsoleOutputLock.WaitOne(); + Console.ForegroundColor = consoleColor; + return val?.ToString() ?? string.Empty; } - void WriteColoredLineOrText(object val, ConsoleColor consoleColor, bool writeLine) + protected void EndWriting(string text, bool writeLine) { - if (val == null) - val = String.Empty; - consoleOutputLock.WaitOne(); - Console.ForegroundColor = consoleColor; - if (writeLine) - Console.WriteLine(val); - else - Console.Write(val); Console.ResetColor(); if (IsBufferEnabled) { - Buffer.Add(val.ToString()); + Buffer.Add(text); if (writeLine) Buffer.Add(Environment.NewLine); } - consoleOutputLock.ReleaseMutex(); + ConsoleOutputLock.ReleaseMutex(); } public string FlushBuffer() @@ -115,12 +128,12 @@ public string FlushBuffer() public void ToFile(string path, string text, bool shouldAppend = false) { - fileOutputLock.WaitOne(); + FileOutputLock.WaitOne(); if (shouldAppend) File.AppendAllText(path, text); else File.WriteAllText(path, text); - fileOutputLock.ReleaseMutex(); + FileOutputLock.ReleaseMutex(); } } \ No newline at end of file