Skip to content

Commit af0c123

Browse files
committed
refactoring ReadOnlyMemory args based.
1 parent c821763 commit af0c123

File tree

4 files changed

+226
-142
lines changed

4 files changed

+226
-142
lines changed
Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,39 @@
11
using ConsoleAppFramework;
2-
using Microsoft.Extensions.DependencyInjection;
3-
using System.Diagnostics.CodeAnalysis;
4-
using System.Runtime.CompilerServices;
2+
using System;
3+
using System.Linq;
4+
using System.Threading;
5+
using System.Threading.Tasks;
56

6-
args = ["cmd-a", "--x", "10", "--y", "20", "--int-parameter", "1000"];
7-
8-
var app = ConsoleApp.Create();
9-
10-
// builder: Func<ref ConsoleApp.GlobalOptionsBuilder, object>
11-
app.ConfigureGlobalOptions((ref builder) =>
12-
{
13-
var dryRun = builder.AddGlobalOption<bool>("--dry-run");
14-
var verbose = builder.AddGlobalOption<bool>("-v|--verbose");
15-
var intParameter = builder.AddRequiredGlobalOption<int>("--int-parameter", "integer parameter");
16-
17-
// return value stored to ConsoleAppContext.GlobalOptions
18-
return new GlobalOptions(dryRun, verbose, intParameter);
19-
});
20-
21-
app.ConfigureServices((context, _, services) =>
7+
public static class Program
228
{
23-
// store global-options to DI
24-
var globalOptions = (GlobalOptions)context.GlobalOptions;
25-
services.AddSingleton(globalOptions);
26-
27-
// check global-options value to configure services
28-
//services.AddLogging(logging =>
29-
//{
30-
// if (globalOptions.Verbose)
31-
// {
32-
// logging.SetMinimumLevel(LogLevel.Trace);
33-
// }
34-
//});
35-
});
9+
public static void Main(string[] args)
10+
{
11+
var app = ConsoleApp.Create();
3612

37-
app.ConfigureLogging((context, _, services) =>
38-
{
39-
});
13+
app.Add("", (CancellationToken cancellationToken, ConsoleAppContext ctx) => { });
4014

41-
app.Add<Commands>();
15+
app.Run(args, CancellationToken.None);
4216

43-
app.Run(args);
17+
}
18+
}
4419

45-
internal record GlobalOptions(bool DryRun, bool Verbose, int IntParameter);
20+
internal record GlobalOptions(string Flag);
4621

47-
// get GlobalOptions from DI
48-
internal class Commands(GlobalOptions globalOptions)
22+
internal class Commands
4923
{
50-
[Command("cmd-a")]
51-
public void CommandA(int x, int y)
24+
[Command("some-command")]
25+
public void SomeCommand([Argument] string commandArg, ConsoleAppContext context)
5226
{
53-
Console.WriteLine("A:" + globalOptions + ":" + (x, y));
27+
Console.WriteLine($"ARG: {commandArg}");
28+
Console.WriteLine($"ESCAPED: {string.Join(", ", context.EscapedArguments.ToArray()!)}");
5429
}
30+
}
5531

56-
[Command("cmd-b")]
57-
public void CommandB(int x, int y)
32+
internal class SomeFilter(ConsoleAppFilter next) : ConsoleAppFilter(next)
33+
{
34+
public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken)
5835
{
59-
Console.WriteLine("B:" + globalOptions + ":" + (x, y));
36+
Console.WriteLine($"FLAG: {((GlobalOptions)context.GlobalOptions!).Flag}");
37+
await Next.InvokeAsync(context, cancellationToken);
6038
}
6139
}

src/ConsoleAppFramework.Abstractions/ConsoleApp.Abstractions.cs

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,88 @@ public interface IArgumentParser<T>
77
static abstract bool TryParse(ReadOnlySpan<char> s, out T result);
88
}
99

