feat: add self-written help menu

This allowed to make help menu more extensible
This commit is contained in:
cuqmbr 2022-08-21 19:00:26 +03:00
parent 0c410e6451
commit c88e7fb359
3 changed files with 62 additions and 23 deletions

View File

@ -87,7 +87,11 @@ public static class CliOptionsHandlers
} }
else else
{ {
Log.Warning("Options combination is unsupported."); Log.Warning("Options combination is unsupported: " +
"-i: {input}; -o {output}; -d {useDatabase}; " +
"-q: {sqlQuery}; -c: {concatFiles}; -v: {verbosityLevel}.",
inputFile!, outputFile!, useDatabase,
sqlQuery!, concatFiles!, isVerbose);
} }
} }
catch (Exception e) catch (Exception e)

View File

@ -17,7 +17,7 @@ public static class RuntimeStorage
{ {
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose() .MinimumLevel.Verbose()
.WriteTo.Console(IsVerbose ? LogEventLevel.Verbose : LogEventLevel.Fatal, .WriteTo.Console(IsVerbose ? LogEventLevel.Verbose : LogEventLevel.Warning,
outputTemplate: "{Message:lj}{NewLine}{Exception}") outputTemplate: "{Message:lj}{NewLine}{Exception}")
.WriteTo.File(Path.Join(LogsFolder, "log.txt"), .WriteTo.File(Path.Join(LogsFolder, "log.txt"),
restrictedToMinimumLevel: IsVerbose ? LogEventLevel.Verbose : LogEventLevel.Warning, restrictedToMinimumLevel: IsVerbose ? LogEventLevel.Verbose : LogEventLevel.Warning,

View File

@ -1,4 +1,7 @@
using System.CommandLine; using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Help;
using System.CommandLine.Parsing;
using System.Xml.Linq; using System.Xml.Linq;
using netxml2kml.Methods; using netxml2kml.Methods;
@ -12,11 +15,13 @@ class Program
var inputOption = new Option<FileInfo?>( var inputOption = new Option<FileInfo?>(
aliases: new[] {"-i", "--input"}, aliases: new[] {"-i", "--input"},
description: "Path to the file to be converted.") description: "Path to the file to be converted")
{ {
Arity = ArgumentArity.ZeroOrOne Arity = ArgumentArity.ZeroOrOne
}; };
inputOption.ArgumentHelpName = "file_path[.netxml]";
inputOption.AddValidator(result => inputOption.AddValidator(result =>
{ {
var inputFile = result.GetValueForOption(inputOption); var inputFile = result.GetValueForOption(inputOption);
@ -24,13 +29,13 @@ class Program
if (inputFile == null) if (inputFile == null)
{ {
result.ErrorMessage = result.ErrorMessage =
"Argument for input option is not specified."; "Argument for input option is not specified";
return; return;
} }
if (!inputFile.Exists) if (!inputFile.Exists)
{ {
result.ErrorMessage = "Input file doesn't exist."; result.ErrorMessage = "Input file doesn't exist";
return; return;
} }
}); });
@ -39,7 +44,7 @@ class Program
var outputOption = new Option<FileInfo?>( var outputOption = new Option<FileInfo?>(
aliases: new[] {"-o", "--output"}, aliases: new[] {"-o", "--output"},
description: "The name of the file to be created.", description: "Path to the file to be created",
parseArgument: result => parseArgument: result =>
{ {
// If output file with the same name already exists // If output file with the same name already exists
@ -82,6 +87,8 @@ class Program
Arity = ArgumentArity.ZeroOrOne Arity = ArgumentArity.ZeroOrOne
}; };
outputOption.ArgumentHelpName = "file_path[.kml]";
outputOption.AddValidator(result => outputOption.AddValidator(result =>
{ {
var outputFile = result.GetValueForOption(outputOption); var outputFile = result.GetValueForOption(outputOption);
@ -89,13 +96,13 @@ class Program
if (outputFile == null) if (outputFile == null)
{ {
result.ErrorMessage = result.ErrorMessage =
"Argument for output option is not specified."; "Argument for output option is not specified";
return; return;
} }
if (!Directory.Exists(outputFile.DirectoryName)) if (!Directory.Exists(outputFile.DirectoryName))
{ {
result.ErrorMessage = "Output directory doesn't exist."; result.ErrorMessage = "Output directory doesn't exist";
return; return;
} }
}); });
@ -104,11 +111,13 @@ class Program
var concatOption = new Option<IEnumerable<FileInfo>?>( var concatOption = new Option<IEnumerable<FileInfo>?>(
aliases: new[] {"-c", "--concat"}, aliases: new[] {"-c", "--concat"},
description: "Concatenate multiple kml files. ") description: "Concatenate multiple kml files")
{ {
Arity = ArgumentArity.OneOrMore, Arity = ArgumentArity.OneOrMore,
AllowMultipleArgumentsPerToken = true AllowMultipleArgumentsPerToken = true
}; };
concatOption.ArgumentHelpName = "file_path[.kml] file_path[.kml] ...";
concatOption.AddValidator(result => concatOption.AddValidator(result =>
{ {
@ -117,7 +126,7 @@ class Program
if (inputFiles == null) if (inputFiles == null)
{ {
result.ErrorMessage = result.ErrorMessage =
"Argument for concat option is not specified."; "Argument for concat option is not specified";
return; return;
} }
@ -128,7 +137,7 @@ class Program
if (!inputFile.Exists) if (!inputFile.Exists)
{ {
result.ErrorMessage = result.ErrorMessage =
$"File {inputFile.FullName} doesen't exist."; $"File {inputFile.FullName} doesen't exist";
return; return;
} }
} }
@ -138,7 +147,7 @@ class Program
XDocument.Load(fi.FullName).Root?.Name != "kml")) XDocument.Load(fi.FullName).Root?.Name != "kml"))
{ {
result.ErrorMessage = result.ErrorMessage =
"Some files passed to concat option have invalid content."; "Some files passed to concat option have invalid content";
return; return;
} }
}); });
@ -148,7 +157,7 @@ class Program
var databaseOption = new Option<bool>( var databaseOption = new Option<bool>(
aliases: new[] {"-d", "--use-database"}, aliases: new[] {"-d", "--use-database"},
description: description:
"Use database (save/retrieve data from database).") "Use database (save/retrieve data)")
{ {
Arity = ArgumentArity.ZeroOrOne Arity = ArgumentArity.ZeroOrOne
}; };
@ -157,23 +166,25 @@ class Program
var queryOption = new Option<string?>( var queryOption = new Option<string?>(
aliases: new[] {"-q", "--query"}, aliases: new[] {"-q", "--query"},
description: "Filter input/output using sql query.") description: "Filter input/output using sql query")
{ {
Arity = ArgumentArity.ZeroOrOne Arity = ArgumentArity.ZeroOrOne
}; };
queryOption.ArgumentHelpName = "\"sql_query\"";
/*----------------------Verbosity Option---------------------------*/ /*----------------------Verbosity Option---------------------------*/
var verbosityOption = new Option<bool>( var verboseOption = new Option<bool>(
aliases: new[] {"-v", "--verbosity"}, aliases: new[] {"-v", "--verbose"},
description: "Set console output verbosity level.") description: "Show verbose output")
{ {
Arity = ArgumentArity.ZeroOrOne Arity = ArgumentArity.ZeroOrOne
}; };
verbosityOption.AddValidator(result => verboseOption.AddValidator(result =>
{ {
RuntimeStorage.IsVerbose = result.GetValueForOption(verbosityOption); RuntimeStorage.IsVerbose = result.GetValueForOption(verboseOption);
}); });
RuntimeStorage.ConfigureLogger(); RuntimeStorage.ConfigureLogger();
@ -181,25 +192,49 @@ class Program
/*----------------------Root Command Setup-------------------------*/ /*----------------------Root Command Setup-------------------------*/
var rootCommand = var rootCommand =
new RootCommand("netxml2kml .netxml to .kml converter."); new RootCommand("netxml2kml .netxml to .kml CLI converter & tools");
rootCommand.AddOption(inputOption); rootCommand.AddOption(inputOption);
rootCommand.AddOption(outputOption); rootCommand.AddOption(outputOption);
rootCommand.AddOption(databaseOption); rootCommand.AddOption(databaseOption);
rootCommand.AddOption(queryOption); rootCommand.AddOption(queryOption);
rootCommand.AddOption(concatOption); rootCommand.AddOption(concatOption);
rootCommand.AddOption(verbosityOption); rootCommand.AddOption(verboseOption);
/*----------------------Handlers Setup-----------------------------*/ /*----------------------Handlers Setup-----------------------------*/
rootCommand.SetHandler(CliOptionsHandlers.UniversalHandler, rootCommand.SetHandler(CliOptionsHandlers.UniversalHandler,
inputOption, outputOption, databaseOption, queryOption, inputOption, outputOption, databaseOption, queryOption,
concatOption, verbosityOption); concatOption, verboseOption);
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
var rootCommandParser = new CommandLineBuilder(rootCommand)
.UseDefaults().UseHelp(ctx =>
{
ctx.HelpBuilder.CustomizeLayout(_ =>
HelpBuilder.Default
.GetLayout()
.Skip(HelpBuilder.Default.GetLayout().Count())
.Append(_ => Console.WriteLine(
"netxml2kml .netxml to .kml CLI converter & tools" +
"\n" +
"\nUsage:" +
"\n netxml2kml [options]" +
"\n" +
"\nOptions:" +
"\n -i, --input <file_path[.netxml]> Path to the file to be converted" +
"\n -o, --output <file_path[.kml]> Path to the file to be created" +
"\n -c, --concat <file_path[.kml] file_path[.kml] ...> Concatenate multiple kml files" +
"\n -d, --use-database Use database (save/retrieve data)" +
"\n -q, --query <\"sql_query\"> Filter input/output using sql query" +
"\n -v, --verbose Show verbose output" +
"\n -h, --help Show help and usage information" +
"\n --version Show version information")));
}).Build();
try try
{ {
return await rootCommand.InvokeAsync(args); return await rootCommandParser.InvokeAsync(args);
} }
catch (Exception e) catch (Exception e)
{ {