diff --git a/source/Helpers/SiteHelper.cs b/source/Helpers/SiteHelper.cs
index 64d2d104b50c76f94005d9cd8d230b54900ddfa8..a6a6d37acab89bac8fc909b280883b60e57efbbc 100644
--- a/source/Helpers/SiteHelper.cs
+++ b/source/Helpers/SiteHelper.cs
@@ -36,7 +36,7 @@ public static class SiteHelper
}
catch
{
- throw new FormatException($"Error reading app config {configFile}");
+ throw;
}
var site = new Site(options, siteSettings, frontMatterParser, logger, null);
@@ -97,22 +97,16 @@ public static class SiteHelper
ArgumentNullException.ThrowIfNull(options);
ArgumentNullException.ThrowIfNull(frontMatterParser);
- try
- {
- // Read the main configation
- var filePath = Path.Combine(options.Source, configFile);
- if (!File.Exists(filePath))
- {
- throw new FileNotFoundException($"The {configFile} file was not found in the specified source directory: {options.Source}");
- }
-
- var fileContent = File.ReadAllText(filePath);
- var siteSettings = frontMatterParser.ParseSiteSettings(fileContent) ?? throw new FormatException("Error reading app config");
- return siteSettings;
- }
- catch
+ // Read the main configation
+ var filePath = Path.Combine(options.Source, configFile);
+ if (!File.Exists(filePath))
{
- throw new FormatException("Error reading app config");
+ throw new FileNotFoundException($"The {configFile} file was not found in the specified source directory: {options.Source}");
}
+
+ var fileContent = File.ReadAllText(filePath);
+ var siteSettings = frontMatterParser.ParseSiteSettings(fileContent)
+ ?? throw new FormatException($"Error reading app config {configFile}");
+ return siteSettings;
}
}
diff --git a/source/Models/CommandLineOptions/BuildOptions.cs b/source/Models/CommandLineOptions/BuildOptions.cs
index fa14596d6e0e0c40f6d35c0800268dd226c4efe8..9c51c14001210d03efc7940f5cf4eda43ea74926 100644
--- a/source/Models/CommandLineOptions/BuildOptions.cs
+++ b/source/Models/CommandLineOptions/BuildOptions.cs
@@ -1,23 +1,16 @@
+using CommandLine;
+
namespace SuCoS.Models.CommandLineOptions;
///
/// Command line options for the build command.
///
+[Verb("build", HelpText = "Builds the site")]
public class BuildOptions : GenerateOptions
{
///
/// The path of the output files.
///
- public string Output { get; }
-
- ///
- /// Constructor
- ///
- ///
- ///
- public BuildOptions(string source, string output)
- {
- Source = source;
- Output = string.IsNullOrEmpty(output) ? Path.Combine(source, "public") : output;
- }
+ [Option('o', "output", Required = false, HelpText = "Output directory path")]
+ public required string Output { get; set; }
}
diff --git a/source/Models/CommandLineOptions/GenerateOptions.cs b/source/Models/CommandLineOptions/GenerateOptions.cs
index 612284367e8e35440385a18b8d3b3b5de36f9d8a..704c3acb25e88d45209ae0de4f437fbaed47cb34 100644
--- a/source/Models/CommandLineOptions/GenerateOptions.cs
+++ b/source/Models/CommandLineOptions/GenerateOptions.cs
@@ -1,3 +1,5 @@
+using CommandLine;
+
namespace SuCoS.Models.CommandLineOptions;
///
@@ -6,14 +8,22 @@ namespace SuCoS.Models.CommandLineOptions;
public class GenerateOptions : IGenerateOptions
{
///
- public string Source { get; init; } = ".";
+ [Option('v', "verbose", Required = false, HelpText = "How verbose it must be")]
+ public bool Verbose { get; init; }
+
+ ///
+ [Option('s', "source", Required = false, HelpText = "Source directory path")]
+ public required string Source { get; init; } = ".";
///
+ [Option('d', "draft", Required = false, HelpText = "Include draft content")]
public bool Draft { get; init; }
///
+ [Option('f', "future", Required = false, HelpText = "Include content with dates in the future")]
public bool Future { get; init; }
///
+ [Option('e', "expired", Required = false, HelpText = "Include content with ExpiredDate dates from the past")]
public bool Expired { get; init; }
}
diff --git a/source/Models/CommandLineOptions/IGenerateOptions.cs b/source/Models/CommandLineOptions/IGenerateOptions.cs
index 72a911465389312a9d9b9619c081cc0739444edf..6aa93e0e7abc7440d6558b9eafc51a4b0137eae0 100644
--- a/source/Models/CommandLineOptions/IGenerateOptions.cs
+++ b/source/Models/CommandLineOptions/IGenerateOptions.cs
@@ -5,6 +5,11 @@ namespace SuCoS.Models.CommandLineOptions;
///
public interface IGenerateOptions
{
+ ///
+ /// How verbose it must be.
+ ///
+ bool Verbose { get; }
+
///
/// The path of the source files.
///
diff --git a/source/Models/CommandLineOptions/ServeOptions.cs b/source/Models/CommandLineOptions/ServeOptions.cs
index 9e2b5c969726d7babb800b916303453a30410b92..a91c92aba184733e9d9b964c13668852a8f2d1be 100644
--- a/source/Models/CommandLineOptions/ServeOptions.cs
+++ b/source/Models/CommandLineOptions/ServeOptions.cs
@@ -1,8 +1,10 @@
+using CommandLine;
+
namespace SuCoS.Models.CommandLineOptions;
///
/// Command line options for the serve command.
///
-public class ServeOptions : GenerateOptions
-{
-}
+[Verb("serve", HelpText = "Starts the server")]
+public class ServeOptions : GenerateOptions;
+
diff --git a/source/Program.cs b/source/Program.cs
index 231a56f2e12eb59ed4f17807a2d37307173346d3..7464da1274231240dbe13d408f8e87df20d1fa2a 100644
--- a/source/Program.cs
+++ b/source/Program.cs
@@ -2,15 +2,18 @@
using Serilog.Events;
using SuCoS.Helpers;
using SuCoS.Models.CommandLineOptions;
-using System.CommandLine;
using System.Reflection;
+using CommandLine;
namespace SuCoS;
///
/// The main entry point of the program.
///
-public class Program
+///
+/// Constructor
+///
+public class Program(ILogger logger)
{
///
/// Basic logo of the program, for fun
@@ -25,7 +28,7 @@ public class Program
\/_____/\/___/ \/___/ \/___/ \/_____/
";
- private ILogger logger;
+ private ILogger Logger { get; set; } = logger;
private static readonly string[] aliases = ["--source", "-s"];
private static readonly string[] aliasesArray = ["--draft", "-d"];
private static readonly string[] aliasesArray0 = ["--future", "-f"];
@@ -38,19 +41,10 @@ public class Program
///
///
///
- public static int Main(string[] args)
+ public static async Task Main(string[] args)
{
- var logger = CreateLogger();
- var program = new Program(logger);
- return program.Run(args);
- }
-
- ///
- /// Constructor
- ///
- public Program(ILogger logger)
- {
- this.logger = logger;
+ var program = new Program(CreateLogger());
+ return await program.RunCommandLine(args);
}
///
@@ -58,81 +52,55 @@ public class Program
///
///
///
- public int Run(string[] args)
+ public async Task RunCommandLine(string[] args)
{
- // Print the logo of the program.
- OutputLogo();
- OutputWelcome();
-
- // Shared options between the commands
- var sourceOption = new Option(aliases, () => ".", "Source directory path");
- var draftOption = new Option(aliasesArray, "Include draft content");
- var futureOption = new Option(aliasesArray0, "Include content with dates in the future");
- var expiredOption = new Option(aliasesArray1, "Include content with ExpiredDate dates from the past");
- var verboseOption = new Option(aliasesArray2, "Verbose output");
-
- // BuildCommand setup
- var buildOutputOption = new Option(aliasesArray3, "Output directory path");
-
- Command buildCommandHandler = new("build", "Builds the site")
- {
- sourceOption,
- draftOption,
- buildOutputOption,
- futureOption,
- expiredOption,
- verboseOption
- };
- buildCommandHandler.SetHandler((source, output, draft, future, expired, verbose) =>
- {
- logger = CreateLogger(verbose);
-
- BuildOptions buildOptions = new(
- source: source,
- output: output)
+ return await CommandLine.Parser.Default.ParseArguments(args)
+ .WithParsed(options =>
{
- Draft = draft,
- Future = future,
- Expired = expired
- };
- _ = new BuildCommand(buildOptions, logger);
- },
- sourceOption, buildOutputOption, draftOption, futureOption, expiredOption, verboseOption);
-
- // ServerCommand setup
- Command serveCommandHandler = new("serve", "Starts the server")
- {
- sourceOption,
- draftOption,
- futureOption,
- expiredOption,
- verboseOption
- };
- serveCommandHandler.SetHandler(async (source, draft, future, expired, verbose) =>
- {
- logger = CreateLogger(verbose);
-
- ServeOptions serverOptions = new()
+ Logger = CreateLogger(options.Verbose);
+ })
+ .WithParsed(options =>
{
- Source = source,
- Draft = draft,
- Future = future,
- Expired = expired
- };
-
- var serveCommand = new ServeCommand(serverOptions, logger, new SourceFileWatcher());
- serveCommand.StartServer();
- await Task.Delay(-1).ConfigureAwait(false); // Wait forever.
- },
- sourceOption, draftOption, futureOption, expiredOption, verboseOption);
-
- RootCommand rootCommand = new("SuCoS commands")
- {
- buildCommandHandler,
- serveCommandHandler
- };
-
- return rootCommand.Invoke(args);
+ options.Output = string.IsNullOrEmpty(options.Output) ? Path.Combine(options.Source, "public") : options.Output;
+ })
+ .MapResult(
+ (BuildOptions options) =>
+ {
+ try
+ {
+ _ = new BuildCommand(options, Logger);
+ }
+ catch (Exception ex)
+ {
+ Logger.Error($"Build failed: {ex.Message}");
+ return Task.FromResult(1);
+ }
+ return Task.FromResult(0);
+ },
+ async (ServeOptions options) =>
+ {
+ try
+ {
+ var serveCommand = new ServeCommand(options, Logger, new SourceFileWatcher());
+ serveCommand.StartServer();
+ await Task.Delay(-1).ConfigureAwait(false); // Wait forever.
+ }
+ catch (Exception ex)
+ {
+ if (options.Verbose)
+ {
+ Logger.Error(ex, "Serving failed");
+ }
+ else
+ {
+ Logger.Error($"Serving failed: {ex.Message}");
+ }
+ return 1;
+ }
+ return 0;
+ }
+ , errs => Task.FromResult(1)
+ );
}
///
@@ -144,7 +112,8 @@ public class Program
{
return new LoggerConfiguration()
.MinimumLevel.Is(verbose ? LogEventLevel.Debug : LogEventLevel.Information)
- .WriteTo.Async(a => a.Console(formatProvider: System.Globalization.CultureInfo.CurrentCulture))
+ // .WriteTo.Async(a => a.Console(formatProvider: System.Globalization.CultureInfo.CurrentCulture))
+ .WriteTo.Console(formatProvider: System.Globalization.CultureInfo.CurrentCulture)
.CreateLogger();
}
@@ -157,7 +126,7 @@ public class Program
var assemblyName = assembly?.GetName();
var appName = assemblyName?.Name;
var appVersion = assemblyName?.Version;
- logger.Information("{name} v{version}", appName, appVersion);
+ Logger.Information("{name} v{version}", appName, appVersion);
}
///
@@ -165,6 +134,6 @@ public class Program
///
public void OutputLogo()
{
- logger.Information(helloWorld);
+ Logger.Information(helloWorld);
}
}
diff --git a/source/SuCoS.csproj b/source/SuCoS.csproj
index 6b90744bcc5a91596283b1e8d48499b954a93cab..bf151db29be23f6d19fc808da431a1e0aa70de40 100644
--- a/source/SuCoS.csproj
+++ b/source/SuCoS.csproj
@@ -13,6 +13,7 @@
+
@@ -22,7 +23,6 @@
-