10+
/// <summary>
11+
/// Represents the execution context for a console application command, containing command metadata and parsed arguments.
12+
/// </summary>
1013
public record ConsoleAppContext
1114
{
15+
/// <summary>
16+
/// Gets the name of the command being executed.
17+
/// </summary>
1218
public string CommandName { get; init; }
13-
public string[] Arguments { get; init; }
19+
20+
/// <summary>
21+
/// Gets the raw arguments passed to the application, including the command name itself.
22+
/// </summary>
23+
public ReadOnlyMemory<string> Arguments { get; init; }
24+
25+
/// <summary>
26+
/// Gets the custom state object that can be used to share data across commands.
27+
/// </summary>
1428
public object? State { get; init; }
29+
30+
/// <summary>
31+
/// Gets the parsed global options that apply across all commands.
32+
/// </summary>
1533
public object? GlobalOptions { get; init; }
1634

35+
/// <summary>
36+
/// Gets the depth of the command in a nested command hierarchy. Used internally by the framework.
37+
/// </summary>
1738
[EditorBrowsable(EditorBrowsableState.Never)]
1839
public int CommandDepth { get; }
1940

41+
/// <summary>
42+
/// Gets the index of the escape separator ('--') in the arguments, or -1 if not present. Used internally by the framework.
43+
/// </summary>
2044
[EditorBrowsable(EditorBrowsableState.Never)]
2145
public int EscapeIndex { get; }
2246

47+
/// <summary>
48+
/// Gets the internal command arguments with global options removed. Used internally by the framework.
49+
/// </summary>
2350
[EditorBrowsable(EditorBrowsableState.Never)]
24-
public string[] InternalCommandArgs { get; }
51+
public ReadOnlyMemory<string> InternalCommandArgs { get; }
2552

53+
/// <summary>
54+
/// Gets the arguments intended for the current command, excluding the command name and any escaped arguments after '--'.
55+
/// </summary>
2656
public ReadOnlySpan<string> CommandArguments
2757
{
2858
get => (EscapeIndex == -1)
29-
? Arguments.AsSpan(CommandDepth)
30-
: Arguments.AsSpan(CommandDepth, EscapeIndex - CommandDepth);
59+
? Arguments.Span.Slice(CommandDepth)
60+
: Arguments.Span.Slice(CommandDepth, EscapeIndex - CommandDepth);
3161
}
3262

63+
/// <summary>
64+
/// Gets the arguments that appear after the escape separator ('--'), which are not parsed by the command.
65+
/// Returns an empty span if no escape separator is present.
66+
/// </summary>
3367
public ReadOnlySpan<string> EscapedArguments
3468
{
3569
get => (EscapeIndex == -1)
3670
? Array.Empty<string>()
37-
: Arguments.AsSpan(EscapeIndex + 1);
71+
: Arguments.Span.Slice(EscapeIndex + 1);
3872
}
3973

40-
public ConsoleAppContext(string commandName, string[] arguments, string[] commandArgs, object? state, object? globalOptions, int commandDepth, int escapeIndex)
74+
public ConsoleAppContext(string commandName, ReadOnlyMemory<string> arguments, ReadOnlyMemory<string> internalCommandArgs, object? state, object? globalOptions, int commandDepth, int escapeIndex)
4175
{
4276
this.CommandName = commandName;
4377
this.Arguments = arguments;
44-
this.InternalCommandArgs = commandArgs;
78+
this.InternalCommandArgs = internalCommandArgs;
4579
this.State = state;
4680
this.GlobalOptions = globalOptions;
4781
this.CommandDepth = commandDepth;
4882
this.EscapeIndex = escapeIndex;
4983
}
5084

85+
/// <summary>
86+
/// Returns a string representation of all arguments joined by spaces.
87+
/// </summary>
88+
/// <returns>A space-separated string of all arguments.</returns>
5189
public override string ToString()
5290
{
53-
return string.Join(" ", Arguments);
91+
return string.Join(" ", Arguments.ToArray());
5492
}
5593
}
5694

0 commit comments

Comments
 (0)