diff --git a/CHANGELIST.md b/CHANGELIST.md
index 3d99e490..4abeebe2 100644
--- a/CHANGELIST.md
+++ b/CHANGELIST.md
@@ -4,6 +4,7 @@
- Tweaks to how failure cases are reported
- Rename log zip on collision
- Update packages
+- Use CommandLine library for CLI executables
### 3.4.2 (2025-09-30)
diff --git a/MPF.CLI/MPF.CLI.csproj b/MPF.CLI/MPF.CLI.csproj
index 30a6b8d2..4bf6cdd8 100644
--- a/MPF.CLI/MPF.CLI.csproj
+++ b/MPF.CLI/MPF.CLI.csproj
@@ -43,6 +43,7 @@
+
diff --git a/MPF.CLI/Program.cs b/MPF.CLI/Program.cs
index 517b3b02..a585e3c5 100644
--- a/MPF.CLI/Program.cs
+++ b/MPF.CLI/Program.cs
@@ -203,12 +203,12 @@ namespace MPF.CLI
Console.WriteLine("MPF.CLI [options]");
Console.WriteLine();
Console.WriteLine("Standalone Options:");
- Console.WriteLine("-h, -?, --help Show this help text");
- Console.WriteLine("--version Print the program version");
- Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
- Console.WriteLine("-lm, --listmedia List supported media types");
- Console.WriteLine("-ls, --listsystems List supported system types");
- Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
+ Console.WriteLine("?, h, help Show this help text");
+ Console.WriteLine("version Print the program version");
+ Console.WriteLine("lc, listcodes List supported comment/content site codes");
+ Console.WriteLine("lm, listmedia List supported media types");
+ Console.WriteLine("ls, listsystems List supported system types");
+ Console.WriteLine("lp, listprograms List supported dumping program outputs");
Console.WriteLine("-i, --interactive Enable interactive mode");
Console.WriteLine();
diff --git a/MPF.Check/MPF.Check.csproj b/MPF.Check/MPF.Check.csproj
index d00e2df2..a598cc05 100644
--- a/MPF.Check/MPF.Check.csproj
+++ b/MPF.Check/MPF.Check.csproj
@@ -43,6 +43,7 @@
+
diff --git a/MPF.Check/Program.cs b/MPF.Check/Program.cs
index 60cb0159..7ad27416 100644
--- a/MPF.Check/Program.cs
+++ b/MPF.Check/Program.cs
@@ -147,12 +147,12 @@ namespace MPF.Check
Console.WriteLine("MPF.Check [options] ...");
Console.WriteLine();
Console.WriteLine("Standalone Options:");
- Console.WriteLine("-h, -?, --help Show this help text");
- Console.WriteLine("--version Print the program version");
- Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
- Console.WriteLine("-lm, --listmedia List supported media types");
- Console.WriteLine("-ls, --listsystems List supported system types");
- Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
+ Console.WriteLine("?, h, help Show this help text");
+ Console.WriteLine("version Print the program version");
+ Console.WriteLine("lc, listcodes List supported comment/content site codes");
+ Console.WriteLine("lm, listmedia List supported media types");
+ Console.WriteLine("ls, listsystems List supported system types");
+ Console.WriteLine("lp, listprograms List supported dumping program outputs");
Console.WriteLine("-i, --interactive Enable interactive mode");
Console.WriteLine();
diff --git a/MPF.Frontend/Features/ListCodesFeature.cs b/MPF.Frontend/Features/ListCodesFeature.cs
new file mode 100644
index 00000000..f04debad
--- /dev/null
+++ b/MPF.Frontend/Features/ListCodesFeature.cs
@@ -0,0 +1,38 @@
+using System;
+using SabreTools.CommandLine;
+
+namespace MPF.Frontend.Features
+{
+ public class ListCodesFeature : Feature
+ {
+ #region Feature Definition
+
+ public const string DisplayName = "listcodes";
+
+ private static readonly string[] _flags = ["lc", "listcodes"];
+
+ private const string _description = "List supported comment/content site codes";
+
+ #endregion
+
+ public ListCodesFeature()
+ : base(DisplayName, _flags, _description)
+ {
+ }
+
+ ///
+ public override bool Execute()
+ {
+ Console.WriteLine("Supported Site Codes:");
+ foreach (string mediaType in SabreTools.RedumpLib.Data.Extensions.ListMediaTypes())
+ {
+ Console.WriteLine(mediaType);
+ }
+
+ return true;
+ }
+
+ ///
+ public override bool VerifyInputs() => true;
+ }
+}
diff --git a/MPF.Frontend/Features/ListMediaTypesFeature.cs b/MPF.Frontend/Features/ListMediaTypesFeature.cs
new file mode 100644
index 00000000..aa8980c4
--- /dev/null
+++ b/MPF.Frontend/Features/ListMediaTypesFeature.cs
@@ -0,0 +1,38 @@
+using System;
+using SabreTools.CommandLine;
+
+namespace MPF.Frontend.Features
+{
+ public class ListMediaTypesFeature : Feature
+ {
+ #region Feature Definition
+
+ public const string DisplayName = "listmedia";
+
+ private static readonly string[] _flags = ["lm", "listmedia"];
+
+ private const string _description = "List supported media types";
+
+ #endregion
+
+ public ListMediaTypesFeature()
+ : base(DisplayName, _flags, _description)
+ {
+ }
+
+ ///
+ public override bool Execute()
+ {
+ Console.WriteLine("Supported Media Types:");
+ foreach (string mediaType in SabreTools.RedumpLib.Data.Extensions.ListMediaTypes())
+ {
+ Console.WriteLine(mediaType);
+ }
+
+ return true;
+ }
+
+ ///
+ public override bool VerifyInputs() => true;
+ }
+}
diff --git a/MPF.Frontend/Features/ListProgramsFeature.cs b/MPF.Frontend/Features/ListProgramsFeature.cs
new file mode 100644
index 00000000..de2d00b7
--- /dev/null
+++ b/MPF.Frontend/Features/ListProgramsFeature.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using SabreTools.CommandLine;
+
+namespace MPF.Frontend.Features
+{
+ public class ListProgramsFeature : Feature
+ {
+ #region Feature Definition
+
+ public const string DisplayName = "listprograms";
+
+ private static readonly string[] _flags = ["lp", "listprograms"];
+
+ private const string _description = "List supported dumping program outputs";
+
+ #endregion
+
+ public ListProgramsFeature()
+ : base(DisplayName, _flags, _description)
+ {
+ }
+
+ ///
+ public override bool Execute()
+ {
+ Console.WriteLine("Supported Programs:");
+ foreach (string program in ListPrograms())
+ {
+ Console.WriteLine(program);
+ }
+
+ return true;
+ }
+
+ ///
+ public override bool VerifyInputs() => true;
+
+ ///
+ /// List all programs with their short usable names
+ ///
+ private static List ListPrograms()
+ {
+ var programs = new List();
+
+ foreach (var val in Enum.GetValues(typeof(InternalProgram)))
+ {
+ if (((InternalProgram)val!) == InternalProgram.NONE)
+ continue;
+
+ programs.Add($"{((InternalProgram?)val).ShortName()} - {((InternalProgram?)val).LongName()}");
+ }
+
+ return programs;
+ }
+ }
+}
diff --git a/MPF.Frontend/Features/ListSystemsFeature.cs b/MPF.Frontend/Features/ListSystemsFeature.cs
new file mode 100644
index 00000000..b2ae4d3b
--- /dev/null
+++ b/MPF.Frontend/Features/ListSystemsFeature.cs
@@ -0,0 +1,38 @@
+using System;
+using SabreTools.CommandLine;
+
+namespace MPF.Frontend.Features
+{
+ public class ListSystemsFeature : Feature
+ {
+ #region Feature Definition
+
+ public const string DisplayName = "listsystems";
+
+ private static readonly string[] _flags = ["ls", "listsystems"];
+
+ private const string _description = "List supported system types";
+
+ #endregion
+
+ public ListSystemsFeature()
+ : base(DisplayName, _flags, _description)
+ {
+ }
+
+ ///
+ public override bool Execute()
+ {
+ Console.WriteLine("Supported Systems:");
+ foreach (string system in SabreTools.RedumpLib.Data.Extensions.ListSystems())
+ {
+ Console.WriteLine(system);
+ }
+
+ return true;
+ }
+
+ ///
+ public override bool VerifyInputs() => true;
+ }
+}
diff --git a/MPF.Frontend/Features/VersionFeature.cs b/MPF.Frontend/Features/VersionFeature.cs
new file mode 100644
index 00000000..d26c5389
--- /dev/null
+++ b/MPF.Frontend/Features/VersionFeature.cs
@@ -0,0 +1,34 @@
+using System;
+using MPF.Frontend.Tools;
+using SabreTools.CommandLine;
+
+namespace MPF.Frontend.Features
+{
+ public class VersionFeature : Feature
+ {
+ #region Feature Definition
+
+ public const string DisplayName = "version";
+
+ private static readonly string[] _flags = ["version"];
+
+ private const string _description = "Display the program version";
+
+ #endregion
+
+ public VersionFeature()
+ : base(DisplayName, _flags, _description)
+ {
+ }
+
+ ///
+ public override bool Execute()
+ {
+ Console.WriteLine(FrontendTool.GetCurrentVersion() ?? "Unknown version");
+ return true;
+ }
+
+ ///
+ public override bool VerifyInputs() => true;
+ }
+}
diff --git a/MPF.Frontend/MPF.Frontend.csproj b/MPF.Frontend/MPF.Frontend.csproj
index 1d5f315c..2ff77422 100644
--- a/MPF.Frontend/MPF.Frontend.csproj
+++ b/MPF.Frontend/MPF.Frontend.csproj
@@ -37,6 +37,7 @@
+
diff --git a/MPF.Frontend/Tools/OptionsLoader.cs b/MPF.Frontend/Tools/OptionsLoader.cs
index 65c4f12b..c21a7d40 100644
--- a/MPF.Frontend/Tools/OptionsLoader.cs
+++ b/MPF.Frontend/Tools/OptionsLoader.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection;
+using MPF.Frontend.Features;
using Newtonsoft.Json;
using SabreTools.RedumpLib.Data;
@@ -39,56 +40,21 @@ namespace MPF.Frontend.Tools
public static bool? ProcessStandaloneArguments(string[] args)
{
// Help options
- if (args.Length == 0 || args[0] == "-h" || args[0] == "-?" || args[0] == "--help")
+ if (args.Length == 0 || args[0] == "?" || args[0] == "h" || args[0] == "help")
return null;
- if (args[0] == "--version")
- {
- Console.WriteLine(FrontendTool.GetCurrentVersion() ?? "Unknown version");
- return true;
- }
+ if (args[0] == "version")
+ return new VersionFeature().Execute();
// List options
- if (args[0] == "-lc" || args[0] == "--listcodes")
- {
- Console.WriteLine("Supported Site Codes:");
- foreach (string siteCode in Extensions.ListSiteCodes())
- {
- Console.WriteLine(siteCode);
- }
-
- return true;
- }
- else if (args[0] == "-lm" || args[0] == "--listmedia")
- {
- Console.WriteLine("Supported Media Types:");
- foreach (string mediaType in Extensions.ListMediaTypes())
- {
- Console.WriteLine(mediaType);
- }
-
- return true;
- }
- else if (args[0] == "-lp" || args[0] == "--listprograms")
- {
- Console.WriteLine("Supported Programs:");
- foreach (string program in ListPrograms())
- {
- Console.WriteLine(program);
- }
-
- return true;
- }
- else if (args[0] == "-ls" || args[0] == "--listsystems")
- {
- Console.WriteLine("Supported Systems:");
- foreach (string system in Extensions.ListSystems())
- {
- Console.WriteLine(system);
- }
-
- return true;
- }
+ if (args[0] == "lc" || args[0] == "listcodes")
+ return new ListCodesFeature().Execute();
+ else if (args[0] == "lm" || args[0] == "listmedia")
+ return new ListMediaTypesFeature().Execute();
+ else if (args[0] == "lp" || args[0] == "listprograms")
+ return new ListProgramsFeature().Execute();
+ else if (args[0] == "ls" || args[0] == "listsystems")
+ return new ListSystemsFeature().Execute();
return false;
}
@@ -262,24 +228,6 @@ namespace MPF.Frontend.Tools
};
}
- ///
- /// List all programs with their short usable names
- ///
- private static List ListPrograms()
- {
- var programs = new List();
-
- foreach (var val in Enum.GetValues(typeof(InternalProgram)))
- {
- if (((InternalProgram)val!) == InternalProgram.NONE)
- continue;
-
- programs.Add($"{((InternalProgram?)val).ShortName()} - {((InternalProgram?)val).LongName()}");
- }
-
- return programs;
- }
-
#endregion
#region Configuration