From 1aeeca1ca964b1d7bf1b1aad3a5a882c7c3ea567 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Sat, 29 Feb 2020 14:55:28 -0800 Subject: [PATCH] basic cli skeleton --- src/tye/CommandException.cs | 17 +++++++++ src/tye/ConsoleExtensions.cs | 67 ++++++++++++++++++++++++++++++++++ src/tye/Program.cs | 69 +++++++++++++++++++++++++++++++++--- src/tye/tye.csproj | 8 +++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/tye/CommandException.cs create mode 100644 src/tye/ConsoleExtensions.cs diff --git a/src/tye/CommandException.cs b/src/tye/CommandException.cs new file mode 100644 index 00000000..386912cf --- /dev/null +++ b/src/tye/CommandException.cs @@ -0,0 +1,17 @@ +using System; + +namespace Tye +{ + internal class CommandException : Exception + { + public CommandException(string message) + : base(message) + { + } + + public CommandException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/tye/ConsoleExtensions.cs b/src/tye/ConsoleExtensions.cs new file mode 100644 index 00000000..87336536 --- /dev/null +++ b/src/tye/ConsoleExtensions.cs @@ -0,0 +1,67 @@ +using System.Linq; + +namespace System.CommandLine +{ + internal static class ConsoleExtensions + { + private static bool? isConsoleRedirectionCheckSupported; + + private static bool IsConsoleRedirectionCheckSupported + { + get + { + if (isConsoleRedirectionCheckSupported == null) + { + try + { + var check = Console.IsOutputRedirected; + isConsoleRedirectionCheckSupported = true; + } + + catch (PlatformNotSupportedException) + { + isConsoleRedirectionCheckSupported = false; + } + } + + return isConsoleRedirectionCheckSupported.Value; + } + } + + public static void SetTerminalForegroundColor(this IConsole console, ConsoleColor color) + { + if (console.GetType().GetInterfaces().Any(i => i.Name == "ITerminal")) + { + ((dynamic)console).ForegroundColor = color; + } + + if (IsConsoleRedirectionCheckSupported && + !Console.IsOutputRedirected) + { + Console.ForegroundColor = color; + } + else if (IsConsoleRedirectionCheckSupported) + { + Console.ForegroundColor = color; + } + } + + public static void ResetTerminalForegroundColor(this IConsole console) + { + if (console.GetType().GetInterfaces().Any(i => i.Name == "ITerminal")) + { + ((dynamic)console).ForegroundColor = ConsoleColor.Red; + } + + if (IsConsoleRedirectionCheckSupported && + !Console.IsOutputRedirected) + { + Console.ResetColor(); + } + else if (IsConsoleRedirectionCheckSupported) + { + Console.ResetColor(); + } + } + } +} diff --git a/src/tye/Program.cs b/src/tye/Program.cs index 6287d3c0..4bc473d9 100644 --- a/src/tye/Program.cs +++ b/src/tye/Program.cs @@ -1,12 +1,73 @@ using System; +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Help; +using System.CommandLine.Invocation; +using System.CommandLine.IO; +using System.CommandLine.Parsing; +using System.Threading.Tasks; -namespace tye +namespace Tye { - class Program + static partial class Program { - static void Main(string[] args) + public static async Task Main(string[] args) { - Console.WriteLine("Hello World!"); + var command = new RootCommand() + { + Description = "Developer tools and publishing for microservices.", + }; + + // Show commandline help unless a subcommand was used. + command.Handler = CommandHandler.Create(help => + { + help.Write(command); + return 1; + }); + + var builder = new CommandLineBuilder(command); + builder.UseHelp(); + builder.UseVersionOption(); + builder.UseDebugDirective(); + builder.UseParseErrorReporting(); + builder.ParseResponseFileAs(ResponseFileHandling.ParseArgsAsSpaceSeparated); + + builder.CancelOnProcessTermination(); + builder.UseExceptionHandler(HandleException); + + var parser = builder.Build(); + return await parser.InvokeAsync(args); + } + + private static void HandleException(Exception exception, InvocationContext context) + { + context.Console.ResetTerminalForegroundColor(); + context.Console.SetTerminalForegroundColor(ConsoleColor.Red); + + if (exception is OperationCanceledException) + { + context.Console.Error.WriteLine("Oh dear! Operation canceled."); + } + else if (exception is CommandException command) + { + context.Console.Error.WriteLine($"Drats! '{context.ParseResult.CommandResult.Command.Name}' failed:"); + context.Console.Error.WriteLine($"\t{command.Message}"); + + if (command.InnerException != null) + { + context.Console.Error.WriteLine(); + context.Console.Error.WriteLine(command.InnerException.ToString()); + } + } + else + { + context.Console.Error.WriteLine("An unhandled exception has occurred, how unseemly: "); + context.Console.Error.WriteLine(exception.ToString()); + } + + context.Console.ResetTerminalForegroundColor(); + + context.ResultCode = 1; } } } diff --git a/src/tye/tye.csproj b/src/tye/tye.csproj index d453e9a0..0182643a 100644 --- a/src/tye/tye.csproj +++ b/src/tye/tye.csproj @@ -3,6 +3,14 @@ Exe netcoreapp3.1 + Tye + tye + tye + true + + + +