Skip to content

Commit

Permalink
Merge pull request #8 from GeminiLab/f/hook
Browse files Browse the repository at this point in the history
add parsing hook (close #2)
  • Loading branch information
aarkegz authored Nov 20, 2020
2 parents ab1bcf7 + 94053d4 commit a113eb2
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 1 deletion.
34 changes: 34 additions & 0 deletions XUnitTester/LifecycleHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using GeminiLab.Core2.CommandLineParser;
using GeminiLab.Core2.CommandLineParser.Default;
using Xunit;

namespace XUnitTester {
public static class LifecycleHook {
class HookedOption {
public List<string> Queue { get; set; } = new List<string>();

[PreParsing]
public void PreParsing() {
Queue.Add("pre");
}

[PostParsing]
public void PostParsing() {
Queue.Add("post");
}

[ShortOption('z', OptionParameter.Required)]
public void Zulu(string z) {
Queue.Add($"z:{z}");
}
}

[Fact]
public static void LifecycleHookTest() {
var options = CommandLineParser<HookedOption>.DoParse("-zzulu");

Assert.Equal(new string[] { "pre", "z:zulu", "post" }, options.Queue);
}
}
}
11 changes: 11 additions & 0 deletions src/GeminiLab.Core2.CommandLineParser/CommandLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static T DoParse(params string[] args) {

private List<IOptionCategory> _optionCategories = null!;
private List<(Type ExceptionType, object Handler)> _exceptionHandlers = null!;
private List<IParsingHook> _hooks = null!;

[Obsolete("Use method 'Parse' instead")]
public T ParseFromSpan(ReadOnlySpan<string> args) {
Expand Down Expand Up @@ -172,6 +173,7 @@ private void EvaluateMetaInfo() {

_optionCategories = new List<IOptionCategory>();
_exceptionHandlers = new List<(Type ExceptionType, object Handler)>();
_hooks = new List<IParsingHook>();

var attributes = GetAttributes();

Expand Down Expand Up @@ -211,6 +213,10 @@ private void EvaluateMetaInfo() {
if (ifType == typeof(IOptionCategory)) {
_optionCategories.Add((IOptionCategory) instance);
}

if (ifType == typeof(IParsingHook)) {
_hooks.Add((IParsingHook) instance);
}
}
}
}
Expand All @@ -225,6 +231,8 @@ public T Parse(params string[] args) {
int ptr = 0;
var rv = new T();

_hooks.ForEach(h => h.OnParsingEvent(ParsingEvent.PreParsing, rv));

while (ptr < len) {
var current = workplace[ptr..];
int consumed = 0;
Expand Down Expand Up @@ -267,6 +275,8 @@ public T Parse(params string[] args) {
ptr += consumed;
}

_hooks.ForEach(h => h.OnParsingEvent(ParsingEvent.PostParsing, rv));

return rv;
}

Expand All @@ -277,6 +287,7 @@ private void LoadDefaultConfigs() {
Use<TailArgumentsCategory, TailArgumentsConfig>(new TailArgumentsConfig());
Use<NonOptionArgumentCategory>();

Use<LifecycleHookComponent>();
Use<UnknownOptionHandlerComponent>();
}

Expand Down
10 changes: 10 additions & 0 deletions src/GeminiLab.Core2.CommandLineParser/Custom/IParsingHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace GeminiLab.Core2.CommandLineParser.Custom {
public enum ParsingEvent {
PreParsing,
PostParsing,
}

public interface IParsingHook {
void OnParsingEvent(ParsingEvent parsingEvent, object target);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using GeminiLab.Core2.CommandLineParser.Custom;

namespace GeminiLab.Core2.CommandLineParser.Default {
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class PreParsingAttribute : ParsingAttribute { }


[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class PostParsingAttribute : ParsingAttribute { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using GeminiLab.Core2.CommandLineParser.Custom;

namespace GeminiLab.Core2.CommandLineParser.Default {
public class LifecycleHookComponent : IParsingHook, IAttributeCategory<PreParsingAttribute>, IAttributeCategory<PostParsingAttribute> {
private MethodInfo? _pre, _post;

public void OnParsingEvent(ParsingEvent parsingEvent, object target) {
(parsingEvent switch {
ParsingEvent.PreParsing => _pre,
ParsingEvent.PostParsing => _post,
_ => null,
})?.Invoke(target, Array.Empty<object>());
}

IEnumerable<IAttributeCategory<PreParsingAttribute>.MemberWithAttribute> IAttributeCategory<PreParsingAttribute>.Options {
set { _pre = value.Select(mwa => mwa.Target).OfType<MethodInfo>().FirstOrDefault(); }
}

IEnumerable<IAttributeCategory<PostParsingAttribute>.MemberWithAttribute> IAttributeCategory<PostParsingAttribute>.Options {
set { _post = value.Select(mwa => mwa.Target).OfType<MethodInfo>().FirstOrDefault(); }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
using GeminiLab.Core2.CommandLineParser.Custom;

namespace GeminiLab.Core2.CommandLineParser.Default {
[AttributeUsage(SupportedTargets, AllowMultiple = true)]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class UnknownOptionHandlerAttribute : ParsingAttribute { }
}

0 comments on commit a113eb2

Please sign in to comment.