From 9a0bc868f849d30e2ae4473d74e0bca05fcc9e27 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 7 Oct 2025 16:40:30 -0400 Subject: [PATCH] More consistency in commandline programs --- CHANGELIST.md | 1 + MPF.CLI/Features/BaseFeature.cs | 59 +++++++++++++++++++++--- MPF.CLI/Program.cs | 72 +++++++---------------------- MPF.Check/Features/BaseFeature.cs | 47 ++++++++++++++++++- MPF.Check/Program.cs | 76 ++++++++----------------------- 5 files changed, 135 insertions(+), 120 deletions(-) diff --git a/CHANGELIST.md b/CHANGELIST.md index f6b29fcc..197ab7c9 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -20,6 +20,7 @@ - Fix minor typo in verify inputs check - Allow but do not require config for Check - Update packages +- More consistency in commandline programs ### 3.4.2 (2025-09-30) diff --git a/MPF.CLI/Features/BaseFeature.cs b/MPF.CLI/Features/BaseFeature.cs index 001368c1..41b6b3c5 100644 --- a/MPF.CLI/Features/BaseFeature.cs +++ b/MPF.CLI/Features/BaseFeature.cs @@ -117,7 +117,7 @@ namespace MPF.CLI.Features case InternalProgram.Aaru: if (!File.Exists(Options.AaruPath)) { - Program.DisplayHelp("A path needs to be supplied in config.json for Aaru, exiting..."); + Console.Error.WriteLine("A path needs to be supplied in config.json for Aaru, exiting..."); return false; } break; @@ -125,7 +125,7 @@ namespace MPF.CLI.Features case InternalProgram.DiscImageCreator: if (!File.Exists(Options.DiscImageCreatorPath)) { - Program.DisplayHelp("A path needs to be supplied in config.json for DIC, exiting..."); + Console.Error.WriteLine("A path needs to be supplied in config.json for DIC, exiting..."); return false; } break; @@ -133,27 +133,27 @@ namespace MPF.CLI.Features case InternalProgram.Redumper: if (!File.Exists(Options.RedumperPath)) { - Program.DisplayHelp("A path needs to be supplied in config.json for Redumper, exiting..."); + Console.Error.WriteLine("A path needs to be supplied in config.json for Redumper, exiting..."); return false; } break; default: - Program.DisplayHelp($"{Options.InternalProgram} is not a supported dumping program, exiting..."); + Console.Error.WriteLine($"{Options.InternalProgram} is not a supported dumping program, exiting..."); break; } // Ensure we have the values we need if (CustomParams == null && (DevicePath == null || FilePath == null)) { - Program.DisplayHelp("Both a device path and file path need to be supplied, exiting..."); + Console.Error.WriteLine("Both a device path and file path need to be supplied, exiting..."); return false; } if (Options.InternalProgram == InternalProgram.DiscImageCreator && CustomParams == null && (MediaType == null || MediaType == SabreTools.RedumpLib.Data.MediaType.NONE)) { - Program.DisplayHelp("Media type is required for DiscImageCreator, exiting..."); + Console.Error.WriteLine("Media type is required for DiscImageCreator, exiting..."); return false; } @@ -178,7 +178,7 @@ namespace MPF.CLI.Features string? paramStr = CustomParams ?? env.GetFullParameters(MediaType, speed); if (string.IsNullOrEmpty(paramStr)) { - Program.DisplayHelp("No valid environment could be created, exiting..."); + Console.Error.WriteLine("No valid environment could be created, exiting..."); return false; } @@ -194,6 +194,7 @@ namespace MPF.CLI.Features // If it was not a dumping command if (!env.IsDumpingCommand()) { + Console.Error.WriteLine(); Console.WriteLine("Execution not recognized as dumping command, skipping processing..."); return true; } @@ -218,5 +219,49 @@ namespace MPF.CLI.Features return true; } + + /// + /// Display help for MPF.CLI + /// + /// Error string to prefix the help text with + public static void DisplayHelp() + { + Console.WriteLine("Usage:"); + 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("i, interactive Enable interactive mode"); + Console.WriteLine(); + + Console.WriteLine("CLI Options:"); + Console.WriteLine("-u, --use Override configured dumping program name"); + Console.WriteLine("-t, --mediatype Set media type for dumping (Required for DIC)"); + Console.WriteLine("-d, --device Physical drive path (Required if no custom parameters set)"); + Console.WriteLine("-m, --mounted Mounted filesystem path for additional checks"); + Console.WriteLine("-f, --file \"\" Output file path (Required if no custom parameters set)"); + Console.WriteLine("-s, --speed Override default dumping speed"); + Console.WriteLine("-c, --custom \"\" Custom parameters to use"); + Console.WriteLine(); + + Console.WriteLine("Dumping program paths and other settings can be found in the config.json file"); + Console.WriteLine("generated next to the program by default. Ensure that all settings are to user"); + Console.WriteLine("preference before running MPF.CLI."); + Console.WriteLine(); + + Console.WriteLine("Custom dumping parameters, if used, will fully replace the default parameters."); + Console.WriteLine("All dumping parameters need to be supplied if doing this."); + Console.WriteLine("Otherwise, both a drive path and output file path are required."); + Console.WriteLine(); + + Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block"); + Console.WriteLine("device dumping, usually Linux and macOS."); + Console.WriteLine(); + } } } diff --git a/MPF.CLI/Program.cs b/MPF.CLI/Program.cs index c8958ece..fc57ab78 100644 --- a/MPF.CLI/Program.cs +++ b/MPF.CLI/Program.cs @@ -31,7 +31,8 @@ namespace MPF.CLI OptionsLoader.SaveToConfig(options); // Display non-error message - DisplayHelp("First-run detected! Please fill out config.json and run again."); + Console.WriteLine("First-run detected! Please fill out config.json and run again."); + BaseFeature.DisplayHelp(); return; } @@ -42,7 +43,7 @@ namespace MPF.CLI // If we have no args, show the help and quit if (args == null || args.Length == 0) { - DisplayHelp(); + BaseFeature.DisplayHelp(); return; } @@ -54,7 +55,7 @@ namespace MPF.CLI switch (topLevel) { // Standalone Options - case Help: DisplayHelp(); return; + case Help: BaseFeature.DisplayHelp(); return; case VersionFeature version: version.Execute(); return; case ListCodesFeature lc: lc.Execute(); return; case ListMediaTypesFeature lm: lm.Execute(); return; @@ -65,22 +66,30 @@ namespace MPF.CLI case InteractiveFeature interactive: if (!interactive.ProcessArgs(args, 0)) { - DisplayHelp(); + BaseFeature.DisplayHelp(); return; } - - interactive.Execute(); + if (!interactive.Execute()) + { + BaseFeature.DisplayHelp(); + return; + } + break; // Default Behavior default: if (!mainFeature.ProcessArgs(args, 0)) { - DisplayHelp(); + BaseFeature.DisplayHelp(); + return; + } + if (!mainFeature.Execute()) + { + BaseFeature.DisplayHelp(); return; } - mainFeature.Execute(); break; } } @@ -134,52 +143,5 @@ namespace MPF.CLI return commandSet; } - - /// - /// Display help for MPF.CLI - /// - /// Error string to prefix the help text with - internal static void DisplayHelp(string? error = null) - { - if (error != null) - Console.WriteLine(error); - - Console.WriteLine("Usage:"); - 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("i, interactive Enable interactive mode"); - Console.WriteLine(); - - Console.WriteLine("CLI Options:"); - Console.WriteLine("-u, --use Override configured dumping program name"); - Console.WriteLine("-t, --mediatype Set media type for dumping (Required for DIC)"); - Console.WriteLine("-d, --device Physical drive path (Required if no custom parameters set)"); - Console.WriteLine("-m, --mounted Mounted filesystem path for additional checks"); - Console.WriteLine("-f, --file \"\" Output file path (Required if no custom parameters set)"); - Console.WriteLine("-s, --speed Override default dumping speed"); - Console.WriteLine("-c, --custom \"\" Custom parameters to use"); - Console.WriteLine(); - - Console.WriteLine("Dumping program paths and other settings can be found in the config.json file"); - Console.WriteLine("generated next to the program by default. Ensure that all settings are to user"); - Console.WriteLine("preference before running MPF.CLI."); - Console.WriteLine(); - - Console.WriteLine("Custom dumping parameters, if used, will fully replace the default parameters."); - Console.WriteLine("All dumping parameters need to be supplied if doing this."); - Console.WriteLine("Otherwise, both a drive path and output file path are required."); - Console.WriteLine(); - - Console.WriteLine("Mounted filesystem path is only recommended on OSes that require block"); - Console.WriteLine("device dumping, usually Linux and macOS."); - Console.WriteLine(); - } } } diff --git a/MPF.Check/Features/BaseFeature.cs b/MPF.Check/Features/BaseFeature.cs index 7b451f4f..73d9e278 100644 --- a/MPF.Check/Features/BaseFeature.cs +++ b/MPF.Check/Features/BaseFeature.cs @@ -72,7 +72,7 @@ namespace MPF.Check.Features { if (Options.InternalProgram == InternalProgram.NONE) { - Program.DisplayHelp("A program name needs to be provided"); + Console.Error.WriteLine("A program name needs to be provided"); return false; } @@ -98,7 +98,7 @@ namespace MPF.Check.Features // Check for a file if (!File.Exists(Inputs[i].Trim('"'))) { - Program.DisplayHelp($"{Inputs[i].Trim('"')} does not exist"); + Console.Error.WriteLine($"{Inputs[i].Trim('"')} does not exist"); return false; } @@ -125,5 +125,48 @@ namespace MPF.Check.Features return true; } + + /// + /// Display help for MPF.Check + /// + /// Error string to prefix the help text with + public static void DisplayHelp() + { + Console.WriteLine("Usage:"); + 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("i, interactive Enable interactive mode"); + Console.WriteLine(); + + Console.WriteLine("Check Options:"); + Console.WriteLine("-u, --use Dumping program output type [REQUIRED]"); + Console.WriteLine(" --load-seed Load a seed submission JSON for user information"); + Console.WriteLine(" --no-placeholders Disable placeholder values in submission info"); + Console.WriteLine(" --create-ird Create IRD from output files (PS3 only)"); + Console.WriteLine(" --no-retrieve Disable retrieving match information from Redump"); + Console.WriteLine("-c, --credentials Redump username and password (incompatible with --no-retrieve)"); + Console.WriteLine(" --pull-all Pull all information from Redump (requires --credentials)"); + Console.WriteLine("-p, --path Physical drive path for additional checks"); + Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)"); + Console.WriteLine(" --disable-archives Disable scanning archives (requires --scan)"); + Console.WriteLine(" --enable-debug Enable debug protection information (requires --scan)"); + Console.WriteLine(" --hide-drive-letters Hide drive letters from scan output (requires --scan)"); + Console.WriteLine("-x, --suffix Enable adding filename suffix"); + Console.WriteLine("-j, --json Enable submission JSON output"); + Console.WriteLine(" --include-artifacts Include artifacts in JSON (requires --json)"); + Console.WriteLine("-z, --zip Enable log file compression"); + Console.WriteLine("-d, --delete Enable unnecessary file deletion"); + Console.WriteLine(); + Console.WriteLine("WARNING: Check will overwrite both any existing submission information files as well"); + Console.WriteLine("as any log archives. Please make backups of those if you need to before running Check."); + Console.WriteLine(); + } } } diff --git a/MPF.Check/Program.cs b/MPF.Check/Program.cs index d3c31e17..edca2913 100644 --- a/MPF.Check/Program.cs +++ b/MPF.Check/Program.cs @@ -21,7 +21,7 @@ namespace MPF.Check // If we have no args, show the help and quit if (args == null || args.Length == 0) { - DisplayHelp(); + BaseFeature.DisplayHelp(); return; } @@ -33,7 +33,7 @@ namespace MPF.Check switch (topLevel) { // Standalone Options - case Help: DisplayHelp(); return; + case Help: BaseFeature.DisplayHelp(); return; case VersionFeature version: version.Execute(); return; case ListCodesFeature lc: lc.Execute(); return; case ListMediaTypesFeature lm: lm.Execute(); return; @@ -44,32 +44,42 @@ namespace MPF.Check case InteractiveFeature interactive: if (!interactive.ProcessArgs(args, 0)) { - DisplayHelp(); + BaseFeature.DisplayHelp(); return; } - else if (!interactive.VerifyInputs()) + if (!interactive.VerifyInputs()) { - DisplayHelp("At least one input is required"); + Console.Error.WriteLine("At least one input is required"); + BaseFeature.DisplayHelp(); + return; + } + if (!interactive.Execute()) + { + BaseFeature.DisplayHelp(); return; } - interactive.Execute(); break; // Default Behavior default: if (!mainFeature.ProcessArgs(args, 0)) { - DisplayHelp(); + BaseFeature.DisplayHelp(); return; } - else if (!mainFeature.VerifyInputs()) + if (!mainFeature.VerifyInputs()) { - DisplayHelp("At least one input is required"); + Console.Error.WriteLine("At least one input is required"); + BaseFeature.DisplayHelp(); + return; + } + if (mainFeature.Execute()) + { + BaseFeature.DisplayHelp(); return; } - mainFeature.Execute(); break; } } @@ -123,51 +133,5 @@ namespace MPF.Check return commandSet; } - - /// - /// Display help for MPF.Check - /// - /// Error string to prefix the help text with - internal static void DisplayHelp(string? error = null) - { - if (error != null) - Console.WriteLine(error); - - Console.WriteLine("Usage:"); - 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("i, interactive Enable interactive mode"); - Console.WriteLine(); - - Console.WriteLine("Check Options:"); - Console.WriteLine("-u, --use Dumping program output type [REQUIRED]"); - Console.WriteLine(" --load-seed Load a seed submission JSON for user information"); - Console.WriteLine(" --no-placeholders Disable placeholder values in submission info"); - Console.WriteLine(" --create-ird Create IRD from output files (PS3 only)"); - Console.WriteLine(" --no-retrieve Disable retrieving match information from Redump"); - Console.WriteLine("-c, --credentials Redump username and password (incompatible with --no-retrieve)"); - Console.WriteLine(" --pull-all Pull all information from Redump (requires --credentials)"); - Console.WriteLine("-p, --path Physical drive path for additional checks"); - Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)"); - Console.WriteLine(" --disable-archives Disable scanning archives (requires --scan)"); - Console.WriteLine(" --enable-debug Enable debug protection information (requires --scan)"); - Console.WriteLine(" --hide-drive-letters Hide drive letters from scan output (requires --scan)"); - Console.WriteLine("-x, --suffix Enable adding filename suffix"); - Console.WriteLine("-j, --json Enable submission JSON output"); - Console.WriteLine(" --include-artifacts Include artifacts in JSON (requires --json)"); - Console.WriteLine("-z, --zip Enable log file compression"); - Console.WriteLine("-d, --delete Enable unnecessary file deletion"); - Console.WriteLine(); - Console.WriteLine("WARNING: Check will overwrite both any existing submission information files as well"); - Console.WriteLine("as any log archives. Please make backups of those if you need to before running Check."); - Console.WriteLine(); - } } }