mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 21:38:16 +08:00
fixed line-endings
This commit is contained in:

committed by
Patrik Svensson

parent
989c0b9904
commit
44300c871f
@ -1,4 +1,4 @@
|
||||
using Microsoft.CodeAnalysis.Editing;
|
||||
using Microsoft.CodeAnalysis.Editing;
|
||||
using Microsoft.CodeAnalysis.Simplification;
|
||||
|
||||
namespace Spectre.Console.Analyzer.CodeActions;
|
||||
@ -32,171 +32,171 @@ public class SwitchToAnsiConsoleAction : CodeAction
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var editor = await DocumentEditor.CreateAsync(_document, cancellationToken).ConfigureAwait(false);
|
||||
var compilation = editor.SemanticModel.Compilation;
|
||||
|
||||
var operation = editor.SemanticModel.GetOperation(_originalInvocation, cancellationToken) as IInvocationOperation;
|
||||
if (operation == null)
|
||||
{
|
||||
return _document;
|
||||
}
|
||||
|
||||
// If there is an IAnsiConsole passed into the method then we'll use it.
|
||||
// otherwise we'll check for a field level instance.
|
||||
// if neither of those exist we'll fall back to the static param.
|
||||
var spectreConsoleSymbol = compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole");
|
||||
var iansiConsoleSymbol = compilation.GetTypeByMetadataName("Spectre.Console.IAnsiConsole");
|
||||
|
||||
ISymbol? accessibleConsoleSymbol = spectreConsoleSymbol;
|
||||
if (iansiConsoleSymbol != null)
|
||||
{
|
||||
var isInStaticContext = IsInStaticContext(operation, cancellationToken, out var parentStaticMemberStartPosition);
|
||||
|
||||
foreach (var symbol in editor.SemanticModel.LookupSymbols(operation.Syntax.GetLocation().SourceSpan.Start))
|
||||
{
|
||||
// LookupSymbols check the accessibility of the symbol, but it can
|
||||
// suggest instance members when the current context is static.
|
||||
var symbolType = symbol switch
|
||||
{
|
||||
IParameterSymbol parameter => parameter.Type,
|
||||
IFieldSymbol field when !isInStaticContext || field.IsStatic => field.Type,
|
||||
IPropertySymbol { GetMethod: not null } property when !isInStaticContext || property.IsStatic => property.Type,
|
||||
ILocalSymbol local => local.Type,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// Locals can be returned even if there are not valid in the current context. For instance,
|
||||
// it can return locals declared after the current location. Or it can return locals that
|
||||
// should not be accessible in a static local function.
|
||||
//
|
||||
// void Sample()
|
||||
// {
|
||||
// int local = 0;
|
||||
// static void LocalFunction() => local; <-- local is invalid here but LookupSymbols suggests it
|
||||
// }
|
||||
//
|
||||
// Parameters from the ancestor methods or local functions are also returned even if the operation is in a static local function.
|
||||
if (symbol.Kind is SymbolKind.Local or SymbolKind.Parameter)
|
||||
{
|
||||
var localPosition = symbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(cancellationToken).GetLocation().SourceSpan.Start;
|
||||
|
||||
// The local is not part of the source tree
|
||||
if (localPosition == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The local is declared after the current expression
|
||||
if (localPosition > _originalInvocation.Span.Start)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The local is declared outside the static local function
|
||||
if (isInStaticContext && localPosition < parentStaticMemberStartPosition)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsOrImplementSymbol(symbolType, iansiConsoleSymbol))
|
||||
{
|
||||
accessibleConsoleSymbol = symbol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (accessibleConsoleSymbol == null)
|
||||
{
|
||||
return _document;
|
||||
}
|
||||
|
||||
// Replace the original invocation
|
||||
var generator = editor.Generator;
|
||||
var consoleExpression = accessibleConsoleSymbol switch
|
||||
{
|
||||
ITypeSymbol typeSymbol => generator.TypeExpression(typeSymbol, addImport: true).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation),
|
||||
_ => generator.IdentifierName(accessibleConsoleSymbol.Name),
|
||||
};
|
||||
|
||||
var newExpression = generator.InvocationExpression(generator.MemberAccessExpression(consoleExpression, operation.TargetMethod.Name), _originalInvocation.ArgumentList.Arguments)
|
||||
.WithLeadingTrivia(_originalInvocation.GetLeadingTrivia())
|
||||
.WithTrailingTrivia(_originalInvocation.GetTrailingTrivia());
|
||||
|
||||
editor.ReplaceNode(_originalInvocation, newExpression);
|
||||
|
||||
return editor.GetChangedDocument();
|
||||
}
|
||||
|
||||
private static bool IsOrImplementSymbol(ITypeSymbol? symbol, ITypeSymbol interfaceSymbol)
|
||||
{
|
||||
if (symbol == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SymbolEqualityComparer.Default.Equals(symbol, interfaceSymbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var iface in symbol.AllInterfaces)
|
||||
{
|
||||
if (SymbolEqualityComparer.Default.Equals(iface, interfaceSymbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsInStaticContext(IOperation operation, CancellationToken cancellationToken, out int parentStaticMemberStartPosition)
|
||||
{
|
||||
// Local functions can be nested, and an instance local function can be declared
|
||||
// in a static local function. So, you need to continue to check ancestors when a
|
||||
// local function is not static.
|
||||
foreach (var member in operation.Syntax.Ancestors())
|
||||
{
|
||||
if (member is LocalFunctionStatementSyntax localFunction)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetDeclaredSymbol(localFunction, cancellationToken);
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = localFunction.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is LambdaExpressionSyntax lambdaExpression)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetSymbolInfo(lambdaExpression, cancellationToken).Symbol;
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = lambdaExpression.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is AnonymousMethodExpressionSyntax anonymousMethod)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetSymbolInfo(anonymousMethod, cancellationToken).Symbol;
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = anonymousMethod.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is MethodDeclarationSyntax methodDeclaration)
|
||||
{
|
||||
parentStaticMemberStartPosition = methodDeclaration.GetLocation().SourceSpan.Start;
|
||||
|
||||
var symbol = operation.SemanticModel!.GetDeclaredSymbol(methodDeclaration, cancellationToken);
|
||||
return symbol != null && symbol.IsStatic;
|
||||
}
|
||||
}
|
||||
|
||||
parentStaticMemberStartPosition = -1;
|
||||
return false;
|
||||
{
|
||||
var editor = await DocumentEditor.CreateAsync(_document, cancellationToken).ConfigureAwait(false);
|
||||
var compilation = editor.SemanticModel.Compilation;
|
||||
|
||||
var operation = editor.SemanticModel.GetOperation(_originalInvocation, cancellationToken) as IInvocationOperation;
|
||||
if (operation == null)
|
||||
{
|
||||
return _document;
|
||||
}
|
||||
|
||||
// If there is an IAnsiConsole passed into the method then we'll use it.
|
||||
// otherwise we'll check for a field level instance.
|
||||
// if neither of those exist we'll fall back to the static param.
|
||||
var spectreConsoleSymbol = compilation.GetTypeByMetadataName("Spectre.Console.AnsiConsole");
|
||||
var iansiConsoleSymbol = compilation.GetTypeByMetadataName("Spectre.Console.IAnsiConsole");
|
||||
|
||||
ISymbol? accessibleConsoleSymbol = spectreConsoleSymbol;
|
||||
if (iansiConsoleSymbol != null)
|
||||
{
|
||||
var isInStaticContext = IsInStaticContext(operation, cancellationToken, out var parentStaticMemberStartPosition);
|
||||
|
||||
foreach (var symbol in editor.SemanticModel.LookupSymbols(operation.Syntax.GetLocation().SourceSpan.Start))
|
||||
{
|
||||
// LookupSymbols check the accessibility of the symbol, but it can
|
||||
// suggest instance members when the current context is static.
|
||||
var symbolType = symbol switch
|
||||
{
|
||||
IParameterSymbol parameter => parameter.Type,
|
||||
IFieldSymbol field when !isInStaticContext || field.IsStatic => field.Type,
|
||||
IPropertySymbol { GetMethod: not null } property when !isInStaticContext || property.IsStatic => property.Type,
|
||||
ILocalSymbol local => local.Type,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// Locals can be returned even if there are not valid in the current context. For instance,
|
||||
// it can return locals declared after the current location. Or it can return locals that
|
||||
// should not be accessible in a static local function.
|
||||
//
|
||||
// void Sample()
|
||||
// {
|
||||
// int local = 0;
|
||||
// static void LocalFunction() => local; <-- local is invalid here but LookupSymbols suggests it
|
||||
// }
|
||||
//
|
||||
// Parameters from the ancestor methods or local functions are also returned even if the operation is in a static local function.
|
||||
if (symbol.Kind is SymbolKind.Local or SymbolKind.Parameter)
|
||||
{
|
||||
var localPosition = symbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(cancellationToken).GetLocation().SourceSpan.Start;
|
||||
|
||||
// The local is not part of the source tree
|
||||
if (localPosition == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The local is declared after the current expression
|
||||
if (localPosition > _originalInvocation.Span.Start)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The local is declared outside the static local function
|
||||
if (isInStaticContext && localPosition < parentStaticMemberStartPosition)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsOrImplementSymbol(symbolType, iansiConsoleSymbol))
|
||||
{
|
||||
accessibleConsoleSymbol = symbol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (accessibleConsoleSymbol == null)
|
||||
{
|
||||
return _document;
|
||||
}
|
||||
|
||||
// Replace the original invocation
|
||||
var generator = editor.Generator;
|
||||
var consoleExpression = accessibleConsoleSymbol switch
|
||||
{
|
||||
ITypeSymbol typeSymbol => generator.TypeExpression(typeSymbol, addImport: true).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation),
|
||||
_ => generator.IdentifierName(accessibleConsoleSymbol.Name),
|
||||
};
|
||||
|
||||
var newExpression = generator.InvocationExpression(generator.MemberAccessExpression(consoleExpression, operation.TargetMethod.Name), _originalInvocation.ArgumentList.Arguments)
|
||||
.WithLeadingTrivia(_originalInvocation.GetLeadingTrivia())
|
||||
.WithTrailingTrivia(_originalInvocation.GetTrailingTrivia());
|
||||
|
||||
editor.ReplaceNode(_originalInvocation, newExpression);
|
||||
|
||||
return editor.GetChangedDocument();
|
||||
}
|
||||
|
||||
private static bool IsOrImplementSymbol(ITypeSymbol? symbol, ITypeSymbol interfaceSymbol)
|
||||
{
|
||||
if (symbol == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SymbolEqualityComparer.Default.Equals(symbol, interfaceSymbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var iface in symbol.AllInterfaces)
|
||||
{
|
||||
if (SymbolEqualityComparer.Default.Equals(iface, interfaceSymbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsInStaticContext(IOperation operation, CancellationToken cancellationToken, out int parentStaticMemberStartPosition)
|
||||
{
|
||||
// Local functions can be nested, and an instance local function can be declared
|
||||
// in a static local function. So, you need to continue to check ancestors when a
|
||||
// local function is not static.
|
||||
foreach (var member in operation.Syntax.Ancestors())
|
||||
{
|
||||
if (member is LocalFunctionStatementSyntax localFunction)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetDeclaredSymbol(localFunction, cancellationToken);
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = localFunction.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is LambdaExpressionSyntax lambdaExpression)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetSymbolInfo(lambdaExpression, cancellationToken).Symbol;
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = lambdaExpression.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is AnonymousMethodExpressionSyntax anonymousMethod)
|
||||
{
|
||||
var symbol = operation.SemanticModel!.GetSymbolInfo(anonymousMethod, cancellationToken).Symbol;
|
||||
if (symbol != null && symbol.IsStatic)
|
||||
{
|
||||
parentStaticMemberStartPosition = anonymousMethod.GetLocation().SourceSpan.Start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (member is MethodDeclarationSyntax methodDeclaration)
|
||||
{
|
||||
parentStaticMemberStartPosition = methodDeclaration.GetLocation().SourceSpan.Start;
|
||||
|
||||
var symbol = operation.SemanticModel!.GetDeclaredSymbol(methodDeclaration, cancellationToken);
|
||||
return symbol != null && symbol.IsStatic;
|
||||
}
|
||||
}
|
||||
|
||||
parentStaticMemberStartPosition = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using Spectre.Console.Cli.Internal.Configuration;
|
||||
|
||||
using Spectre.Console.Cli.Internal.Configuration;
|
||||
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Spectre.Console.Cli.Internal.Configuration;
|
||||
|
||||
using Spectre.Console.Cli.Internal.Configuration;
|
||||
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
/// <summary>
|
||||
@ -49,8 +49,8 @@ public sealed class CommandApp<TDefaultCommand> : ICommandApp
|
||||
public Task<int> RunAsync(IEnumerable<string> args)
|
||||
{
|
||||
return _app.RunAsync(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal Configurator GetConfigurator()
|
||||
{
|
||||
return _app.GetConfigurator();
|
||||
|
@ -5,40 +5,40 @@ namespace Spectre.Console.Cli;
|
||||
/// and <see cref="IConfigurator{TSettings}"/>.
|
||||
/// </summary>
|
||||
public static class ConfiguratorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="configurator">The configurator.</param>
|
||||
/// <param name="helpProvider">The help provider to use.</param>
|
||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||
public static IConfigurator SetHelpProvider(this IConfigurator configurator, IHelpProvider helpProvider)
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="configurator">The configurator.</param>
|
||||
/// <param name="helpProvider">The help provider to use.</param>
|
||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||
public static IConfigurator SetHelpProvider(this IConfigurator configurator, IHelpProvider helpProvider)
|
||||
{
|
||||
if (configurator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurator));
|
||||
}
|
||||
|
||||
configurator.SetHelpProvider(helpProvider);
|
||||
return configurator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="configurator">The configurator.</param>
|
||||
/// <typeparam name="T">The type of the help provider to instantiate at runtime and use.</typeparam>
|
||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||
public static IConfigurator SetHelpProvider<T>(this IConfigurator configurator)
|
||||
where T : IHelpProvider
|
||||
{
|
||||
}
|
||||
|
||||
configurator.SetHelpProvider(helpProvider);
|
||||
return configurator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="configurator">The configurator.</param>
|
||||
/// <typeparam name="T">The type of the help provider to instantiate at runtime and use.</typeparam>
|
||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||
public static IConfigurator SetHelpProvider<T>(this IConfigurator configurator)
|
||||
where T : IHelpProvider
|
||||
{
|
||||
if (configurator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurator));
|
||||
}
|
||||
|
||||
configurator.SetHelpProvider<T>();
|
||||
return configurator;
|
||||
}
|
||||
|
||||
configurator.SetHelpProvider<T>();
|
||||
return configurator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -11,22 +11,22 @@ namespace Spectre.Console.Cli.Help;
|
||||
public class HelpProvider : IHelpProvider
|
||||
{
|
||||
private HelpProviderResources resources;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating how many examples from direct children to show in the help text.
|
||||
/// </summary>
|
||||
protected virtual int MaximumIndirectExamples { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether any default values for command options are shown in the help text.
|
||||
/// </summary>
|
||||
protected virtual bool ShowOptionDefaultValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a trailing period of a command description is trimmed in the help text.
|
||||
/// </summary>
|
||||
protected virtual bool TrimTrailingPeriod { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating how many examples from direct children to show in the help text.
|
||||
/// </summary>
|
||||
protected virtual int MaximumIndirectExamples { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether any default values for command options are shown in the help text.
|
||||
/// </summary>
|
||||
protected virtual bool ShowOptionDefaultValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a trailing period of a command description is trimmed in the help text.
|
||||
/// </summary>
|
||||
protected virtual bool TrimTrailingPeriod { get; }
|
||||
|
||||
private sealed class HelpArgument
|
||||
{
|
||||
public string Name { get; }
|
||||
@ -74,14 +74,14 @@ public class HelpProvider : IHelpProvider
|
||||
public static IReadOnlyList<HelpOption> Get(ICommandInfo? command, HelpProviderResources resources)
|
||||
{
|
||||
var parameters = new List<HelpOption>();
|
||||
parameters.Add(new HelpOption("h", "help", null, null, resources.PrintHelpDescription, null));
|
||||
|
||||
// Version information applies to the entire application
|
||||
// Include the "-v" option in the help when at the root of the command line application
|
||||
// Don't allow the "-v" option if users have specified one or more sub-commands
|
||||
if ((command == null || command?.Parent == null) && !(command?.IsBranch ?? false))
|
||||
{
|
||||
parameters.Add(new HelpOption("v", "version", null, null, resources.PrintVersionDescription, null));
|
||||
parameters.Add(new HelpOption("h", "help", null, null, resources.PrintHelpDescription, null));
|
||||
|
||||
// Version information applies to the entire application
|
||||
// Include the "-v" option in the help when at the root of the command line application
|
||||
// Don't allow the "-v" option if users have specified one or more sub-commands
|
||||
if ((command == null || command?.Parent == null) && !(command?.IsBranch ?? false))
|
||||
{
|
||||
parameters.Add(new HelpOption("v", "version", null, null, resources.PrintVersionDescription, null));
|
||||
}
|
||||
|
||||
parameters.AddRange(command?.Parameters.OfType<ICommandOption>().Where(o => !o.IsHidden).Select(o =>
|
||||
@ -92,55 +92,55 @@ public class HelpProvider : IHelpProvider
|
||||
?? Array.Empty<HelpOption>());
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HelpProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The command line application settings used for configuration.</param>
|
||||
public HelpProvider(ICommandAppSettings settings)
|
||||
{
|
||||
this.ShowOptionDefaultValues = settings.ShowOptionDefaultValues;
|
||||
this.MaximumIndirectExamples = settings.MaximumIndirectExamples;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HelpProvider"/> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The command line application settings used for configuration.</param>
|
||||
public HelpProvider(ICommandAppSettings settings)
|
||||
{
|
||||
this.ShowOptionDefaultValues = settings.ShowOptionDefaultValues;
|
||||
this.MaximumIndirectExamples = settings.MaximumIndirectExamples;
|
||||
this.TrimTrailingPeriod = settings.TrimTrailingPeriod;
|
||||
|
||||
resources = new HelpProviderResources(settings.Culture);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
resources = new HelpProviderResources(settings.Culture);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual IEnumerable<IRenderable> Write(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
var result = new List<IRenderable>();
|
||||
|
||||
result.AddRange(GetHeader(model, command));
|
||||
var result = new List<IRenderable>();
|
||||
|
||||
result.AddRange(GetHeader(model, command));
|
||||
result.AddRange(GetDescription(model, command));
|
||||
result.AddRange(GetUsage(model, command));
|
||||
result.AddRange(GetExamples(model, command));
|
||||
result.AddRange(GetArguments(model, command));
|
||||
result.AddRange(GetOptions(model, command));
|
||||
result.AddRange(GetCommands(model, command));
|
||||
result.AddRange(GetCommands(model, command));
|
||||
result.AddRange(GetFooter(model, command));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the header for the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the header for the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetHeader(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetDescription(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
if (command?.Description == null)
|
||||
@ -152,14 +152,14 @@ public class HelpProvider : IHelpProvider
|
||||
composer.Style("yellow", $"{resources.Description}:").LineBreak();
|
||||
composer.Text(command.Description).LineBreak();
|
||||
yield return composer.LineBreak();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the usage section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the usage section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetUsage(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
var composer = new Composer();
|
||||
@ -219,26 +219,26 @@ public class HelpProvider : IHelpProvider
|
||||
}
|
||||
|
||||
if (command.IsBranch && command.DefaultCommand == null)
|
||||
{
|
||||
{
|
||||
// The user must specify the command
|
||||
parameters.Add($"[aqua]<{resources.Command}>[/]");
|
||||
}
|
||||
else if (command.IsBranch && command.DefaultCommand != null && command.Commands.Count > 0)
|
||||
{
|
||||
// We are on a branch with a default command
|
||||
}
|
||||
else if (command.IsBranch && command.DefaultCommand != null && command.Commands.Count > 0)
|
||||
{
|
||||
// We are on a branch with a default command
|
||||
// The user can optionally specify the command
|
||||
parameters.Add($"[aqua][[{resources.Command}]][/]");
|
||||
}
|
||||
else if (command.IsDefaultCommand)
|
||||
{
|
||||
var commands = model.Commands.Where(x => !x.IsHidden && !x.IsDefaultCommand).ToList();
|
||||
|
||||
if (commands.Count > 0)
|
||||
{
|
||||
// Commands other than the default are present
|
||||
// So make these optional in the usage statement
|
||||
parameters.Add($"[aqua][[{resources.Command}]][/]");
|
||||
}
|
||||
parameters.Add($"[aqua][[{resources.Command}]][/]");
|
||||
}
|
||||
else if (command.IsDefaultCommand)
|
||||
{
|
||||
var commands = model.Commands.Where(x => !x.IsHidden && !x.IsDefaultCommand).ToList();
|
||||
|
||||
if (commands.Count > 0)
|
||||
{
|
||||
// Commands other than the default are present
|
||||
// So make these optional in the usage statement
|
||||
parameters.Add($"[aqua][[{resources.Command}]][/]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,19 +249,19 @@ public class HelpProvider : IHelpProvider
|
||||
{
|
||||
composer,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the examples section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
/// <remarks>
|
||||
/// Examples from the command's direct children are used
|
||||
/// if no examples have been set on the specified command or model.
|
||||
/// </remarks>
|
||||
public virtual IEnumerable<IRenderable> GetExamples(ICommandModel model, ICommandInfo? command)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the examples section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
/// <remarks>
|
||||
/// Examples from the command's direct children are used
|
||||
/// if no examples have been set on the specified command or model.
|
||||
/// </remarks>
|
||||
public virtual IEnumerable<IRenderable> GetExamples(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
var maxExamples = int.MaxValue;
|
||||
|
||||
@ -272,12 +272,12 @@ public class HelpProvider : IHelpProvider
|
||||
// make sure that we limit the number of examples.
|
||||
maxExamples = MaximumIndirectExamples;
|
||||
|
||||
// Start at the current command (if exists)
|
||||
// or alternatively commence at the model.
|
||||
// Start at the current command (if exists)
|
||||
// or alternatively commence at the model.
|
||||
var commandContainer = command ?? (ICommandContainer)model;
|
||||
var queue = new Queue<ICommandContainer>(new[] { commandContainer });
|
||||
|
||||
// Traverse the command tree and look for examples.
|
||||
// Traverse the command tree and look for examples.
|
||||
// As soon as a node contains commands, bail.
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
@ -317,14 +317,14 @@ public class HelpProvider : IHelpProvider
|
||||
}
|
||||
|
||||
return Array.Empty<IRenderable>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetArguments(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
var arguments = HelpArgument.Get(command);
|
||||
@ -361,13 +361,13 @@ public class HelpProvider : IHelpProvider
|
||||
result.Add(grid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetOptions(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
@ -469,18 +469,18 @@ public class HelpProvider : IHelpProvider
|
||||
result.Add(grid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the commands section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the commands section of the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetCommands(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
var commandContainer = command ?? (ICommandContainer)model;
|
||||
bool isDefaultCommand = command?.IsDefaultCommand ?? false;
|
||||
{
|
||||
var commandContainer = command ?? (ICommandContainer)model;
|
||||
bool isDefaultCommand = command?.IsDefaultCommand ?? false;
|
||||
|
||||
var commands = isDefaultCommand ? model.Commands : commandContainer.Commands;
|
||||
commands = commands.Where(x => !x.IsHidden).ToList();
|
||||
@ -530,16 +530,16 @@ public class HelpProvider : IHelpProvider
|
||||
result.Add(grid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the footer for the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the footer for the help information.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects.</returns>
|
||||
public virtual IEnumerable<IRenderable> GetFooter(ICommandModel model, ICommandInfo? command)
|
||||
{
|
||||
yield break;
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ namespace Spectre.Console.Cli.Help;
|
||||
/// Represents a command container.
|
||||
/// </summary>
|
||||
public interface ICommandContainer
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all the examples for the container.
|
||||
/// </summary>
|
||||
|
@ -1,42 +1,42 @@
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an executable command.
|
||||
/// </summary>
|
||||
public interface ICommandInfo : ICommandContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the command.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the command.
|
||||
/// </summary>
|
||||
string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is a branch.
|
||||
/// </summary>
|
||||
bool IsBranch { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is the default command within its container.
|
||||
/// </summary>
|
||||
bool IsDefaultCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is hidden.
|
||||
/// </summary>
|
||||
bool IsHidden { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters associated with the command.
|
||||
/// </summary>
|
||||
IReadOnlyList<ICommandParameter> Parameters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent command, if any.
|
||||
/// </summary>
|
||||
ICommandInfo? Parent { get; }
|
||||
/// <summary>
|
||||
/// Represents an executable command.
|
||||
/// </summary>
|
||||
public interface ICommandInfo : ICommandContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the command.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the command.
|
||||
/// </summary>
|
||||
string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is a branch.
|
||||
/// </summary>
|
||||
bool IsBranch { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is the default command within its container.
|
||||
/// </summary>
|
||||
bool IsDefaultCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the command is hidden.
|
||||
/// </summary>
|
||||
bool IsHidden { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters associated with the command.
|
||||
/// </summary>
|
||||
IReadOnlyList<ICommandParameter> Parameters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent command, if any.
|
||||
/// </summary>
|
||||
ICommandInfo? Parent { get; }
|
||||
}
|
@ -1,23 +1,23 @@
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
internal static class ICommandInfoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Walks up the command.Parent tree, adding each command into a list as it goes.
|
||||
/// </summary>
|
||||
/// <remarks>The first command added to the list is the current (ie. this one).</remarks>
|
||||
/// <returns>The list of commands from current to root, as traversed by <see cref="CommandInfo.Parent"/>.</returns>
|
||||
public static List<ICommandInfo> Flatten(this ICommandInfo commandInfo)
|
||||
{
|
||||
var result = new Stack<Help.ICommandInfo>();
|
||||
|
||||
var current = commandInfo;
|
||||
while (current != null)
|
||||
{
|
||||
result.Push(current);
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
}
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
internal static class ICommandInfoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Walks up the command.Parent tree, adding each command into a list as it goes.
|
||||
/// </summary>
|
||||
/// <remarks>The first command added to the list is the current (ie. this one).</remarks>
|
||||
/// <returns>The list of commands from current to root, as traversed by <see cref="CommandInfo.Parent"/>.</returns>
|
||||
public static List<ICommandInfo> Flatten(this ICommandInfo commandInfo)
|
||||
{
|
||||
var result = new Stack<Help.ICommandInfo>();
|
||||
|
||||
var current = commandInfo;
|
||||
while (current != null)
|
||||
{
|
||||
result.Push(current);
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a command option.
|
||||
/// </summary>
|
||||
public interface ICommandOption : ICommandParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the long names of the option.
|
||||
/// </summary>
|
||||
IReadOnlyList<string> LongNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the short names of the option.
|
||||
/// </summary>
|
||||
IReadOnlyList<string> ShortNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value name of the option, if applicable.
|
||||
/// </summary>
|
||||
string? ValueName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the option value is optional.
|
||||
/// </summary>
|
||||
bool ValueIsOptional { get; }
|
||||
/// <summary>
|
||||
/// Represents a command option.
|
||||
/// </summary>
|
||||
public interface ICommandOption : ICommandParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the long names of the option.
|
||||
/// </summary>
|
||||
IReadOnlyList<string> LongNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the short names of the option.
|
||||
/// </summary>
|
||||
IReadOnlyList<string> ShortNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value name of the option, if applicable.
|
||||
/// </summary>
|
||||
string? ValueName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the option value is optional.
|
||||
/// </summary>
|
||||
bool ValueIsOptional { get; }
|
||||
}
|
@ -1,32 +1,32 @@
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a command parameter.
|
||||
/// </summary>
|
||||
public interface ICommandParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is a flag.
|
||||
/// </summary>
|
||||
bool IsFlag { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is required.
|
||||
/// </summary>
|
||||
bool Required { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the parameter.
|
||||
/// </summary>
|
||||
string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default value of the parameter, if specified.
|
||||
/// </summary>
|
||||
DefaultValueAttribute? DefaultValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is hidden.
|
||||
/// </summary>
|
||||
bool IsHidden { get; }
|
||||
/// <summary>
|
||||
/// Represents a command parameter.
|
||||
/// </summary>
|
||||
public interface ICommandParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is a flag.
|
||||
/// </summary>
|
||||
bool IsFlag { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is required.
|
||||
/// </summary>
|
||||
bool Required { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the parameter.
|
||||
/// </summary>
|
||||
string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default value of the parameter, if specified.
|
||||
/// </summary>
|
||||
DefaultValueAttribute? DefaultValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the parameter is hidden.
|
||||
/// </summary>
|
||||
bool IsHidden { get; }
|
||||
}
|
@ -1,20 +1,20 @@
|
||||
namespace Spectre.Console.Cli.Help;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The help provider interface for Spectre.Console.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations of this interface are responsbile
|
||||
/// for writing command help to the terminal when the
|
||||
/// `-h` or `--help` has been specified on the command line.
|
||||
/// The help provider interface for Spectre.Console.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations of this interface are responsbile
|
||||
/// for writing command help to the terminal when the
|
||||
/// `-h` or `--help` has been specified on the command line.
|
||||
/// </remarks>
|
||||
public interface IHelpProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes help information for the application.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects representing the help information.</returns>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes help information for the application.
|
||||
/// </summary>
|
||||
/// <param name="model">The command model to write help for.</param>
|
||||
/// <param name="command">The command for which to write help information (optional).</param>
|
||||
/// <returns>An enumerable collection of <see cref="IRenderable"/> objects representing the help information.</returns>
|
||||
IEnumerable<IRenderable> Write(ICommandModel model, ICommandInfo? command);
|
||||
}
|
||||
|
@ -24,22 +24,22 @@ public interface ICommandAppSettings
|
||||
/// <summary>
|
||||
/// Gets or sets the application version (use it to override auto-detected value).
|
||||
/// </summary>
|
||||
string? ApplicationVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating how many examples from direct children to show in the help text.
|
||||
/// </summary>
|
||||
int MaximumIndirectExamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether any default values for command options are shown in the help text.
|
||||
/// </summary>
|
||||
bool ShowOptionDefaultValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether a trailing period of a command description is trimmed in the help text.
|
||||
/// </summary>
|
||||
bool TrimTrailingPeriod { get; set; }
|
||||
string? ApplicationVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating how many examples from direct children to show in the help text.
|
||||
/// </summary>
|
||||
int MaximumIndirectExamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether any default values for command options are shown in the help text.
|
||||
/// </summary>
|
||||
bool ShowOptionDefaultValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether a trailing period of a command description is trimmed in the help text.
|
||||
/// </summary>
|
||||
bool TrimTrailingPeriod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IAnsiConsole"/>.
|
||||
@ -65,14 +65,14 @@ public interface ICommandAppSettings
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not parsing is strict.
|
||||
/// </summary>
|
||||
bool StrictParsing { get; set; }
|
||||
|
||||
bool StrictParsing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not flags found on the commnd line
|
||||
/// that would normally result in a <see cref="CommandParseException"/> being thrown
|
||||
/// during parsing with the message "Flags cannot be assigned a value."
|
||||
/// Gets or sets a value indicating whether or not flags found on the commnd line
|
||||
/// that would normally result in a <see cref="CommandParseException"/> being thrown
|
||||
/// during parsing with the message "Flags cannot be assigned a value."
|
||||
/// should instead be added to the remaining arguments collection.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
bool ConvertFlagsToRemainingArguments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -4,19 +4,19 @@ namespace Spectre.Console.Cli;
|
||||
/// Represents a configurator.
|
||||
/// </summary>
|
||||
public interface IConfigurator
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="helpProvider">The help provider to use.</param>
|
||||
public void SetHelpProvider(IHelpProvider helpProvider);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the help provider to instantiate at runtime and use.</typeparam>
|
||||
public void SetHelpProvider<T>()
|
||||
where T : IHelpProvider;
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <param name="helpProvider">The help provider to use.</param>
|
||||
public void SetHelpProvider(IHelpProvider helpProvider);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the help provider for the application.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the help provider to instantiate at runtime and use.</typeparam>
|
||||
public void SetHelpProvider<T>()
|
||||
where T : IHelpProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command app settings.
|
||||
@ -66,5 +66,5 @@ public interface IConfigurator
|
||||
/// <param name="action">The command branch configurator.</param>
|
||||
/// <returns>A branch configurator that can be used to configure the branch further.</returns>
|
||||
IBranchConfigurator AddBranch<TSettings>(string name, Action<IConfigurator<TSettings>> action)
|
||||
where TSettings : CommandSettings;
|
||||
where TSettings : CommandSettings;
|
||||
}
|
@ -1,146 +1,146 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
internal sealed class CommandExecutor
|
||||
{
|
||||
private readonly ITypeRegistrar _registrar;
|
||||
|
||||
public CommandExecutor(ITypeRegistrar registrar)
|
||||
{
|
||||
_registrar = registrar ?? throw new ArgumentNullException(nameof(registrar));
|
||||
_registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor));
|
||||
}
|
||||
|
||||
public async Task<int> Execute(IConfiguration configuration, IEnumerable<string> args)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
args ??= new List<string>();
|
||||
|
||||
_registrar.RegisterInstance(typeof(IConfiguration), configuration);
|
||||
_registrar.RegisterLazy(typeof(IAnsiConsole), () => configuration.Settings.Console.GetConsole());
|
||||
|
||||
// Create the command model.
|
||||
var model = CommandModelBuilder.Build(configuration);
|
||||
_registrar.RegisterInstance(typeof(CommandModel), model);
|
||||
_registrar.RegisterDependencies(model);
|
||||
|
||||
// Asking for version? Kind of a hack, but it's alright.
|
||||
// We should probably make this a bit better in the future.
|
||||
if (args.Contains("-v") || args.Contains("--version"))
|
||||
{
|
||||
var console = configuration.Settings.Console.GetConsole();
|
||||
console.WriteLine(ResolveApplicationVersion(configuration));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse and map the model against the arguments.
|
||||
var parsedResult = ParseCommandLineArguments(model, configuration.Settings, args);
|
||||
|
||||
// Register the arguments with the container.
|
||||
_registrar.RegisterInstance(typeof(CommandTreeParserResult), parsedResult);
|
||||
_registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining);
|
||||
|
||||
// Create the resolver.
|
||||
using (var resolver = new TypeResolverAdapter(_registrar.Build()))
|
||||
{
|
||||
// Get the registered help provider, falling back to the default provider
|
||||
// if no custom implementations have been registered.
|
||||
var helpProviders = resolver.Resolve(typeof(IEnumerable<IHelpProvider>)) as IEnumerable<IHelpProvider>;
|
||||
var helpProvider = helpProviders?.LastOrDefault() ?? new HelpProvider(configuration.Settings);
|
||||
|
||||
// Currently the root?
|
||||
if (parsedResult?.Tree == null)
|
||||
{
|
||||
// Display help.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, null));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the command to execute.
|
||||
var leaf = parsedResult.Tree.GetLeafCommand();
|
||||
if (leaf.Command.IsBranch || leaf.ShowHelp)
|
||||
{
|
||||
// Branches can't be executed. Show help.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command));
|
||||
return leaf.ShowHelp ? 0 : 1;
|
||||
}
|
||||
|
||||
// Is this the default and is it called without arguments when there are required arguments?
|
||||
if (leaf.Command.IsDefaultCommand && args.Count() == 0 && leaf.Command.Parameters.Any(p => p.Required))
|
||||
{
|
||||
// Display help for default command.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the content.
|
||||
var context = new CommandContext(parsedResult.Remaining, leaf.Command.Name, leaf.Command.Data);
|
||||
|
||||
// Execute the command tree.
|
||||
return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
private CommandTreeParserResult ParseCommandLineArguments(CommandModel model, CommandAppSettings settings, IEnumerable<string> args)
|
||||
{
|
||||
var parser = new CommandTreeParser(model, settings.CaseSensitivity, settings.ParsingMode, settings.ConvertFlagsToRemainingArguments);
|
||||
|
||||
var parserContext = new CommandTreeParserContext(args, settings.ParsingMode);
|
||||
var tokenizerResult = CommandTreeTokenizer.Tokenize(args);
|
||||
var parsedResult = parser.Parse(parserContext, tokenizerResult);
|
||||
|
||||
var lastParsedLeaf = parsedResult?.Tree?.GetLeafCommand();
|
||||
var lastParsedCommand = lastParsedLeaf?.Command;
|
||||
if (lastParsedLeaf != null && lastParsedCommand != null &&
|
||||
lastParsedCommand.IsBranch && !lastParsedLeaf.ShowHelp &&
|
||||
lastParsedCommand.DefaultCommand != null)
|
||||
{
|
||||
// Insert this branch's default command into the command line
|
||||
// arguments and try again to see if it will parse.
|
||||
var argsWithDefaultCommand = new List<string>(args);
|
||||
|
||||
argsWithDefaultCommand.Insert(tokenizerResult.Tokens.Position, lastParsedCommand.DefaultCommand.Name);
|
||||
|
||||
parserContext = new CommandTreeParserContext(argsWithDefaultCommand, settings.ParsingMode);
|
||||
tokenizerResult = CommandTreeTokenizer.Tokenize(argsWithDefaultCommand);
|
||||
parsedResult = parser.Parse(parserContext, tokenizerResult);
|
||||
}
|
||||
|
||||
return parsedResult;
|
||||
}
|
||||
#pragma warning restore CS8603 // Possible null reference return.
|
||||
|
||||
private static string ResolveApplicationVersion(IConfiguration configuration)
|
||||
{
|
||||
return
|
||||
configuration.Settings.ApplicationVersion ?? // potential override
|
||||
VersionHelper.GetVersion(Assembly.GetEntryAssembly());
|
||||
}
|
||||
|
||||
private static Task<int> Execute(
|
||||
CommandTree leaf,
|
||||
CommandTree tree,
|
||||
CommandContext context,
|
||||
ITypeResolver resolver,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
// Bind the command tree against the settings.
|
||||
var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver);
|
||||
configuration.Settings.Interceptor?.Intercept(context, settings);
|
||||
|
||||
// Create and validate the command.
|
||||
var command = leaf.CreateCommand(resolver);
|
||||
var validationResult = command.Validate(context, settings);
|
||||
if (!validationResult.Successful)
|
||||
{
|
||||
throw CommandRuntimeException.ValidationFailed(validationResult);
|
||||
}
|
||||
|
||||
// Execute the command.
|
||||
return command.Execute(context, settings);
|
||||
}
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
internal sealed class CommandExecutor
|
||||
{
|
||||
private readonly ITypeRegistrar _registrar;
|
||||
|
||||
public CommandExecutor(ITypeRegistrar registrar)
|
||||
{
|
||||
_registrar = registrar ?? throw new ArgumentNullException(nameof(registrar));
|
||||
_registrar.Register(typeof(DefaultPairDeconstructor), typeof(DefaultPairDeconstructor));
|
||||
}
|
||||
|
||||
public async Task<int> Execute(IConfiguration configuration, IEnumerable<string> args)
|
||||
{
|
||||
if (configuration == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
args ??= new List<string>();
|
||||
|
||||
_registrar.RegisterInstance(typeof(IConfiguration), configuration);
|
||||
_registrar.RegisterLazy(typeof(IAnsiConsole), () => configuration.Settings.Console.GetConsole());
|
||||
|
||||
// Create the command model.
|
||||
var model = CommandModelBuilder.Build(configuration);
|
||||
_registrar.RegisterInstance(typeof(CommandModel), model);
|
||||
_registrar.RegisterDependencies(model);
|
||||
|
||||
// Asking for version? Kind of a hack, but it's alright.
|
||||
// We should probably make this a bit better in the future.
|
||||
if (args.Contains("-v") || args.Contains("--version"))
|
||||
{
|
||||
var console = configuration.Settings.Console.GetConsole();
|
||||
console.WriteLine(ResolveApplicationVersion(configuration));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse and map the model against the arguments.
|
||||
var parsedResult = ParseCommandLineArguments(model, configuration.Settings, args);
|
||||
|
||||
// Register the arguments with the container.
|
||||
_registrar.RegisterInstance(typeof(CommandTreeParserResult), parsedResult);
|
||||
_registrar.RegisterInstance(typeof(IRemainingArguments), parsedResult.Remaining);
|
||||
|
||||
// Create the resolver.
|
||||
using (var resolver = new TypeResolverAdapter(_registrar.Build()))
|
||||
{
|
||||
// Get the registered help provider, falling back to the default provider
|
||||
// if no custom implementations have been registered.
|
||||
var helpProviders = resolver.Resolve(typeof(IEnumerable<IHelpProvider>)) as IEnumerable<IHelpProvider>;
|
||||
var helpProvider = helpProviders?.LastOrDefault() ?? new HelpProvider(configuration.Settings);
|
||||
|
||||
// Currently the root?
|
||||
if (parsedResult?.Tree == null)
|
||||
{
|
||||
// Display help.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, null));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the command to execute.
|
||||
var leaf = parsedResult.Tree.GetLeafCommand();
|
||||
if (leaf.Command.IsBranch || leaf.ShowHelp)
|
||||
{
|
||||
// Branches can't be executed. Show help.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command));
|
||||
return leaf.ShowHelp ? 0 : 1;
|
||||
}
|
||||
|
||||
// Is this the default and is it called without arguments when there are required arguments?
|
||||
if (leaf.Command.IsDefaultCommand && args.Count() == 0 && leaf.Command.Parameters.Any(p => p.Required))
|
||||
{
|
||||
// Display help for default command.
|
||||
configuration.Settings.Console.SafeRender(helpProvider.Write(model, leaf.Command));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the content.
|
||||
var context = new CommandContext(parsedResult.Remaining, leaf.Command.Name, leaf.Command.Data);
|
||||
|
||||
// Execute the command tree.
|
||||
return await Execute(leaf, parsedResult.Tree, context, resolver, configuration).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
private CommandTreeParserResult ParseCommandLineArguments(CommandModel model, CommandAppSettings settings, IEnumerable<string> args)
|
||||
{
|
||||
var parser = new CommandTreeParser(model, settings.CaseSensitivity, settings.ParsingMode, settings.ConvertFlagsToRemainingArguments);
|
||||
|
||||
var parserContext = new CommandTreeParserContext(args, settings.ParsingMode);
|
||||
var tokenizerResult = CommandTreeTokenizer.Tokenize(args);
|
||||
var parsedResult = parser.Parse(parserContext, tokenizerResult);
|
||||
|
||||
var lastParsedLeaf = parsedResult?.Tree?.GetLeafCommand();
|
||||
var lastParsedCommand = lastParsedLeaf?.Command;
|
||||
if (lastParsedLeaf != null && lastParsedCommand != null &&
|
||||
lastParsedCommand.IsBranch && !lastParsedLeaf.ShowHelp &&
|
||||
lastParsedCommand.DefaultCommand != null)
|
||||
{
|
||||
// Insert this branch's default command into the command line
|
||||
// arguments and try again to see if it will parse.
|
||||
var argsWithDefaultCommand = new List<string>(args);
|
||||
|
||||
argsWithDefaultCommand.Insert(tokenizerResult.Tokens.Position, lastParsedCommand.DefaultCommand.Name);
|
||||
|
||||
parserContext = new CommandTreeParserContext(argsWithDefaultCommand, settings.ParsingMode);
|
||||
tokenizerResult = CommandTreeTokenizer.Tokenize(argsWithDefaultCommand);
|
||||
parsedResult = parser.Parse(parserContext, tokenizerResult);
|
||||
}
|
||||
|
||||
return parsedResult;
|
||||
}
|
||||
#pragma warning restore CS8603 // Possible null reference return.
|
||||
|
||||
private static string ResolveApplicationVersion(IConfiguration configuration)
|
||||
{
|
||||
return
|
||||
configuration.Settings.ApplicationVersion ?? // potential override
|
||||
VersionHelper.GetVersion(Assembly.GetEntryAssembly());
|
||||
}
|
||||
|
||||
private static Task<int> Execute(
|
||||
CommandTree leaf,
|
||||
CommandTree tree,
|
||||
CommandContext context,
|
||||
ITypeResolver resolver,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
// Bind the command tree against the settings.
|
||||
var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver);
|
||||
configuration.Settings.Interceptor?.Intercept(context, settings);
|
||||
|
||||
// Create and validate the command.
|
||||
var command = leaf.CreateCommand(resolver);
|
||||
var validationResult = command.Validate(context, settings);
|
||||
if (!validationResult.Successful)
|
||||
{
|
||||
throw CommandRuntimeException.ValidationFailed(validationResult);
|
||||
}
|
||||
|
||||
// Execute the command.
|
||||
return command.Execute(context, settings);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
internal sealed class BranchConfigurator : IBranchConfigurator
|
||||
{
|
||||
|
@ -5,16 +5,16 @@ internal sealed class CommandAppSettings : ICommandAppSettings
|
||||
public CultureInfo? Culture { get; set; }
|
||||
public string? ApplicationName { get; set; }
|
||||
public string? ApplicationVersion { get; set; }
|
||||
public int MaximumIndirectExamples { get; set; }
|
||||
public bool ShowOptionDefaultValues { get; set; }
|
||||
public int MaximumIndirectExamples { get; set; }
|
||||
public bool ShowOptionDefaultValues { get; set; }
|
||||
public IAnsiConsole? Console { get; set; }
|
||||
public ICommandInterceptor? Interceptor { get; set; }
|
||||
public ITypeRegistrarFrontend Registrar { get; set; }
|
||||
public CaseSensitivity CaseSensitivity { get; set; }
|
||||
public bool PropagateExceptions { get; set; }
|
||||
public bool ValidateExamples { get; set; }
|
||||
public bool TrimTrailingPeriod { get; set; } = true;
|
||||
public bool StrictParsing { get; set; }
|
||||
public bool TrimTrailingPeriod { get; set; } = true;
|
||||
public bool StrictParsing { get; set; }
|
||||
public bool ConvertFlagsToRemainingArguments { get; set; } = false;
|
||||
|
||||
public ParsingMode ParsingMode =>
|
||||
@ -26,7 +26,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings
|
||||
{
|
||||
Registrar = new TypeRegistrar(registrar);
|
||||
CaseSensitivity = CaseSensitivity.All;
|
||||
ShowOptionDefaultValues = true;
|
||||
ShowOptionDefaultValues = true;
|
||||
MaximumIndirectExamples = 5;
|
||||
}
|
||||
|
||||
|
@ -19,19 +19,19 @@ internal sealed class Configurator : IUnsafeConfigurator, IConfigurator, IConfig
|
||||
Settings = new CommandAppSettings(registrar);
|
||||
Examples = new List<string[]>();
|
||||
}
|
||||
|
||||
public void SetHelpProvider(IHelpProvider helpProvider)
|
||||
{
|
||||
// Register the help provider
|
||||
_registrar.RegisterInstance(typeof(IHelpProvider), helpProvider);
|
||||
}
|
||||
|
||||
public void SetHelpProvider<T>()
|
||||
where T : IHelpProvider
|
||||
{
|
||||
// Register the help provider
|
||||
_registrar.Register(typeof(IHelpProvider), typeof(T));
|
||||
}
|
||||
|
||||
public void SetHelpProvider(IHelpProvider helpProvider)
|
||||
{
|
||||
// Register the help provider
|
||||
_registrar.RegisterInstance(typeof(IHelpProvider), helpProvider);
|
||||
}
|
||||
|
||||
public void SetHelpProvider<T>()
|
||||
where T : IHelpProvider
|
||||
{
|
||||
// Register the help provider
|
||||
_registrar.Register(typeof(IHelpProvider), typeof(T));
|
||||
}
|
||||
|
||||
public void AddExample(params string[] args)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
|
||||
internal sealed class CommandInfo : ICommandContainer, ICommandInfo
|
||||
{
|
||||
public string Name { get; }
|
||||
@ -20,14 +20,14 @@ internal sealed class CommandInfo : ICommandContainer, ICommandInfo
|
||||
|
||||
// only branches can have a default command
|
||||
public CommandInfo? DefaultCommand => IsBranch ? Children.FirstOrDefault(c => c.IsDefaultCommand) : null;
|
||||
public bool IsHidden { get; }
|
||||
|
||||
IReadOnlyList<ICommandInfo> Help.ICommandContainer.Commands => Children.Cast<ICommandInfo>().ToList();
|
||||
ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand;
|
||||
IReadOnlyList<ICommandParameter> ICommandInfo.Parameters => Parameters.Cast<ICommandParameter>().ToList();
|
||||
ICommandInfo? ICommandInfo.Parent => Parent;
|
||||
IReadOnlyList<string[]> Help.ICommandContainer.Examples => (IReadOnlyList<string[]>)Examples;
|
||||
|
||||
public bool IsHidden { get; }
|
||||
|
||||
IReadOnlyList<ICommandInfo> Help.ICommandContainer.Commands => Children.Cast<ICommandInfo>().ToList();
|
||||
ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand;
|
||||
IReadOnlyList<ICommandParameter> ICommandInfo.Parameters => Parameters.Cast<ICommandParameter>().ToList();
|
||||
ICommandInfo? ICommandInfo.Parent => Parent;
|
||||
IReadOnlyList<string[]> Help.ICommandContainer.Examples => (IReadOnlyList<string[]>)Examples;
|
||||
|
||||
public CommandInfo(CommandInfo? parent, ConfiguredCommand prototype)
|
||||
{
|
||||
Parent = parent;
|
||||
@ -54,5 +54,5 @@ internal sealed class CommandInfo : ICommandContainer, ICommandInfo
|
||||
Description = description.Description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
|
||||
internal sealed class CommandModel : ICommandContainer, ICommandModel
|
||||
{
|
||||
public string? ApplicationName { get; }
|
||||
public ParsingMode ParsingMode { get; }
|
||||
public IList<CommandInfo> Commands { get; }
|
||||
public IList<string[]> Examples { get; }
|
||||
|
||||
public IList<string[]> Examples { get; }
|
||||
|
||||
public CommandInfo? DefaultCommand => Commands.FirstOrDefault(c => c.IsDefaultCommand);
|
||||
|
||||
string ICommandModel.ApplicationName => GetApplicationName(ApplicationName);
|
||||
IReadOnlyList<ICommandInfo> Help.ICommandContainer.Commands => Commands.Cast<ICommandInfo>().ToList();
|
||||
ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand;
|
||||
ICommandInfo? Help.ICommandContainer.DefaultCommand => DefaultCommand;
|
||||
IReadOnlyList<string[]> Help.ICommandContainer.Examples => (IReadOnlyList<string[]>)Examples;
|
||||
|
||||
public CommandModel(
|
||||
@ -22,18 +22,18 @@ internal sealed class CommandModel : ICommandContainer, ICommandModel
|
||||
ApplicationName = settings.ApplicationName;
|
||||
ParsingMode = settings.ParsingMode;
|
||||
Commands = new List<CommandInfo>(commands ?? Array.Empty<CommandInfo>());
|
||||
Examples = new List<string[]>(examples ?? Array.Empty<string[]>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the application.
|
||||
/// If the provided <paramref name="applicationName"/> is not null or empty,
|
||||
/// it is returned. Otherwise the name of the current application
|
||||
/// is determined based on the executable file's name.
|
||||
/// </summary>
|
||||
/// <param name="applicationName">The optional name of the application.</param>
|
||||
/// <returns>
|
||||
/// The name of the application, or a default value of "?" if no valid application name can be determined.
|
||||
Examples = new List<string[]>(examples ?? Array.Empty<string[]>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the application.
|
||||
/// If the provided <paramref name="applicationName"/> is not null or empty,
|
||||
/// it is returned. Otherwise the name of the current application
|
||||
/// is determined based on the executable file's name.
|
||||
/// </summary>
|
||||
/// <param name="applicationName">The optional name of the application.</param>
|
||||
/// <returns>
|
||||
/// The name of the application, or a default value of "?" if no valid application name can be determined.
|
||||
/// </returns>
|
||||
private static string GetApplicationName(string? applicationName)
|
||||
{
|
||||
@ -45,7 +45,7 @@ internal sealed class CommandModel : ICommandContainer, ICommandModel
|
||||
|
||||
private static string? GetApplicationFile()
|
||||
{
|
||||
var location = Assembly.GetEntryAssembly()?.Location;
|
||||
var location = Assembly.GetEntryAssembly()?.Location;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(location))
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
|
||||
internal static class CommandModelBuilder
|
||||
{
|
||||
// Consider removing this in favor for value tuples at some point.
|
||||
@ -31,8 +31,8 @@ internal static class CommandModelBuilder
|
||||
configuration.DefaultCommand.Examples.AddRange(configuration.Examples);
|
||||
|
||||
// Build the default command.
|
||||
var defaultCommand = Build(null, configuration.DefaultCommand);
|
||||
|
||||
var defaultCommand = Build(null, configuration.DefaultCommand);
|
||||
|
||||
result.Add(defaultCommand);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ internal static class CommandModelBuilder
|
||||
foreach (var childCommand in command.Children)
|
||||
{
|
||||
var child = Build(info, childCommand);
|
||||
info.Children.Add(child);
|
||||
info.Children.Add(child);
|
||||
}
|
||||
|
||||
// Normalize argument positions.
|
||||
|
@ -1,5 +1,5 @@
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
|
||||
internal abstract class CommandParameter : ICommandParameterInfo, ICommandParameter
|
||||
{
|
||||
public Guid Id { get; }
|
||||
@ -17,10 +17,10 @@ internal abstract class CommandParameter : ICommandParameterInfo, ICommandParame
|
||||
public string PropertyName => Property.Name;
|
||||
|
||||
public virtual bool WantRawValue => ParameterType.IsPairDeconstructable()
|
||||
&& (PairDeconstructor != null || Converter == null);
|
||||
|
||||
public bool IsFlag => ParameterKind == ParameterKind.Flag;
|
||||
|
||||
&& (PairDeconstructor != null || Converter == null);
|
||||
|
||||
public bool IsFlag => ParameterKind == ParameterKind.Flag;
|
||||
|
||||
protected CommandParameter(
|
||||
Type parameterType, ParameterKind parameterKind, PropertyInfo property,
|
||||
string? description, TypeConverterAttribute? converter,
|
||||
|
@ -8,13 +8,13 @@ internal interface ICommandContainer
|
||||
/// <summary>
|
||||
/// Gets all commands in the container.
|
||||
/// </summary>
|
||||
IList<CommandInfo> Commands { get; }
|
||||
|
||||
IList<CommandInfo> Commands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default command for the container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns null if a default command has not been set.
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns null if a default command has not been set.
|
||||
/// </remarks>
|
||||
CommandInfo? DefaultCommand { get; }
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
using static Spectre.Console.Cli.CommandTreeTokenizer;
|
||||
|
||||
using static Spectre.Console.Cli.CommandTreeTokenizer;
|
||||
|
||||
namespace Spectre.Console.Cli;
|
||||
|
||||
internal class CommandTreeParser
|
||||
{
|
||||
private readonly CommandModel _configuration;
|
||||
private readonly ParsingMode _parsingMode;
|
||||
private readonly CommandOptionAttribute _help;
|
||||
private readonly CommandOptionAttribute _help;
|
||||
private readonly bool _convertFlagsToRemainingArguments;
|
||||
|
||||
public CaseSensitivity CaseSensitivity { get; }
|
||||
@ -21,20 +21,20 @@ internal class CommandTreeParser
|
||||
{
|
||||
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
|
||||
_parsingMode = parsingMode ?? _configuration.ParsingMode;
|
||||
_help = new CommandOptionAttribute("-h|--help");
|
||||
_help = new CommandOptionAttribute("-h|--help");
|
||||
_convertFlagsToRemainingArguments = convertFlagsToRemainingArguments ?? false;
|
||||
|
||||
CaseSensitivity = caseSensitivity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CommandTreeParserResult Parse(IEnumerable<string> args)
|
||||
{
|
||||
var parserContext = new CommandTreeParserContext(args, _parsingMode);
|
||||
var tokenizerResult = CommandTreeTokenizer.Tokenize(args);
|
||||
|
||||
return Parse(parserContext, tokenizerResult);
|
||||
}
|
||||
|
||||
{
|
||||
var parserContext = new CommandTreeParserContext(args, _parsingMode);
|
||||
var tokenizerResult = CommandTreeTokenizer.Tokenize(args);
|
||||
|
||||
return Parse(parserContext, tokenizerResult);
|
||||
}
|
||||
|
||||
public CommandTreeParserResult Parse(CommandTreeParserContext context, CommandTreeTokenizerResult tokenizerResult)
|
||||
{
|
||||
var tokens = tokenizerResult.Tokens;
|
||||
@ -258,8 +258,8 @@ internal class CommandTreeParser
|
||||
// Find the option.
|
||||
var option = node.FindOption(token.Value, isLongOption, CaseSensitivity);
|
||||
if (option != null)
|
||||
{
|
||||
ParseOptionValue(context, stream, token, node, option);
|
||||
{
|
||||
ParseOptionValue(context, stream, token, node, option);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -291,10 +291,10 @@ internal class CommandTreeParser
|
||||
CommandTreeParserContext context,
|
||||
CommandTreeTokenStream stream,
|
||||
CommandTreeToken token,
|
||||
CommandTree current,
|
||||
CommandTree current,
|
||||
CommandParameter? parameter = null)
|
||||
{
|
||||
bool addToMappedCommandParameters = parameter != null;
|
||||
{
|
||||
bool addToMappedCommandParameters = parameter != null;
|
||||
|
||||
var value = default(string);
|
||||
|
||||
@ -312,49 +312,49 @@ internal class CommandTreeParser
|
||||
{
|
||||
// Is this a command?
|
||||
if (current.Command.FindCommand(valueToken.Value, CaseSensitivity) == null)
|
||||
{
|
||||
if (parameter != null)
|
||||
{
|
||||
if (parameter.ParameterKind == ParameterKind.Flag)
|
||||
{
|
||||
if (!CliConstants.AcceptedBooleanValues.Contains(valueToken.Value, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!valueToken.HadSeparator)
|
||||
{
|
||||
// Do nothing
|
||||
// - assume valueToken is unrelated to the flag parameter (ie. we've parsed it unnecessarily)
|
||||
// - rely on the "No value?" code below to set the flag to its default value
|
||||
// - valueToken will be handled on the next pass of the parser
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flags cannot be assigned a value.
|
||||
if (_convertFlagsToRemainingArguments)
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
|
||||
context.AddRemainingArgument(token.Value, value);
|
||||
|
||||
// Prevent the option and it's non-boolean value from being added to
|
||||
// mapped parameters (otherwise an exception will be thrown later
|
||||
// when binding the value to the flag in the comand settings)
|
||||
addToMappedCommandParameters = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw CommandParseException.CannotAssignValueToFlag(context.Arguments, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
}
|
||||
{
|
||||
if (parameter != null)
|
||||
{
|
||||
if (parameter.ParameterKind == ParameterKind.Flag)
|
||||
{
|
||||
if (!CliConstants.AcceptedBooleanValues.Contains(valueToken.Value, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!valueToken.HadSeparator)
|
||||
{
|
||||
// Do nothing
|
||||
// - assume valueToken is unrelated to the flag parameter (ie. we've parsed it unnecessarily)
|
||||
// - rely on the "No value?" code below to set the flag to its default value
|
||||
// - valueToken will be handled on the next pass of the parser
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flags cannot be assigned a value.
|
||||
if (_convertFlagsToRemainingArguments)
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
|
||||
context.AddRemainingArgument(token.Value, value);
|
||||
|
||||
// Prevent the option and it's non-boolean value from being added to
|
||||
// mapped parameters (otherwise an exception will be thrown later
|
||||
// when binding the value to the flag in the comand settings)
|
||||
addToMappedCommandParameters = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw CommandParseException.CannotAssignValueToFlag(context.Arguments, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = stream.Consume(CommandTreeToken.Kind.String)?.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -370,13 +370,13 @@ internal class CommandTreeParser
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
context.AddRemainingArgument(token.Value, parseValue ? valueToken.Value : null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parameter == null && // Only add tokens which have not been matched to a command parameter
|
||||
if (parameter == null && // Only add tokens which have not been matched to a command parameter
|
||||
(context.State == State.Remaining || context.ParsingMode == ParsingMode.Relaxed))
|
||||
{
|
||||
context.AddRemainingArgument(token.Value, null);
|
||||
@ -399,10 +399,10 @@ internal class CommandTreeParser
|
||||
if (parameter.IsFlagValue())
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw CommandParseException.OptionHasNoValue(context.Arguments, token, option);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw CommandParseException.OptionHasNoValue(context.Arguments, token, option);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -415,9 +415,9 @@ internal class CommandTreeParser
|
||||
}
|
||||
}
|
||||
|
||||
if (parameter != null && addToMappedCommandParameters)
|
||||
{
|
||||
current.Mapped.Add(new MappedCommandParameter(parameter, value));
|
||||
if (parameter != null && addToMappedCommandParameters)
|
||||
{
|
||||
current.Mapped.Add(new MappedCommandParameter(parameter, value));
|
||||
}
|
||||
}
|
||||
}
|
@ -26,15 +26,15 @@ internal class CommandTreeParserContext
|
||||
public void IncreaseArgumentPosition()
|
||||
{
|
||||
CurrentArgumentPosition++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void AddRemainingArgument(string key, string? value)
|
||||
{
|
||||
if (!_remaining.ContainsKey(key))
|
||||
{
|
||||
_remaining.Add(key, new List<string?>());
|
||||
}
|
||||
|
||||
{
|
||||
if (!_remaining.ContainsKey(key))
|
||||
{
|
||||
_remaining.Add(key, new List<string?>());
|
||||
}
|
||||
|
||||
_remaining[key].Add(value);
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,11 @@ internal sealed class CommandTreeToken
|
||||
public int Position { get; }
|
||||
public string Value { get; }
|
||||
public string Representation { get; }
|
||||
public bool IsGrouped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether a separater was encountered immediately before the <see cref="CommandTreeToken.Value"/>.
|
||||
/// </summary>
|
||||
public bool IsGrouped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether a separater was encountered immediately before the <see cref="CommandTreeToken.Value"/>.
|
||||
/// </summary>
|
||||
public bool HadSeparator { get; set; }
|
||||
|
||||
public enum Kind
|
||||
|
@ -5,7 +5,7 @@ internal sealed class CommandTreeTokenStream : IReadOnlyList<CommandTreeToken>
|
||||
private readonly List<CommandTreeToken> _tokens;
|
||||
private int _position;
|
||||
|
||||
public int Count => _tokens.Count;
|
||||
public int Count => _tokens.Count;
|
||||
public int Position => _position;
|
||||
|
||||
public CommandTreeToken this[int index] => _tokens[index];
|
||||
|
@ -29,13 +29,13 @@ internal static class CommandTreeTokenizer
|
||||
var context = new CommandTreeTokenizerContext();
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arg))
|
||||
{
|
||||
// Null strings in the args array are still represented as tokens
|
||||
tokens.Add(new CommandTreeToken(CommandTreeToken.Kind.String, position, string.Empty, string.Empty));
|
||||
continue;
|
||||
}
|
||||
{
|
||||
if (string.IsNullOrEmpty(arg))
|
||||
{
|
||||
// Null strings in the args array are still represented as tokens
|
||||
tokens.Add(new CommandTreeToken(CommandTreeToken.Kind.String, position, string.Empty, string.Empty));
|
||||
continue;
|
||||
}
|
||||
|
||||
var start = position;
|
||||
var reader = new TextBuffer(previousReader, arg);
|
||||
@ -55,30 +55,30 @@ internal static class CommandTreeTokenizer
|
||||
}
|
||||
|
||||
private static int ParseToken(CommandTreeTokenizerContext context, TextBuffer reader, int position, int start, List<CommandTreeToken> tokens)
|
||||
{
|
||||
if (!reader.ReachedEnd && reader.Peek() == '-')
|
||||
{
|
||||
// Option
|
||||
tokens.AddRange(ScanOptions(context, reader));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Command or argument
|
||||
while (reader.Peek() != -1)
|
||||
{
|
||||
if (reader.ReachedEnd)
|
||||
{
|
||||
position += reader.Position - start;
|
||||
break;
|
||||
}
|
||||
|
||||
tokens.Add(ScanString(context, reader));
|
||||
|
||||
// Flush remaining tokens
|
||||
context.FlushRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (!reader.ReachedEnd && reader.Peek() == '-')
|
||||
{
|
||||
// Option
|
||||
tokens.AddRange(ScanOptions(context, reader));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Command or argument
|
||||
while (reader.Peek() != -1)
|
||||
{
|
||||
if (reader.ReachedEnd)
|
||||
{
|
||||
position += reader.Position - start;
|
||||
break;
|
||||
}
|
||||
|
||||
tokens.Add(ScanString(context, reader));
|
||||
|
||||
// Flush remaining tokens
|
||||
context.FlushRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ internal static class CommandTreeTokenizer
|
||||
builder.Append(current);
|
||||
}
|
||||
|
||||
var value = builder.ToString();
|
||||
var value = builder.ToString();
|
||||
return new CommandTreeToken(CommandTreeToken.Kind.String, position, value, value);
|
||||
}
|
||||
|
||||
@ -149,8 +149,8 @@ internal static class CommandTreeTokenizer
|
||||
var token = new CommandTreeToken(CommandTreeToken.Kind.String, reader.Position, "=", "=");
|
||||
throw CommandParseException.OptionValueWasExpected(reader.Original, token);
|
||||
}
|
||||
|
||||
var tokenValue = ScanString(context, reader);
|
||||
|
||||
var tokenValue = ScanString(context, reader);
|
||||
tokenValue.HadSeparator = true;
|
||||
result.Add(tokenValue);
|
||||
}
|
||||
@ -193,7 +193,7 @@ internal static class CommandTreeTokenizer
|
||||
// be tokenized as strings. This block handles parsing those cases, but we only allow this
|
||||
// when the digit is the first character in the token (i.e. "-a1" is always an error), hence the
|
||||
// result.Count == 0 check above.
|
||||
string value = string.Empty;
|
||||
string value = string.Empty;
|
||||
|
||||
while (!reader.ReachedEnd)
|
||||
{
|
||||
@ -212,12 +212,12 @@ internal static class CommandTreeTokenizer
|
||||
result.Add(new CommandTreeToken(CommandTreeToken.Kind.String, position, value, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// Create a token representing the short option.
|
||||
var representation = current.ToString(CultureInfo.InvariantCulture);
|
||||
var tokenPosition = position + 1 + result.Count;
|
||||
var token = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, tokenPosition, representation, representation);
|
||||
|
||||
var representation = current.ToString(CultureInfo.InvariantCulture);
|
||||
var tokenPosition = position + 1 + result.Count;
|
||||
var token = new CommandTreeToken(CommandTreeToken.Kind.ShortOption, tokenPosition, representation, representation);
|
||||
|
||||
throw CommandParseException.InvalidShortOptionName(reader.Original, token);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ global using System.Linq;
|
||||
global using System.Reflection;
|
||||
global using System.Text;
|
||||
global using System.Threading.Tasks;
|
||||
global using System.Xml;
|
||||
global using System.Xml;
|
||||
global using Spectre.Console.Cli.Help;
|
||||
global using Spectre.Console.Cli.Unsafe;
|
||||
global using Spectre.Console.Rendering;
|
@ -1,153 +1,153 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Spectre.Console.Cli.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class HelpProvider {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal HelpProvider() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Spectre.Console.Cli.Resources.HelpProvider", typeof(HelpProvider).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ARGUMENTS.
|
||||
/// </summary>
|
||||
internal static string Arguments {
|
||||
get {
|
||||
return ResourceManager.GetString("Arguments", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to COMMAND.
|
||||
/// </summary>
|
||||
internal static string Command {
|
||||
get {
|
||||
return ResourceManager.GetString("Command", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to COMMANDS.
|
||||
/// </summary>
|
||||
internal static string Commands {
|
||||
get {
|
||||
return ResourceManager.GetString("Commands", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DEFAULT.
|
||||
/// </summary>
|
||||
internal static string Default {
|
||||
get {
|
||||
return ResourceManager.GetString("Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DESCRIPTION.
|
||||
/// </summary>
|
||||
internal static string Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to EXAMPLES.
|
||||
/// </summary>
|
||||
internal static string Examples {
|
||||
get {
|
||||
return ResourceManager.GetString("Examples", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OPTIONS.
|
||||
/// </summary>
|
||||
internal static string Options {
|
||||
get {
|
||||
return ResourceManager.GetString("Options", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prints help information.
|
||||
/// </summary>
|
||||
internal static string PrintHelpDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("PrintHelpDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prints version information.
|
||||
/// </summary>
|
||||
internal static string PrintVersionDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("PrintVersionDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to USAGE.
|
||||
/// </summary>
|
||||
internal static string Usage {
|
||||
get {
|
||||
return ResourceManager.GetString("Usage", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Spectre.Console.Cli.Resources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class HelpProvider {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal HelpProvider() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Spectre.Console.Cli.Resources.HelpProvider", typeof(HelpProvider).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ARGUMENTS.
|
||||
/// </summary>
|
||||
internal static string Arguments {
|
||||
get {
|
||||
return ResourceManager.GetString("Arguments", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to COMMAND.
|
||||
/// </summary>
|
||||
internal static string Command {
|
||||
get {
|
||||
return ResourceManager.GetString("Command", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to COMMANDS.
|
||||
/// </summary>
|
||||
internal static string Commands {
|
||||
get {
|
||||
return ResourceManager.GetString("Commands", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DEFAULT.
|
||||
/// </summary>
|
||||
internal static string Default {
|
||||
get {
|
||||
return ResourceManager.GetString("Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to DESCRIPTION.
|
||||
/// </summary>
|
||||
internal static string Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to EXAMPLES.
|
||||
/// </summary>
|
||||
internal static string Examples {
|
||||
get {
|
||||
return ResourceManager.GetString("Examples", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OPTIONS.
|
||||
/// </summary>
|
||||
internal static string Options {
|
||||
get {
|
||||
return ResourceManager.GetString("Options", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prints help information.
|
||||
/// </summary>
|
||||
internal static string PrintHelpDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("PrintHelpDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Prints version information.
|
||||
/// </summary>
|
||||
internal static string PrintVersionDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("PrintVersionDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to USAGE.
|
||||
/// </summary>
|
||||
internal static string Usage {
|
||||
get {
|
||||
return ResourceManager.GetString("Usage", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,8 +141,8 @@ public sealed class CommandAppTester
|
||||
.Trim();
|
||||
|
||||
return new CommandAppResult(result, output, context, settings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the command application asynchronously.
|
||||
/// </summary>
|
||||
|
@ -60,7 +60,7 @@ public static partial class AnsiConsoleExtensions
|
||||
|
||||
if (!char.IsControl(key.KeyChar))
|
||||
{
|
||||
text += key.KeyChar.ToString();
|
||||
text += key.KeyChar.ToString();
|
||||
var output = key.KeyChar.ToString();
|
||||
console.Write(secret ? output.Mask(mask) : output, style);
|
||||
}
|
||||
|
@ -185,28 +185,28 @@ public static class StringExtensions
|
||||
#else
|
||||
return text.Contains(value, StringComparison.Ordinal);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "Masks" every character in a string.
|
||||
/// </summary>
|
||||
/// <param name="value">String value to mask.</param>
|
||||
/// <param name="mask">Character to use for masking.</param>
|
||||
/// <returns>Masked string.</returns>
|
||||
public static string Mask(this string value, char? mask)
|
||||
{
|
||||
var output = string.Empty;
|
||||
|
||||
if (mask is null)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
foreach (var c in value)
|
||||
{
|
||||
output += mask;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "Masks" every character in a string.
|
||||
/// </summary>
|
||||
/// <param name="value">String value to mask.</param>
|
||||
/// <param name="mask">Character to use for masking.</param>
|
||||
/// <returns>Masked string.</returns>
|
||||
public static string Mask(this string value, char? mask)
|
||||
{
|
||||
var output = string.Empty;
|
||||
|
||||
if (mask is null)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
foreach (var c in value)
|
||||
{
|
||||
output += mask;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Spectre.Console;
|
||||
namespace Spectre.Console;
|
||||
|
||||
/// <summary>
|
||||
/// Represents horizontal alignment.
|
||||
|
@ -286,25 +286,25 @@ public static class TextPromptExtensions
|
||||
|
||||
obj.IsSecret = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces prompt user input with mask in the console.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The prompt type.</typeparam>
|
||||
/// <param name="obj">The prompt.</param>
|
||||
/// <param name="obj">The prompt.</param>
|
||||
/// <param name="mask">The masking character to use for the secret.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static TextPrompt<T> Secret<T>(this TextPrompt<T> obj, char? mask)
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.IsSecret = true;
|
||||
obj.Mask = mask;
|
||||
return obj;
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static TextPrompt<T> Secret<T>(this TextPrompt<T> obj, char? mask)
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.IsSecret = true;
|
||||
obj.Mask = mask;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Spectre.Console;
|
||||
namespace Spectre.Console;
|
||||
|
||||
/// <summary>
|
||||
/// Represents vertical alignment.
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Spectre.Console;
|
||||
namespace Spectre.Console;
|
||||
|
||||
internal static class TypeNameHelper
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Spectre.Console;
|
||||
namespace Spectre.Console;
|
||||
|
||||
[DebuggerDisplay("{Region,nq}")]
|
||||
internal sealed class LayoutRender
|
||||
|
Reference in New Issue
Block a user