mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
asd
This commit is contained in:
@@ -305,7 +305,7 @@ internal class HelpConsoleFormatter(ConsoleWriter consoleWriter, HelpContext con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteDefaultValue(InputSchema schema)
|
private void WriteDefaultValue(CommandInputSchema schema)
|
||||||
{
|
{
|
||||||
var defaultValue = context.CommandDefaultValues.GetValueOrDefault(schema);
|
var defaultValue = context.CommandDefaultValues.GetValueOrDefault(schema);
|
||||||
if (defaultValue is null)
|
if (defaultValue is null)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ internal class HelpContext(
|
|||||||
ApplicationMetadata applicationMetadata,
|
ApplicationMetadata applicationMetadata,
|
||||||
ApplicationSchema applicationSchema,
|
ApplicationSchema applicationSchema,
|
||||||
CommandSchema commandSchema,
|
CommandSchema commandSchema,
|
||||||
IReadOnlyDictionary<InputSchema, object?> commandDefaultValues
|
IReadOnlyDictionary<CommandInputSchema, object?> commandDefaultValues
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
public ApplicationMetadata ApplicationMetadata { get; } = applicationMetadata;
|
public ApplicationMetadata ApplicationMetadata { get; } = applicationMetadata;
|
||||||
@@ -16,6 +16,6 @@ internal class HelpContext(
|
|||||||
|
|
||||||
public CommandSchema CommandSchema { get; } = commandSchema;
|
public CommandSchema CommandSchema { get; } = commandSchema;
|
||||||
|
|
||||||
public IReadOnlyDictionary<InputSchema, object?> CommandDefaultValues { get; } =
|
public IReadOnlyDictionary<CommandInputSchema, object?> CommandDefaultValues { get; } =
|
||||||
commandDefaultValues;
|
commandDefaultValues;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,17 @@ namespace CliFx.Schema;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes an input of a command.
|
/// Describes an input of a command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class InputSchema(
|
public abstract class CommandInputSchema(
|
||||||
PropertyBinding property,
|
PropertyBinding property,
|
||||||
string? description,
|
string? description,
|
||||||
IBindingConverter converter,
|
IBindingConverter converter,
|
||||||
IReadOnlyList<IBindingValidator> validators
|
IReadOnlyList<IBindingValidator> validators
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
internal abstract string Kind { get; }
|
||||||
|
|
||||||
|
internal abstract string FormattedIdentifier { get; }
|
||||||
|
|
||||||
internal bool IsSequence { get; } =
|
internal bool IsSequence { get; } =
|
||||||
property.Type != typeof(string)
|
property.Type != typeof(string)
|
||||||
&& property.Type.TryGetEnumerableUnderlyingType() is not null;
|
&& property.Type.TryGetEnumerableUnderlyingType() is not null;
|
||||||
@@ -43,10 +47,6 @@ public abstract class InputSchema(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<IBindingValidator> Validators { get; } = validators;
|
public IReadOnlyList<IBindingValidator> Validators { get; } = validators;
|
||||||
|
|
||||||
internal abstract string GetKind();
|
|
||||||
|
|
||||||
internal abstract string GetFormattedIdentifier();
|
|
||||||
|
|
||||||
private void Validate(object? value)
|
private void Validate(object? value)
|
||||||
{
|
{
|
||||||
var errors = Validators
|
var errors = Validators
|
||||||
@@ -58,7 +58,7 @@ public abstract class InputSchema(
|
|||||||
{
|
{
|
||||||
throw CliFxException.UserError(
|
throw CliFxException.UserError(
|
||||||
$"""
|
$"""
|
||||||
{GetKind()} {GetFormattedIdentifier()} has been provided with an invalid value.
|
{Kind} {FormattedIdentifier} has been provided with an invalid value.
|
||||||
Error(s):
|
Error(s):
|
||||||
{errors.Select(e => "- " + e.Message).JoinToString(Environment.NewLine)}
|
{errors.Select(e => "- " + e.Message).JoinToString(Environment.NewLine)}
|
||||||
"""
|
"""
|
||||||
@@ -93,7 +93,7 @@ public abstract class InputSchema(
|
|||||||
{
|
{
|
||||||
throw CliFxException.UserError(
|
throw CliFxException.UserError(
|
||||||
$"""
|
$"""
|
||||||
{GetKind()} {GetFormattedIdentifier()} expects a single argument, but provided with multiple:
|
{Kind} {FormattedIdentifier} expects a single argument, but provided with multiple:
|
||||||
{rawInputs.Select(v => '<' + v + '>').JoinToString(" ")}
|
{rawInputs.Select(v => '<' + v + '>').JoinToString(" ")}
|
||||||
"""
|
"""
|
||||||
);
|
);
|
||||||
@@ -103,7 +103,7 @@ public abstract class InputSchema(
|
|||||||
{
|
{
|
||||||
throw CliFxException.UserError(
|
throw CliFxException.UserError(
|
||||||
$"""
|
$"""
|
||||||
{GetKind()} {GetFormattedIdentifier()} cannot be set from the provided argument(s):
|
{Kind} {FormattedIdentifier} cannot be set from the provided argument(s):
|
||||||
{rawInputs.Select(v => '<' + v + '>').JoinToString(" ")}
|
{rawInputs.Select(v => '<' + v + '>').JoinToString(" ")}
|
||||||
Error: {ex.Message}
|
Error: {ex.Message}
|
||||||
""",
|
""",
|
||||||
@@ -111,13 +111,18 @@ public abstract class InputSchema(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString() => FormattedIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of the type is used to simplify initialization from the source-generated code
|
/// <inheritdoc cref="CommandInputSchema" />
|
||||||
// and to enforce static references to all the types used in the binding.
|
/// <remarks>
|
||||||
// The non-generic version is used internally by the framework when operating in a dynamic context.
|
/// Generic version of the type is used to simplify initialization from source-generated code and
|
||||||
/// <inheritdoc cref="InputSchema" />
|
/// to enforce static references to all types used in the binding.
|
||||||
public abstract class InputSchema<
|
/// The non-generic version is used internally by the framework when operating in a dynamic context.
|
||||||
|
/// </remarks>
|
||||||
|
public abstract class CommandInputSchema<
|
||||||
TCommand,
|
TCommand,
|
||||||
[DynamicallyAccessedMembers(
|
[DynamicallyAccessedMembers(
|
||||||
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
||||||
@@ -128,5 +133,5 @@ public abstract class InputSchema<
|
|||||||
string? description,
|
string? description,
|
||||||
BindingConverter<TProperty> converter,
|
BindingConverter<TProperty> converter,
|
||||||
IReadOnlyList<BindingValidator<TProperty>> validators
|
IReadOnlyList<BindingValidator<TProperty>> validators
|
||||||
) : InputSchema(property, description, converter, validators)
|
) : CommandInputSchema(property, description, converter, validators)
|
||||||
where TCommand : ICommand;
|
where TCommand : ICommand;
|
||||||
@@ -9,7 +9,7 @@ namespace CliFx.Schema;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes an option input of a command.
|
/// Describes an option input of a command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OptionSchema(
|
public class CommandOptionSchema(
|
||||||
PropertyBinding property,
|
PropertyBinding property,
|
||||||
string? name,
|
string? name,
|
||||||
char? shortName,
|
char? shortName,
|
||||||
@@ -18,8 +18,38 @@ public class OptionSchema(
|
|||||||
string? description,
|
string? description,
|
||||||
IBindingConverter converter,
|
IBindingConverter converter,
|
||||||
IReadOnlyList<IBindingValidator> validators
|
IReadOnlyList<IBindingValidator> validators
|
||||||
) : InputSchema(property,description, converter, validators)
|
) : CommandInputSchema(property,description, converter, validators)
|
||||||
{
|
{
|
||||||
|
internal override string Kind => "Option";
|
||||||
|
|
||||||
|
internal override string FormattedIdentifier
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var buffer = new StringBuilder();
|
||||||
|
|
||||||
|
// Short name
|
||||||
|
if (ShortName is not null)
|
||||||
|
{
|
||||||
|
buffer.Append('-').Append(ShortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
if (!string.IsNullOrWhiteSpace(Name) && ShortName is not null)
|
||||||
|
{
|
||||||
|
buffer.Append('|');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name
|
||||||
|
if (!string.IsNullOrWhiteSpace(Name))
|
||||||
|
{
|
||||||
|
buffer.Append("--").Append(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Option name.
|
/// Option name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -53,40 +83,15 @@ public class OptionSchema(
|
|||||||
internal bool MatchesEnvironmentVariable(string environmentVariableName) =>
|
internal bool MatchesEnvironmentVariable(string environmentVariableName) =>
|
||||||
!string.IsNullOrWhiteSpace(EnvironmentVariable)
|
!string.IsNullOrWhiteSpace(EnvironmentVariable)
|
||||||
&& string.Equals(EnvironmentVariable, environmentVariableName, StringComparison.Ordinal);
|
&& string.Equals(EnvironmentVariable, environmentVariableName, StringComparison.Ordinal);
|
||||||
|
|
||||||
internal override string GetKind() => "Option";
|
|
||||||
|
|
||||||
internal override string GetFormattedIdentifier()
|
|
||||||
{
|
|
||||||
var buffer = new StringBuilder();
|
|
||||||
|
|
||||||
// Short name
|
|
||||||
if (ShortName is not null)
|
|
||||||
{
|
|
||||||
buffer.Append('-').Append(ShortName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Separator
|
|
||||||
if (!string.IsNullOrWhiteSpace(Name) && ShortName is not null)
|
|
||||||
{
|
|
||||||
buffer.Append('|');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name
|
|
||||||
if (!string.IsNullOrWhiteSpace(Name))
|
|
||||||
{
|
|
||||||
buffer.Append("--").Append(Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of the type is used to simplify initialization from the source-generated code
|
/// <inheritdoc cref="CommandOptionSchema" />
|
||||||
// and to enforce static references to all the types used in the binding.
|
/// <remarks>
|
||||||
// The non-generic version is used internally by the framework when operating in a dynamic context.
|
/// Generic version of the type is used to simplify initialization from source-generated code and
|
||||||
/// <inheritdoc cref="OptionSchema" />
|
/// to enforce static references to all types used in the binding.
|
||||||
public class OptionSchema<
|
/// The non-generic version is used internally by the framework when operating in a dynamic context.
|
||||||
|
/// </remarks>
|
||||||
|
public class CommandOptionSchema<
|
||||||
TCommand,
|
TCommand,
|
||||||
[DynamicallyAccessedMembers(
|
[DynamicallyAccessedMembers(
|
||||||
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
||||||
@@ -102,7 +107,7 @@ public class OptionSchema<
|
|||||||
BindingConverter<TProperty> converter,
|
BindingConverter<TProperty> converter,
|
||||||
IReadOnlyList<BindingValidator<TProperty>> validators
|
IReadOnlyList<BindingValidator<TProperty>> validators
|
||||||
)
|
)
|
||||||
: OptionSchema(
|
: CommandOptionSchema(
|
||||||
property,
|
property,
|
||||||
name,
|
name,
|
||||||
shortName,
|
shortName,
|
||||||
@@ -7,7 +7,7 @@ namespace CliFx.Schema;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a parameter input of a command.
|
/// Describes a parameter input of a command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ParameterSchema(
|
public class CommandParameterSchema(
|
||||||
PropertyBinding property,
|
PropertyBinding property,
|
||||||
int order,
|
int order,
|
||||||
string name,
|
string name,
|
||||||
@@ -15,8 +15,12 @@ public class ParameterSchema(
|
|||||||
string? description,
|
string? description,
|
||||||
IBindingConverter converter,
|
IBindingConverter converter,
|
||||||
IReadOnlyList<IBindingValidator> validators
|
IReadOnlyList<IBindingValidator> validators
|
||||||
) : InputSchema(property, description, converter, validators)
|
) : CommandInputSchema(property, description, converter, validators)
|
||||||
{
|
{
|
||||||
|
internal override string Kind => "Parameter";
|
||||||
|
|
||||||
|
internal override string FormattedIdentifier => IsSequence ? $"<{Name}>" : $"<{Name}...>";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Order, in which the parameter is bound from the command-line arguments.
|
/// Order, in which the parameter is bound from the command-line arguments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -31,17 +35,15 @@ public class ParameterSchema(
|
|||||||
/// Whether the parameter is required.
|
/// Whether the parameter is required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRequired { get; } = isRequired;
|
public bool IsRequired { get; } = isRequired;
|
||||||
|
|
||||||
internal override string GetKind() => "Parameter";
|
|
||||||
|
|
||||||
internal override string GetFormattedIdentifier() => IsSequence ? $"<{Name}>" : $"<{Name}...>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of the type is used to simplify initialization from the source-generated code
|
/// <inheritdoc cref="CommandParameterSchema" />
|
||||||
// and to enforce static references to all the types used in the binding.
|
/// <remarks>
|
||||||
// The non-generic version is used internally by the framework when operating in a dynamic context.
|
/// Generic version of the type is used to simplify initialization from source-generated code and
|
||||||
/// <inheritdoc cref="ParameterSchema" />
|
/// to enforce static references to all types used in the binding.
|
||||||
public class ParameterSchema<
|
/// The non-generic version is used internally by the framework when operating in a dynamic context.
|
||||||
|
/// </remarks>
|
||||||
|
public class CommandParameterSchema<
|
||||||
TCommand,
|
TCommand,
|
||||||
[DynamicallyAccessedMembers(
|
[DynamicallyAccessedMembers(
|
||||||
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicMethods
|
||||||
@@ -55,5 +57,5 @@ public class ParameterSchema<
|
|||||||
string? description,
|
string? description,
|
||||||
BindingConverter<TProperty> converter,
|
BindingConverter<TProperty> converter,
|
||||||
IReadOnlyList<BindingValidator<TProperty>> validators
|
IReadOnlyList<BindingValidator<TProperty>> validators
|
||||||
) : ParameterSchema(property, order, name, isRequired, description, converter, validators)
|
) : CommandParameterSchema(property, order, name, isRequired, description, converter, validators)
|
||||||
where TCommand : ICommand;
|
where TCommand : ICommand;
|
||||||
@@ -9,13 +9,13 @@ using CliFx.Utils.Extensions;
|
|||||||
namespace CliFx.Schema;
|
namespace CliFx.Schema;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes an individual command, along with its parameter and option inputs.
|
/// Describes an individual command, along with its inputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CommandSchema(
|
public class CommandSchema(
|
||||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type,
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type,
|
||||||
string? name,
|
string? name,
|
||||||
string? description,
|
string? description,
|
||||||
IReadOnlyList<InputSchema> inputs
|
IReadOnlyList<CommandInputSchema> inputs
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,29 +40,29 @@ public class CommandSchema(
|
|||||||
public string? Description { get; } = description;
|
public string? Description { get; } = description;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inputs (parameters and options) of the command.
|
/// Command inputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<InputSchema> Inputs { get; } = inputs;
|
public IReadOnlyList<CommandInputSchema> Inputs { get; } = inputs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parameter inputs of the command.
|
/// Parameter inputs of the command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<ParameterSchema> Parameters { get; } =
|
public IReadOnlyList<CommandParameterSchema> Parameters { get; } =
|
||||||
inputs.OfType<ParameterSchema>().ToArray();
|
inputs.OfType<CommandParameterSchema>().ToArray();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Option inputs of the command.
|
/// Option inputs of the command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<OptionSchema> Options { get; } = inputs.OfType<OptionSchema>().ToArray();
|
public IReadOnlyList<CommandOptionSchema> Options { get; } = inputs.OfType<CommandOptionSchema>().ToArray();
|
||||||
|
|
||||||
internal bool MatchesName(string? name) =>
|
internal bool MatchesName(string? name) =>
|
||||||
!string.IsNullOrWhiteSpace(Name)
|
!string.IsNullOrWhiteSpace(Name)
|
||||||
? string.Equals(name, Name, StringComparison.OrdinalIgnoreCase)
|
? string.Equals(name, Name, StringComparison.OrdinalIgnoreCase)
|
||||||
: string.IsNullOrWhiteSpace(name);
|
: string.IsNullOrWhiteSpace(name);
|
||||||
|
|
||||||
internal IReadOnlyDictionary<InputSchema, object?> GetValues(ICommand instance)
|
internal IReadOnlyDictionary<CommandInputSchema, object?> GetValues(ICommand instance)
|
||||||
{
|
{
|
||||||
var result = new Dictionary<InputSchema, object?>();
|
var result = new Dictionary<CommandInputSchema, object?>();
|
||||||
|
|
||||||
foreach (var parameterSchema in Parameters)
|
foreach (var parameterSchema in Parameters)
|
||||||
{
|
{
|
||||||
@@ -135,7 +135,7 @@ public class CommandSchema(
|
|||||||
$"""
|
$"""
|
||||||
Missing required parameter(s):
|
Missing required parameter(s):
|
||||||
{remainingRequiredParameterSchemas
|
{remainingRequiredParameterSchemas
|
||||||
.Select(p => p.GetFormattedIdentifier())
|
.Select(p => p.FormattedIdentifier)
|
||||||
.JoinToString(" ")}
|
.JoinToString(" ")}
|
||||||
"""
|
"""
|
||||||
);
|
);
|
||||||
@@ -208,7 +208,7 @@ public class CommandSchema(
|
|||||||
$"""
|
$"""
|
||||||
Missing required option(s):
|
Missing required option(s):
|
||||||
{remainingRequiredOptionSchemas
|
{remainingRequiredOptionSchemas
|
||||||
.Select(o => o.GetFormattedIdentifier())
|
.Select(o => o.FormattedIdentifier)
|
||||||
.JoinToString(", ")}
|
.JoinToString(", ")}
|
||||||
"""
|
"""
|
||||||
);
|
);
|
||||||
@@ -222,12 +222,14 @@ public class CommandSchema(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of the type is used to simplify initialization from the source-generated code
|
|
||||||
// and to enforce static references to all the types used in the binding.
|
|
||||||
// The non-generic version is used internally by the framework when operating in a dynamic context.
|
|
||||||
/// <inheritdoc cref="CommandSchema" />
|
/// <inheritdoc cref="CommandSchema" />
|
||||||
|
/// <remarks>
|
||||||
|
/// Generic version of the type is used to simplify initialization from source-generated code and
|
||||||
|
/// to enforce static references to all types used in the binding.
|
||||||
|
/// The non-generic version is used internally by the framework when operating in a dynamic context.
|
||||||
|
/// </remarks>
|
||||||
public class CommandSchema<
|
public class CommandSchema<
|
||||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCommand
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TCommand
|
||||||
>(string? name, string? description, IReadOnlyList<InputSchema> inputs)
|
>(string? name, string? description, IReadOnlyList<CommandInputSchema> inputs)
|
||||||
: CommandSchema(typeof(TCommand), name, description, inputs)
|
: CommandSchema(typeof(TCommand), name, description, inputs)
|
||||||
where TCommand : ICommand;
|
where TCommand : ICommand;
|
||||||
|
|||||||
@@ -55,10 +55,12 @@ public class PropertyBinding(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of the type is used to simplify initialization from the source-generated code
|
|
||||||
// and to enforce static references to all the types used in the binding.
|
|
||||||
// The non-generic version is used internally by the framework when operating in a dynamic context.
|
|
||||||
/// <inheritdoc cref="PropertyBinding" />
|
/// <inheritdoc cref="PropertyBinding" />
|
||||||
|
/// <remarks>
|
||||||
|
/// Generic version of the type is used to simplify initialization from source-generated code and
|
||||||
|
/// to enforce static references to all types used in the binding.
|
||||||
|
/// The non-generic version is used internally by the framework when operating in a dynamic context.
|
||||||
|
/// </remarks>
|
||||||
public class PropertyBinding<
|
public class PropertyBinding<
|
||||||
TObject,
|
TObject,
|
||||||
[DynamicallyAccessedMembers(
|
[DynamicallyAccessedMembers(
|
||||||
|
|||||||
Reference in New Issue
Block a user