Skip to content

Introduce Directive Symbol type #2063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion samples/RenderingPlayground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static void Main(

var consoleRenderer = new ConsoleRenderer(
console,
mode: invocationContext.BindingContext.OutputMode(),
mode: OutputMode.Auto,
resetAfterRender: true);

switch (sample)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
System.CommandLine.Hosting
public static class DirectiveConfigurationExtensions
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddCommandLineDirectives(this Microsoft.Extensions.Configuration.IConfigurationBuilder config, System.CommandLine.ParseResult commandline, System.String name)
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddCommandLineDirectives(this Microsoft.Extensions.Configuration.IConfigurationBuilder config, System.CommandLine.ParseResult commandline, System.CommandLine.Directive directive)
public static class HostingExtensions
public static OptionsBuilder<TOptions> BindCommandLine<TOptions>(this OptionsBuilder<TOptions> optionsBuilder)
public static Microsoft.Extensions.Hosting.IHost GetHost(this System.CommandLine.Invocation.InvocationContext invocationContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ System.CommandLine
public class CommandLineBuilder
.ctor(Command rootCommand)
public Command Command { get; }
public System.Collections.Generic.List<Directive> Directives { get; }
public CommandLineBuilder AddMiddleware(System.CommandLine.Invocation.InvocationMiddleware middleware, System.CommandLine.Invocation.MiddlewareOrder order = Default)
public CommandLineBuilder AddMiddleware(System.Action<System.CommandLine.Invocation.InvocationContext> onInvoke, System.CommandLine.Invocation.MiddlewareOrder order = Default)
public CommandLineConfiguration Build()
public CommandLineBuilder CancelOnProcessTermination(System.Nullable<System.TimeSpan> timeout = null)
public CommandLineBuilder EnableDirectives(System.Boolean value = True)
public CommandLineBuilder EnablePosixBundling(System.Boolean value = True)
public CommandLineBuilder RegisterWithDotnetSuggest()
public CommandLineBuilder UseDefaults()
Expand All @@ -81,8 +81,8 @@ System.CommandLine
public CommandLineBuilder UseVersionOption(System.String name, System.String[] aliases)
public class CommandLineConfiguration
public static CommandLineBuilder CreateBuilder(Command rootCommand)
.ctor(Command command, System.Boolean enablePosixBundling = True, System.Boolean enableDirectives = True, System.Boolean enableTokenReplacement = True, System.Collections.Generic.IReadOnlyList<System.CommandLine.Invocation.InvocationMiddleware> middlewarePipeline = null, System.Func<System.CommandLine.Binding.BindingContext,System.CommandLine.Help.HelpBuilder> helpBuilderFactory = null, System.CommandLine.Parsing.TryReplaceToken tokenReplacer = null)
public System.Boolean EnableDirectives { get; }
.ctor(Command command, System.Boolean enablePosixBundling = True, System.Boolean enableTokenReplacement = True, System.Collections.Generic.IReadOnlyList<System.CommandLine.Invocation.InvocationMiddleware> middlewarePipeline = null, System.Func<System.CommandLine.Binding.BindingContext,System.CommandLine.Help.HelpBuilder> helpBuilderFactory = null, System.CommandLine.Parsing.TryReplaceToken tokenReplacer = null)
public System.Collections.Generic.IReadOnlyList<Directive> Directives { get; }
public System.Boolean EnablePosixBundling { get; }
public System.Boolean EnableTokenReplacement { get; }
public Command RootCommand { get; }
Expand All @@ -101,11 +101,13 @@ System.CommandLine
public static class ConsoleExtensions
public static System.Void Write(this IConsole console, System.String value)
public static System.Void WriteLine(this IConsole console, System.String value)
public class DirectiveCollection, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<System.String,System.Collections.Generic.IEnumerable<System.String>>>, System.Collections.IEnumerable
public class Directive : Symbol
.ctor(System.String name, System.Action<System.CommandLine.Invocation.InvocationContext> syncHandler = null, System.Func<System.CommandLine.Invocation.InvocationContext,System.Threading.CancellationToken,System.Threading.Tasks.Task> asyncHandler = null)
public System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem> GetCompletions(System.CommandLine.Completions.CompletionContext context)
public System.Void SetAsynchronousHandler(System.Func<System.CommandLine.Invocation.InvocationContext,System.Threading.CancellationToken,System.Threading.Tasks.Task> handler)
public System.Void SetSynchronousHandler(System.Action<System.CommandLine.Invocation.InvocationContext> handler)
public class EnvironmentVariablesDirective : Directive
.ctor()
public System.Boolean Contains(System.String name)
public System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<System.String,System.Collections.Generic.IEnumerable<System.String>>> GetEnumerator()
public System.Boolean TryGetValues(System.String name, ref System.Collections.Generic.IReadOnlyList<System.String> values)
public static class Handler
public static System.Void SetHandler(this Command command, System.Action<System.CommandLine.Invocation.InvocationContext> handle)
public static System.Void SetHandler(this Command command, System.Action handle)
Expand Down Expand Up @@ -154,17 +156,19 @@ System.CommandLine
public static Option<System.IO.DirectoryInfo> AcceptExistingOnly(this Option<System.IO.DirectoryInfo> option)
public static Option<System.IO.FileSystemInfo> AcceptExistingOnly(this Option<System.IO.FileSystemInfo> option)
public static Option<T> AcceptExistingOnly<T>(this Option<T> option)
public class ParseDirective : Directive
.ctor(System.Int32 errorExitCode = 1)
public class ParseResult
public System.CommandLine.Parsing.CommandResult CommandResult { get; }
public CommandLineConfiguration Configuration { get; }
public System.Collections.Generic.IReadOnlyDictionary<System.String,System.Collections.Generic.IReadOnlyList<System.String>> Directives { get; }
public System.Collections.Generic.IReadOnlyList<System.CommandLine.Parsing.ParseError> Errors { get; }
public System.CommandLine.Parsing.CommandResult RootCommandResult { get; }
public System.Collections.Generic.IReadOnlyList<System.CommandLine.Parsing.Token> Tokens { get; }
public System.Collections.Generic.IReadOnlyList<System.String> UnmatchedTokens { get; }
public System.CommandLine.Parsing.ArgumentResult FindResultFor(Argument argument)
public System.CommandLine.Parsing.CommandResult FindResultFor(Command command)
public System.CommandLine.Parsing.OptionResult FindResultFor(Option option)
public System.CommandLine.Parsing.DirectiveResult FindResultFor(Directive directive)
public System.CommandLine.Parsing.SymbolResult FindResultFor(Symbol symbol)
public System.CommandLine.Completions.CompletionContext GetCompletionContext()
public System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem> GetCompletions(System.Nullable<System.Int32> position = null)
Expand All @@ -177,6 +181,8 @@ System.CommandLine
public static System.String ExecutableName { get; }
public static System.String ExecutablePath { get; }
.ctor(System.String description = )
public class SuggestDirective : Directive
.ctor()
public abstract class Symbol
public System.String Description { get; set; }
public System.Boolean IsHidden { get; set; }
Expand Down Expand Up @@ -337,6 +343,10 @@ System.CommandLine.Parsing
public System.CommandLine.Command Command { get; }
public Token Token { get; }
public System.String ToString()
public class DirectiveResult : SymbolResult
public System.CommandLine.Directive Directive { get; }
public Token Token { get; }
public System.Collections.Generic.IReadOnlyList<System.String> Values { get; }
public class OptionResult : SymbolResult
public System.Boolean IsImplicit { get; }
public System.CommandLine.Option Option { get; }
Expand All @@ -360,6 +370,7 @@ System.CommandLine.Parsing
public ArgumentResult FindResultFor(System.CommandLine.Argument argument)
public CommandResult FindResultFor(System.CommandLine.Command command)
public OptionResult FindResultFor(System.CommandLine.Option option)
public DirectiveResult FindResultFor(System.CommandLine.Directive directive)
public T GetValue<T>(Argument<T> argument)
public T GetValue<T>(Option<T> option)
public class Token, System.IEquatable<Token>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public IEnumerable<object> GenerateTestParseResults()

[Benchmark]
[ArgumentsSource(nameof(GenerateTestInputs))]
public IReadOnlyDictionary<string, IReadOnlyList<string>> ParseResult_Directives(string input)
=> _configuration.RootCommand.Parse(input, _configuration).Directives;
public ParseResult ParseResult_Directives(string input)
=> _configuration.RootCommand.Parse(input, _configuration);

[Benchmark]
[ArgumentsSource(nameof(GenerateTestParseResults))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.CommandLine.Parsing;
using System.Linq;

using Microsoft.Extensions.Configuration;
Expand All @@ -9,18 +10,21 @@ public static class DirectiveConfigurationExtensions
{
public static IConfigurationBuilder AddCommandLineDirectives(
this IConfigurationBuilder config, ParseResult commandline,
string name)
Directive directive)
{
if (commandline is null)
throw new ArgumentNullException(nameof(commandline));
if (name is null)
throw new ArgumentNullException(nameof(name));
if (directive is null)
throw new ArgumentNullException(nameof(directive));

if (!commandline.Directives.TryGetValue(name, out var directives))
if (commandline.FindResultFor(directive) is not DirectiveResult result
|| result.Values.Count == 0)
{
return config;
}

var kvpSeparator = new[] { '=' };
return config.AddInMemoryCollection(directives.Select(s =>
return config.AddInMemoryCollection(result.Values.Select(s =>
{
var parts = s.Split(kvpSeparator, count: 2);
var key = parts[0];
Expand Down
13 changes: 8 additions & 5 deletions src/System.CommandLine.Hosting/HostingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ namespace System.CommandLine.Hosting
{
public static class HostingExtensions
{
private const string ConfigurationDirectiveName = "config";

public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Func<string[], IHostBuilder> hostBuilderFactory,
Action<IHostBuilder> configureHost = null) =>
builder.AddMiddleware(async (invocation, cancellationToken, next) =>
Action<IHostBuilder> configureHost = null)
{
Directive configurationDirective = new("config");
builder.Directives.Add(configurationDirective);

return builder.AddMiddleware(async (invocation, cancellationToken, next) =>
{
var argsRemaining = invocation.ParseResult.UnmatchedTokens.ToArray();
var hostBuilder = hostBuilderFactory?.Invoke(argsRemaining)
Expand All @@ -27,7 +29,7 @@ public static CommandLineBuilder UseHost(this CommandLineBuilder builder,

hostBuilder.ConfigureHostConfiguration(config =>
{
config.AddCommandLineDirectives(invocation.ParseResult, ConfigurationDirectiveName);
config.AddCommandLineDirectives(invocation.ParseResult, configurationDirective);
});
hostBuilder.ConfigureServices(services =>
{
Expand All @@ -50,6 +52,7 @@ public static CommandLineBuilder UseHost(this CommandLineBuilder builder,

await host.StopAsync(cancellationToken);
});
}

public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Action<IHostBuilder> configureHost = null
Expand Down
38 changes: 18 additions & 20 deletions src/System.CommandLine.Rendering/CommandLineBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.CommandLine.Binding;
using System.Linq;
using System.CommandLine.Parsing;

namespace System.CommandLine.Rendering
{
Expand All @@ -11,30 +10,33 @@ public static class CommandLineBuilderExtensions
public static CommandLineBuilder UseAnsiTerminalWhenAvailable(
this CommandLineBuilder builder)
{
Directive enableVtDirective = new ("enable-vt");
Directive outputDirective = new ("output");
builder.Directives.Add(enableVtDirective);
builder.Directives.Add(outputDirective);

builder.AddMiddleware(context =>
{
var console = context.Console;

var terminal = console.GetTerminal(
PreferVirtualTerminal(context.BindingContext),
OutputMode(context.BindingContext));
PreferVirtualTerminal(context.ParseResult, enableVtDirective),
OutputMode(context.ParseResult, outputDirective));

context.Console = terminal ?? console;
});

return builder;
}

internal static bool PreferVirtualTerminal(
this BindingContext context)
private static bool PreferVirtualTerminal(ParseResult parseResult, Directive enableVtDirective)
{
if (context.ParseResult.Directives.TryGetValue(
"enable-vt",
out var trueOrFalse))
if (parseResult.FindResultFor(enableVtDirective) is DirectiveResult result
&& result.Values.Count == 1)
{
if (bool.TryParse(
trueOrFalse.FirstOrDefault(),
out var pvt))
string trueOrFalse = result.Values[0];

if (bool.TryParse(trueOrFalse, out var pvt))
{
return pvt;
}
Expand All @@ -43,15 +45,11 @@ internal static bool PreferVirtualTerminal(
return true;
}

public static OutputMode OutputMode(this BindingContext context)
private static OutputMode OutputMode(ParseResult parseResult, Directive outputDirective)
{
if (context.ParseResult.Directives.TryGetValue(
"output",
out var modeString) &&
Enum.TryParse<OutputMode>(
modeString.FirstOrDefault(),
true,
out var mode))
if (parseResult.FindResultFor(outputDirective) is DirectiveResult result
&& result.Values.Count == 1
&& Enum.TryParse<OutputMode>(result.Values[0], true, out var mode))
{
return mode;
}
Expand Down
Loading