diff --git a/.editorconfig b/.editorconfig
index e6796a9..522a693 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -289,6 +289,12 @@ dotnet_diagnostic.ide0044.severity = none
# IDE0042: Deconstruct variable declaration
dotnet_diagnostic.ide0042.severity = none
+# IDE0305: Simplify collection initialization
+dotnet_diagnostic.ide0305.severity = none
+
+# IDE0057: Substring can be simplified
+dotnet_diagnostic.ide0057.severity = none
+
# CS1998: Async method lacks 'await' operators and will run synchronously
dotnet_diagnostic.cs1998.severity = none
diff --git a/Src/Attributes.cs b/Src/Attributes.cs
new file mode 100644
index 0000000..a745d42
--- /dev/null
+++ b/Src/Attributes.cs
@@ -0,0 +1,144 @@
+using RT.Util;
+using RT.Util.Consoles;
+
+namespace RT.CommandLine;
+
+///
+/// Use this to specify that a field in a class can be specified on the command line using an option, for example
+/// -a or --option-name. The option name(s) MUST begin with a dash (-).
+///
+/// The name of the option. Specify several names as synonyms if required.
+[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public sealed class OptionAttribute(params string[] names) : Attribute
+{
+ /// All of the names of the option.
+ public string[] Names { get; private set; } = names;
+}
+
+///
+/// Use this to specify that a command-line parameter is positional, i.e. is not invoked by an option that starts with
+/// "-".
+[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public sealed class IsPositionalAttribute : Attribute
+{
+ /// Constructor.
+ public IsPositionalAttribute() { }
+}
+
+/// Use this to specify that a command-line parameter is mandatory.
+[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public sealed class IsMandatoryAttribute() : Attribute
+{
+}
+
+/// Specifies that the command-line parser should ignore a field.
+[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+public sealed class IgnoreAttribute : Attribute
+{
+ /// Constructor.
+ public IgnoreAttribute() { }
+}
+
+///
+/// Specifies that a field of an enum type should be interpreted as multiple possible options, each specified by an on the enum values in the enum type.
+[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+public sealed class EnumOptionsAttribute(EnumBehavior behavior) : Attribute
+{
+ ///
+ /// Specifies whether the enum is considered to represent a single value or a bitfield containing multiple values.
+ public EnumBehavior Behavior { get; private set; } = behavior;
+}
+
+///
+/// Use this on a sub-class of an abstract class or on an enum value to specify the command the user must use to invoke
+/// that class or enum value.
+///
+/// The command(s) the user can specify to invoke this class or enum value.
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public sealed class CommandNameAttribute(params string[] names) : Attribute
+{
+ /// The command the user can specify to invoke this class.
+ public string[] Names { get; private set; } = names;
+}
+
+/// Use this on an abstract class to specify that its subclasses represent various commands.
+[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+public sealed class CommandGroupAttribute : Attribute
+{
+ /// Constructor.
+ public CommandGroupAttribute() { }
+}
+
+///
+/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
+/// for single-language applications only. See Remarks.
+///
+/// This attribute specifies the documentation in plain text. All characters are printed exactly as specified. You may
+/// wish to use to specify documentation with special markup for
+/// command-line-related concepts, as well as for an alternative markup
+/// language without command-line specific concepts.
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public class DocumentationAttribute(string documentation) : Attribute
+{
+ ///
+ /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
+ /// where applicable.
+ public virtual ConsoleColoredString Text => OriginalText;
+ /// Gets a string describing the documentation format to the programmer (not seen by the users).
+ public virtual string OriginalFormat => "Plain text";
+ /// Gets the original documentation string exactly as specified in the attribute.
+ public string OriginalText { get; private set; } = documentation;
+}
+
+///
+/// This is a legacy attribute. Do not use in new programs. This attribute is equivalent to .
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public class DocumentationLiteralAttribute(string documentation) : DocumentationEggsMLAttribute(documentation)
+{
+}
+
+///
+/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
+/// for single-language applications only. The documentation is to be specified in , which is
+/// interpreted as described in . See also and .
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public class DocumentationEggsMLAttribute(string documentation) : DocumentationAttribute(documentation)
+{
+ /// Gets a string describing the documentation format to the programmer (not seen by the users).
+ public override string OriginalFormat { get { return "EggsML"; } }
+ ///
+ /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
+ /// where applicable.
+ public override ConsoleColoredString Text => _parsed ??= CommandLineParser.Colorize(EggsML.Parse(OriginalText));
+ private ConsoleColoredString _parsed;
+}
+
+///
+/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
+/// for single-language applications only. The documentation is to be specified in , which is
+/// interpreted as described in . See also .
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
+public class DocumentationRhoMLAttribute(string documentation) : DocumentationAttribute(documentation)
+{
+ /// Gets a string describing the documentation format to the programmer (not seen by the users).
+ public override string OriginalFormat { get { return "RhoML"; } }
+ ///
+ /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
+ /// where applicable.
+ public override ConsoleColoredString Text => _parsed ??= CommandLineParser.Colorize(RhoML.Parse(OriginalText));
+ private ConsoleColoredString _parsed;
+}
+
+///
+/// Specifies that a specific command-line option should not be printed in help pages, i.e. the option should explicitly
+/// be undocumented.
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+public sealed class UndocumentedAttribute : Attribute
+{
+ /// Constructor.
+ public UndocumentedAttribute() { }
+}
diff --git a/Src/CommandGroupAttribute.cs b/Src/CommandGroupAttribute.cs
deleted file mode 100644
index f51e67f..0000000
--- a/Src/CommandGroupAttribute.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace RT.CommandLine;
-
-/// Use this on an abstract class to specify that its subclasses represent various commands.
-[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
-public sealed class CommandGroupAttribute : Attribute
-{
- /// Constructor.
- public CommandGroupAttribute() { }
-}
diff --git a/Src/CommandLineHelpRequestedException.cs b/Src/CommandLineHelpRequestedException.cs
deleted file mode 100644
index 1785256..0000000
--- a/Src/CommandLineHelpRequestedException.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-/// Indicates that the user supplied one of the standard options we recognize as a help request.
-[Serializable]
-public sealed class CommandLineHelpRequestedException(Func helpGenerator)
- : CommandLineParseException("The user has requested help using one of the help options.".Color(ConsoleColor.Gray), helpGenerator)
-{
- /// Prints usage information.
- public override void WriteUsageInfoToConsole() => ConsoleUtil.Write(GenerateHelp(ConsoleUtil.WrapToWidth()));
- ///
- protected internal override bool WriteErrorText => false;
-}
diff --git a/Src/CommandLineParseException.cs b/Src/CommandLineParseException.cs
deleted file mode 100644
index 14c006e..0000000
--- a/Src/CommandLineParseException.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-/// Represents any error encountered while parsing a command line. This class is abstract.
-[Serializable]
-public abstract class CommandLineParseException(ConsoleColoredString message, Func helpGenerator, Exception inner)
- : Exception(message.ToString(), inner)
-{
- ///
- /// Generates the help screen to be output to the user on the console. For non-internationalised (single-language)
- /// applications, pass null for the Translation parameter.
- internal Func GenerateHelpFunc { get; private set; } = helpGenerator;
- /// Contains the error message that describes the cause of this exception.
- public ConsoleColoredString ColoredMessage { get; private set; } = message;
- ///
- /// Generates the help screen to be output to the user on the console.
- ///
- /// The character width at which the output should be word-wrapped. The default (null) uses .
- public ConsoleColoredString GenerateHelp(int? wrapWidth = null) { return GenerateHelpFunc(wrapWidth ?? ConsoleUtil.WrapToWidth()); }
- ///
- /// Generates a printable description of the error represented by this exception, typically used to tell the user what
- /// they did wrong.
- ///
- /// The character width at which the output should be word-wrapped. The default (null) uses .
- public ConsoleColoredString GenerateErrorText(int? wrapWidth = null)
- {
- var strings = new List();
- var message = "Error:".Color(CmdLineColor.Error) + " " + ColoredMessage;
- foreach (var line in message.WordWrap(wrapWidth ?? ConsoleUtil.WrapToWidth(), "Error:".Length + 1))
- {
- strings.Add(line);
- strings.Add(Environment.NewLine);
- }
- return new ConsoleColoredString(strings);
- }
-
- /// Constructor.
- public CommandLineParseException(ConsoleColoredString message, Func helpGenerator) : this(message, helpGenerator, null) { }
-
- ///
- /// Prints usage information, followed by an error message describing to the user what it was that the parser didn't
- /// understand.
- public virtual void WriteUsageInfoToConsole()
- {
- ConsoleUtil.Write(GetUsageInfo());
- }
-
- ///
- /// Generates and returns usage information, followed by an error message describing to the user what it was that the
- /// parser didn't understand.
- public ConsoleColoredString GetUsageInfo()
- {
- var s = GenerateHelp(ConsoleUtil.WrapToWidth());
- if (WriteErrorText)
- s += Environment.NewLine + GenerateErrorText(ConsoleUtil.WrapToWidth());
- return s;
- }
-
- ///
- /// Determines whether and should call and output it to the console. Default is true.
- ///
- /// Only set this to false if the user explicitly asked to see the help screen. Otherwise its appearance
- /// without explanation is confusing.
- protected internal virtual bool WriteErrorText => true;
-}
diff --git a/Src/CommandLineValidationException.cs b/Src/CommandLineValidationException.cs
deleted file mode 100644
index faf35e7..0000000
--- a/Src/CommandLineValidationException.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using RT.Util.Consoles;
-
-namespace RT.CommandLine;
-
-/// Specifies that the arguments specified by the user on the command-line do not pass the custom validation checks.
-[Serializable]
-public sealed class CommandLineValidationException(ConsoleColoredString message, Func helpGenerator)
- : CommandLineParseException(message, helpGenerator)
-{
-}
diff --git a/Src/CommandNameAttribute.cs b/Src/CommandNameAttribute.cs
deleted file mode 100644
index 3460d57..0000000
--- a/Src/CommandNameAttribute.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using RT.Util;
-
-namespace RT.CommandLine;
-
-///
-/// Use this on a sub-class of an abstract class or on an enum value to specify the command the user must use to invoke
-/// that class or enum value.
-///
-/// The command(s) the user can specify to invoke this class or enum value.
-[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public sealed class CommandNameAttribute(params string[] names) : Attribute
-{
- /// The command the user can specify to invoke this class.
- public string[] Names { get; private set; } = names;
-}
diff --git a/Src/DocumentationAttribute.cs b/Src/DocumentationAttribute.cs
deleted file mode 100644
index ca70e76..0000000
--- a/Src/DocumentationAttribute.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using RT.Util;
-using RT.Util.Consoles;
-
-namespace RT.CommandLine;
-
-///
-/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
-/// for single-language applications only. See Remarks.
-///
-/// This attribute specifies the documentation in plain text. All characters are printed exactly as specified. You may
-/// wish to use to specify documentation with special markup for
-/// command-line-related concepts, as well as for an alternative markup
-/// language without command-line specific concepts.
-[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public class DocumentationAttribute(string documentation) : Attribute
-{
- ///
- /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
- /// where applicable.
- public virtual ConsoleColoredString Text => OriginalText;
- /// Gets a string describing the documentation format to the programmer (not seen by the users).
- public virtual string OriginalFormat => "Plain text";
- /// Gets the original documentation string exactly as specified in the attribute.
- public string OriginalText { get; private set; } = documentation;
-}
diff --git a/Src/DocumentationEggsMLAttribute.cs b/Src/DocumentationEggsMLAttribute.cs
deleted file mode 100644
index 6ff83be..0000000
--- a/Src/DocumentationEggsMLAttribute.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using RT.Util;
-using RT.Util.Consoles;
-
-namespace RT.CommandLine;
-
-///
-/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
-/// for single-language applications only. The documentation is to be specified in , which is
-/// interpreted as described in . See also and .
-[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public class DocumentationEggsMLAttribute(string documentation) : DocumentationAttribute(documentation)
-{
- /// Gets a string describing the documentation format to the programmer (not seen by the users).
- public override string OriginalFormat { get { return "EggsML"; } }
- ///
- /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
- /// where applicable.
- public override ConsoleColoredString Text => _parsed ??= CommandLineParser.Colorize(EggsML.Parse(OriginalText));
- private ConsoleColoredString _parsed;
-}
diff --git a/Src/DocumentationLiteralAttribute.cs b/Src/DocumentationLiteralAttribute.cs
deleted file mode 100644
index a141f1e..0000000
--- a/Src/DocumentationLiteralAttribute.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using RT.Util;
-
-namespace RT.CommandLine;
-
-///
-/// This is a legacy attribute. Do not use in new programs. This attribute is equivalent to .
-[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public class DocumentationLiteralAttribute(string documentation) : DocumentationEggsMLAttribute(documentation)
-{
-}
diff --git a/Src/DocumentationRhoMLAttribute.cs b/Src/DocumentationRhoMLAttribute.cs
deleted file mode 100644
index 10b7965..0000000
--- a/Src/DocumentationRhoMLAttribute.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using RT.Util;
-using RT.Util.Consoles;
-
-namespace RT.CommandLine;
-
-///
-/// Use this attribute to link a command-line option or command with the help text that describes (documents) it. Suitable
-/// for single-language applications only. The documentation is to be specified in , which is
-/// interpreted as described in . See also .
-[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public class DocumentationRhoMLAttribute(string documentation) : DocumentationAttribute(documentation)
-{
- /// Gets a string describing the documentation format to the programmer (not seen by the users).
- public override string OriginalFormat { get { return "RhoML"; } }
- ///
- /// Gets the console-colored documentation string. Note that this property may throw if the text couldn't be parsed
- /// where applicable.
- public override ConsoleColoredString Text => _parsed ??= CommandLineParser.Colorize(RhoML.Parse(OriginalText));
- private ConsoleColoredString _parsed;
-}
diff --git a/Src/EnumOptionsAttribute.cs b/Src/EnumOptionsAttribute.cs
deleted file mode 100644
index 47cff33..0000000
--- a/Src/EnumOptionsAttribute.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace RT.CommandLine;
-
-///
-/// Specifies that a field of an enum type should be interpreted as multiple possible options, each specified by an on the enum values in the enum type.
-[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
-public sealed class EnumOptionsAttribute(EnumBehavior behavior) : Attribute
-{
- ///
- /// Specifies whether the enum is considered to represent a single value or a bitfield containing multiple values.
- public EnumBehavior Behavior { get; private set; } = behavior;
-}
diff --git a/Src/Exceptions.cs b/Src/Exceptions.cs
new file mode 100644
index 0000000..b185086
--- /dev/null
+++ b/Src/Exceptions.cs
@@ -0,0 +1,189 @@
+using System.Reflection;
+using RT.Util.Consoles;
+using RT.Util.ExtensionMethods;
+
+namespace RT.CommandLine;
+
+/// Represents any error encountered while parsing a command line. This class is abstract.
+[Serializable]
+public abstract class CommandLineParseException(ConsoleColoredString message, Func helpGenerator, Exception inner)
+ : Exception(message.ToString(), inner)
+{
+ ///
+ /// Generates the help screen to be output to the user on the console. For non-internationalised (single-language)
+ /// applications, pass null for the Translation parameter.
+ internal Func GenerateHelpFunc { get; private set; } = helpGenerator;
+ /// Contains the error message that describes the cause of this exception.
+ public ConsoleColoredString ColoredMessage { get; private set; } = message;
+ ///
+ /// Generates the help screen to be output to the user on the console.
+ ///
+ /// The character width at which the output should be word-wrapped. The default (null) uses .
+ public ConsoleColoredString GenerateHelp(int? wrapWidth = null) { return GenerateHelpFunc(wrapWidth ?? ConsoleUtil.WrapToWidth()); }
+ ///
+ /// Generates a printable description of the error represented by this exception, typically used to tell the user what
+ /// they did wrong.
+ ///
+ /// The character width at which the output should be word-wrapped. The default (null) uses .
+ public ConsoleColoredString GenerateErrorText(int? wrapWidth = null)
+ {
+ var strings = new List();
+ var message = "Error:".Color(CmdLineColor.Error) + " " + ColoredMessage;
+ foreach (var line in message.WordWrap(wrapWidth ?? ConsoleUtil.WrapToWidth(), "Error:".Length + 1))
+ {
+ strings.Add(line);
+ strings.Add(Environment.NewLine);
+ }
+ return new ConsoleColoredString(strings);
+ }
+
+ /// Constructor.
+ public CommandLineParseException(ConsoleColoredString message, Func helpGenerator) : this(message, helpGenerator, null) { }
+
+ ///
+ /// Prints usage information, followed by an error message describing to the user what it was that the parser didn't
+ /// understand.
+ public virtual void WriteUsageInfoToConsole()
+ {
+ ConsoleUtil.Write(GetUsageInfo());
+ }
+
+ ///
+ /// Generates and returns usage information, followed by an error message describing to the user what it was that the
+ /// parser didn't understand.
+ public ConsoleColoredString GetUsageInfo()
+ {
+ var s = GenerateHelp(ConsoleUtil.WrapToWidth());
+ if (WriteErrorText)
+ s += Environment.NewLine + GenerateErrorText(ConsoleUtil.WrapToWidth());
+ return s;
+ }
+
+ ///
+ /// Determines whether and should call and output it to the console. Default is true.
+ ///
+ /// Only set this to false if the user explicitly asked to see the help screen. Otherwise its appearance
+ /// without explanation is confusing.
+ protected internal virtual bool WriteErrorText => true;
+}
+
+/// Indicates that the user supplied one of the standard options we recognize as a help request.
+[Serializable]
+public sealed class CommandLineHelpRequestedException(Func helpGenerator)
+ : CommandLineParseException("The user has requested help using one of the help options.".Color(ConsoleColor.Gray), helpGenerator)
+{
+ /// Prints usage information.
+ public override void WriteUsageInfoToConsole() => ConsoleUtil.Write(GenerateHelp(ConsoleUtil.WrapToWidth()));
+ ///
+ protected internal override bool WriteErrorText => false;
+}
+
+///
+/// Specifies that the command-line parser encountered a command or option that was not recognised (there was no or attribute with a matching option or command name).
+[Serializable]
+public sealed class UnrecognizedCommandOrOptionException(string commandOrOptionName, Func helpGenerator, Exception inner)
+ : CommandLineParseException("The specified command or option, {0}, is not recognized.".ToConsoleColoredString().Fmt(commandOrOptionName.Color(ConsoleColor.White)), helpGenerator, inner)
+{
+ /// The unrecognized command name or option name.
+ public string CommandOrOptionName { get; private set; } = commandOrOptionName;
+ /// Constructor.
+ public UnrecognizedCommandOrOptionException(string commandOrOptionName, Func helpGenerator) : this(commandOrOptionName, helpGenerator, null) { }
+}
+
+///
+/// Specifies that the command-line parser encountered a command or option that is not allowed in conjunction with a
+/// previously-encountered command or option.
+[Serializable]
+public sealed class IncompatibleCommandOrOptionException(string earlier, string later, Func helpGenerator, Exception inner)
+ : CommandLineParseException("The command or option, {0}, cannot be used in conjunction with {1}. Please specify only one of the two.".ToConsoleColoredString().Fmt(later.Color(ConsoleColor.White), earlier.Color(ConsoleColor.White)), helpGenerator, inner)
+{
+ ///
+ /// The earlier option or command, which by itself is valid, but conflicts with the .
+ public string EarlierCommandOrOption { get; private set; } = earlier;
+ /// The later option or command, which conflicts with the .
+ public string LaterCommandOrOption { get; private set; } = later;
+ /// Constructor.
+ public IncompatibleCommandOrOptionException(string earlier, string later, Func helpGenerator) : this(earlier, later, helpGenerator, null) { }
+}
+
+///
+/// Specifies that the command-line parser encountered the end of the command line when it expected additional mandatory
+/// options.
+[Serializable]
+public sealed class MissingParameterException(FieldInfo paramField, FieldInfo beforeField, bool isOption, Func helpGenerator, Exception inner)
+ : CommandLineParseException(getMessage(paramField, beforeField, isOption), helpGenerator, inner)
+{
+ /// Contains the field pertaining to the parameter that was missing.
+ public FieldInfo Field { get; private set; } = paramField;
+
+ /// Contains an optional reference to a field which the missing parameter must precede.
+ public FieldInfo BeforeField { get; private set; } = beforeField;
+
+ ///
+ /// Specifies whether the missing parameter was a missing option (true) or a missing positional parameter (false).
+ public bool IsOption { get; private set; } = isOption;
+
+ /// Constructor.
+ public MissingParameterException(FieldInfo paramField, FieldInfo beforeField, bool isOption, Func helpGenerator) : this(paramField, beforeField, isOption, helpGenerator, null) { }
+
+ private static ConsoleColoredString getMessage(FieldInfo field, FieldInfo beforeField, bool isOption)
+ {
+ if (beforeField == null)
+ return (isOption ? "The option {0} is mandatory and must be specified." : "The parameter {0} is mandatory and must be specified.").ToConsoleColoredString().Fmt(field.FormatParameterUsage(true));
+
+ return (isOption ? "The option {0} is mandatory and must be specified before the {1} parameter." : "The parameter {0} is mandatory and must be specified before the {1} parameter.").ToConsoleColoredString().Fmt(
+ field.FormatParameterUsage(true),
+ "<".Color(CmdLineColor.FieldBrackets) + beforeField.Name.Color(CmdLineColor.Field) + ">".Color(CmdLineColor.FieldBrackets));
+ }
+}
+
+///
+/// Specifies that the command-line parser encountered additional command-line arguments when it expected the end of the
+/// command line.
+[Serializable]
+public sealed class UnexpectedArgumentException(string[] unexpectedArgs, Func helpGenerator, Exception inner)
+ : CommandLineParseException("Unexpected parameter: {0}".ToConsoleColoredString().Fmt(unexpectedArgs.Select(prm => prm.Length > 50 ? $"{prm.Substring(0, 47)}..." : prm).FirstOrDefault().Color(CmdLineColor.UnexpectedArgument)), helpGenerator, inner)
+{
+ /// Contains the first unexpected argument and all of the subsequent arguments.
+ public string[] UnexpectedParameters { get; private set; } = unexpectedArgs;
+ /// Constructor.
+ public UnexpectedArgumentException(string[] unexpectedArgs, Func helpGenerator) : this(unexpectedArgs, helpGenerator, null) { }
+}
+
+///
+/// Specifies that the command-line parser encountered the end of the command line when it expected an argument to an
+/// option.
+[Serializable]
+public sealed class IncompleteOptionException(string optionName, Func helpGenerator, Exception inner)
+ : CommandLineParseException("The {0} option must be followed by an additional parameter.".ToConsoleColoredString().Fmt(optionName.Color(ConsoleColor.White)), helpGenerator, inner)
+{
+ /// The name of the option that was missing an argument.
+ public string OptionName { get; private set; } = optionName;
+ /// Constructor.
+ public IncompleteOptionException(string optionName, Func helpGenerator) : this(optionName, helpGenerator, null) { }
+}
+
+///
+/// Specifies that a parameter that expected a numerical value was passed a string by the user that doesn’t parse as a
+/// number.
+[Serializable]
+public sealed class InvalidNumericParameterException(string fieldName, Func helpGenerator, Exception inner)
+ : CommandLineParseException("The {0} option expects a number. The specified parameter does not constitute a valid number.".ToConsoleColoredString().Fmt("<".Color(CmdLineColor.FieldBrackets) + fieldName.Color(CmdLineColor.Field) + ">".Color(CmdLineColor.FieldBrackets)), helpGenerator, inner)
+{
+ /// Contains the name of the field pertaining to the parameter that was passed an invalid value.
+ public string FieldName { get; private set; } = fieldName;
+ /// Constructor.
+ public InvalidNumericParameterException(string fieldName, Func helpGenerator) : this(fieldName, helpGenerator, null) { }
+}
+
+/// Specifies that the arguments specified by the user on the command-line do not pass the custom validation checks.
+[Serializable]
+public sealed class CommandLineValidationException(ConsoleColoredString message, Func helpGenerator)
+ : CommandLineParseException(message, helpGenerator)
+{
+}
diff --git a/Src/GlobalSuppressions.cs b/Src/GlobalSuppressions.cs
deleted file mode 100644
index 7ae7a12..0000000
--- a/Src/GlobalSuppressions.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is used by Code Analysis to maintain SuppressMessage
-// attributes that are applied to this project.
-// Project-level suppressions either have no target or are given
-// a specific target and scoped to a namespace, type, member, etc.
-
-using System.Diagnostics.CodeAnalysis;
-
-[assembly: SuppressMessage("Style", "IDE0305:Simplify collection initialization", Justification = "Let me use ToArray", Scope = "member", Target = "~M:RT.CommandLine.CommandLineParser.parseCommandLine(System.String[],System.Type,System.Int32,System.Func{RT.Util.Consoles.ConsoleColoredString,RT.Util.Consoles.ConsoleColoredString})~System.Object")]
-[assembly: SuppressMessage("Style", "IDE0057:Substring can be simplified", Justification = "Let me use Substring")]
diff --git a/Src/IgnoreAttribute.cs b/Src/IgnoreAttribute.cs
deleted file mode 100644
index 43ec55e..0000000
--- a/Src/IgnoreAttribute.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace RT.CommandLine;
-
-/// Specifies that the command-line parser should ignore a field.
-[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
-public sealed class IgnoreAttribute : Attribute
-{
- /// Constructor.
- public IgnoreAttribute() { }
-}
diff --git a/Src/IncompatibleCommandOrOptionException.cs b/Src/IncompatibleCommandOrOptionException.cs
deleted file mode 100644
index f4101c1..0000000
--- a/Src/IncompatibleCommandOrOptionException.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that the command-line parser encountered a command or option that is not allowed in conjunction with a
-/// previously-encountered command or option.
-[Serializable]
-public sealed class IncompatibleCommandOrOptionException(string earlier, string later, Func helpGenerator, Exception inner)
- : CommandLineParseException("The command or option, {0}, cannot be used in conjunction with {1}. Please specify only one of the two.".ToConsoleColoredString().Fmt(later.Color(ConsoleColor.White), earlier.Color(ConsoleColor.White)), helpGenerator, inner)
-{
- ///
- /// The earlier option or command, which by itself is valid, but conflicts with the .
- public string EarlierCommandOrOption { get; private set; } = earlier;
- /// The later option or command, which conflicts with the .
- public string LaterCommandOrOption { get; private set; } = later;
- /// Constructor.
- public IncompatibleCommandOrOptionException(string earlier, string later, Func helpGenerator) : this(earlier, later, helpGenerator, null) { }
-}
diff --git a/Src/IncompleteOptionException.cs b/Src/IncompleteOptionException.cs
deleted file mode 100644
index 4c5d048..0000000
--- a/Src/IncompleteOptionException.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that the command-line parser encountered the end of the command line when it expected an argument to an
-/// option.
-[Serializable]
-public sealed class IncompleteOptionException(string optionName, Func helpGenerator, Exception inner)
- : CommandLineParseException("The {0} option must be followed by an additional parameter.".ToConsoleColoredString().Fmt(optionName.Color(ConsoleColor.White)), helpGenerator, inner)
-{
- /// The name of the option that was missing an argument.
- public string OptionName { get; private set; } = optionName;
- /// Constructor.
- public IncompleteOptionException(string optionName, Func helpGenerator) : this(optionName, helpGenerator, null) { }
-}
diff --git a/Src/InvalidNumericParameterException.cs b/Src/InvalidNumericParameterException.cs
deleted file mode 100644
index 35d138d..0000000
--- a/Src/InvalidNumericParameterException.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that a parameter that expected a numerical value was passed a string by the user that doesn’t parse as a
-/// number.
-[Serializable]
-public sealed class InvalidNumericParameterException(string fieldName, Func helpGenerator, Exception inner)
- : CommandLineParseException("The {0} option expects a number. The specified parameter does not constitute a valid number.".ToConsoleColoredString().Fmt("<".Color(CmdLineColor.FieldBrackets) + fieldName.Color(CmdLineColor.Field) + ">".Color(CmdLineColor.FieldBrackets)), helpGenerator, inner)
-{
- /// Contains the name of the field pertaining to the parameter that was passed an invalid value.
- public string FieldName { get; private set; } = fieldName;
- /// Constructor.
- public InvalidNumericParameterException(string fieldName, Func helpGenerator) : this(fieldName, helpGenerator, null) { }
-}
diff --git a/Src/IsMandatoryAttribute.cs b/Src/IsMandatoryAttribute.cs
deleted file mode 100644
index 74050cc..0000000
--- a/Src/IsMandatoryAttribute.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using RT.Util;
-
-namespace RT.CommandLine;
-
-/// Use this to specify that a command-line parameter is mandatory.
-[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public sealed class IsMandatoryAttribute() : Attribute
-{
-}
diff --git a/Src/IsPositionalAttribute.cs b/Src/IsPositionalAttribute.cs
deleted file mode 100644
index 35a5d2d..0000000
--- a/Src/IsPositionalAttribute.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using RT.Util;
-
-namespace RT.CommandLine;
-
-///
-/// Use this to specify that a command-line parameter is positional, i.e. is not invoked by an option that starts with
-/// "-".
-[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public sealed class IsPositionalAttribute : Attribute
-{
- /// Constructor.
- public IsPositionalAttribute() { }
-}
diff --git a/Src/MissingParameterException.cs b/Src/MissingParameterException.cs
deleted file mode 100644
index f3ec76e..0000000
--- a/Src/MissingParameterException.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that the command-line parser encountered the end of the command line when it expected additional mandatory
-/// options.
-[Serializable]
-public sealed class MissingParameterException(FieldInfo paramField, FieldInfo beforeField, bool isOption, Func helpGenerator, Exception inner)
- : CommandLineParseException(getMessage(paramField, beforeField, isOption), helpGenerator, inner)
-{
- /// Contains the field pertaining to the parameter that was missing.
- public FieldInfo Field { get; private set; } = paramField;
-
- /// Contains an optional reference to a field which the missing parameter must precede.
- public FieldInfo BeforeField { get; private set; } = beforeField;
-
- ///
- /// Specifies whether the missing parameter was a missing option (true) or a missing positional parameter (false).
- public bool IsOption { get; private set; } = isOption;
-
- /// Constructor.
- public MissingParameterException(FieldInfo paramField, FieldInfo beforeField, bool isOption, Func helpGenerator) : this(paramField, beforeField, isOption, helpGenerator, null) { }
-
- private static ConsoleColoredString getMessage(FieldInfo field, FieldInfo beforeField, bool isOption)
- {
- if (beforeField == null)
- return (isOption ? "The option {0} is mandatory and must be specified." : "The parameter {0} is mandatory and must be specified.").ToConsoleColoredString().Fmt(field.FormatParameterUsage(true));
-
- return (isOption ? "The option {0} is mandatory and must be specified before the {1} parameter." : "The parameter {0} is mandatory and must be specified before the {1} parameter.").ToConsoleColoredString().Fmt(
- field.FormatParameterUsage(true),
- "<".Color(CmdLineColor.FieldBrackets) + beforeField.Name.Color(CmdLineColor.Field) + ">".Color(CmdLineColor.FieldBrackets));
- }
-}
diff --git a/Src/OptionAttribute.cs b/Src/OptionAttribute.cs
deleted file mode 100644
index ba3ad9a..0000000
--- a/Src/OptionAttribute.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using RT.Util;
-
-namespace RT.CommandLine;
-
-///
-/// Use this to specify that a field in a class can be specified on the command line using an option, for example
-/// -a or --option-name. The option name(s) MUST begin with a dash (-).
-///
-/// The name of the option. Specify several names as synonyms if required.
-[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false), RummageKeepUsersReflectionSafe]
-public sealed class OptionAttribute(params string[] names) : Attribute
-{
- /// All of the names of the option.
- public string[] Names { get; private set; } = names;
-}
diff --git a/Src/UndocumentedAttribute.cs b/Src/UndocumentedAttribute.cs
deleted file mode 100644
index fc17f5c..0000000
--- a/Src/UndocumentedAttribute.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace RT.CommandLine;
-
-///
-/// Specifies that a specific command-line option should not be printed in help pages, i.e. the option should explicitly
-/// be undocumented.
-[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
-public sealed class UndocumentedAttribute : Attribute
-{
- /// Constructor.
- public UndocumentedAttribute() { }
-}
diff --git a/Src/UnexpectedArgumentException.cs b/Src/UnexpectedArgumentException.cs
deleted file mode 100644
index a8c9b8b..0000000
--- a/Src/UnexpectedArgumentException.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using RT.Internal;
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that the command-line parser encountered additional command-line arguments when it expected the end of the
-/// command line.
-[Serializable]
-public sealed class UnexpectedArgumentException(string[] unexpectedArgs, Func helpGenerator, Exception inner)
- : CommandLineParseException("Unexpected parameter: {0}".ToConsoleColoredString().Fmt(unexpectedArgs.Select(prm => prm.Length > 50 ? $"{prm.Substring(0, 47)}..." : prm).FirstOrDefault().Color(CmdLineColor.UnexpectedArgument)), helpGenerator, inner)
-{
- /// Contains the first unexpected argument and all of the subsequent arguments.
- public string[] UnexpectedParameters { get; private set; } = unexpectedArgs;
- /// Constructor.
- public UnexpectedArgumentException(string[] unexpectedArgs, Func helpGenerator) : this(unexpectedArgs, helpGenerator, null) { }
-}
diff --git a/Src/UnrecognizedCommandOrOptionException.cs b/Src/UnrecognizedCommandOrOptionException.cs
deleted file mode 100644
index 3d763d6..0000000
--- a/Src/UnrecognizedCommandOrOptionException.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using RT.Util.Consoles;
-using RT.Util.ExtensionMethods;
-
-namespace RT.CommandLine;
-
-///
-/// Specifies that the command-line parser encountered a command or option that was not recognised (there was no or attribute with a matching option or command name).
-[Serializable]
-public sealed class UnrecognizedCommandOrOptionException(string commandOrOptionName, Func helpGenerator, Exception inner)
- : CommandLineParseException("The specified command or option, {0}, is not recognized.".ToConsoleColoredString().Fmt(commandOrOptionName.Color(ConsoleColor.White)), helpGenerator, inner)
-{
- /// The unrecognized command name or option name.
- public string CommandOrOptionName { get; private set; } = commandOrOptionName;
- /// Constructor.
- public UnrecognizedCommandOrOptionException(string commandOrOptionName, Func helpGenerator) : this(commandOrOptionName, helpGenerator, null) { }
-}