Skip to content

Commit f1bd201

Browse files
committed
show help when nonmatch command
1 parent dc333c3 commit f1bd201

File tree

3 files changed

+134
-97
lines changed

3 files changed

+134
-97
lines changed

sandbox/SingleContainedApp/Program.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ public async Task Timer([Option(0)]uint waitSeconds)
5050

5151
public class OverrideCheck : BatchBase
5252
{
53+
[Command("encode", "encode input string to base64url")]
54+
public void Encode([Option(0)]string input) => Console.WriteLine((input));
55+
56+
[Command("decode", "decode input base64url to string")]
57+
public void Decode([Option(0)]string input) => Console.WriteLine((input));
58+
59+
[Command("escape", "escape base64 to base64url")]
60+
public void Escape([Option(0)]string input) => Console.WriteLine((input));
61+
62+
[Command(new[] { "unescape", "-h" }, "unescape base64url to base64")]
63+
public void Unescape([Option(0)]string input) => Console.WriteLine((input));
64+
5365
[Command(new[] { "help", "-h", "-help", "--help" }, "show help")]
5466
public void Help()
5567
{
@@ -65,7 +77,6 @@ class Program
6577
{
6678
static async Task Main(string[] args)
6779
{
68-
args = new string[] { };
6980
await new HostBuilder().RunBatchEngineAsync<OverrideCheck>(args);
7081
}
7182
}

src/MicroBatchFramework/BatchEngine.cs

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using Microsoft.Extensions.Logging;
2+
using System.Linq;
23
using System;
34
using System.Collections.Generic;
45
using System.Collections.ObjectModel;
56
using System.Reflection;
7+
using System.Text;
68
using System.Threading;
79
using System.Threading.Tasks;
810
using Utf8Json;
@@ -49,23 +51,39 @@ public async Task RunAsync(Type type, string[] args)
4951
}
5052

5153
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
54+
if (methods.Length == 0)
55+
{
56+
await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);
57+
return;
58+
}
59+
60+
MethodInfo helpMethod = null;
5261
foreach (var item in methods)
5362
{
5463
var command = item.GetCustomAttribute<CommandAttribute>();
5564
if (command != null)
5665
{
5766
if (args.Length > 0 && command.EqualsAny(args[0]))
5867
{
68+
// command alias is first priority(if duplicate with MethodName([Command("run")]Run()), okay to execute.
5969
method = item;
6070
argsOffset = 1;
61-
goto RUN;
71+
continue;
72+
}
73+
else
74+
{
75+
if (command.EqualsAny("help"))
76+
{
77+
helpMethod = item;
78+
}
6279
}
6380
}
6481
else
6582
{
6683
if (method != null)
6784
{
68-
goto FAIL;
85+
await SetFailAsync(ctx, "Found duplicate method/command name, name or alias only allows unique name. Type:" + type.FullName + " Method:" + method.Name + " and " + item.Name);
86+
return;
6987
}
7088
method = item;
7189
}
@@ -76,17 +94,25 @@ public async Task RunAsync(Type type, string[] args)
7694
goto RUN;
7795
}
7896

79-
FAIL:
80-
await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);
81-
return;
97+
// completely not found, invalid command name show help.
98+
if (helpMethod != null)
99+
{
100+
method = helpMethod;
101+
goto RUN;
102+
}
103+
else
104+
{
105+
Console.WriteLine(BatchEngine.BuildHelpParameter(methods));
106+
return;
107+
}
82108
}
83109
catch (Exception ex)
84110
{
85111
await SetFailAsync(ctx, "Fail to get method. Type:" + type.FullName, ex);
86112
return;
87113
}
88114

89-
RUN:
115+
RUN:
90116
await RunCore(ctx, type, method, args, argsOffset);
91117
}
92118

@@ -291,5 +317,92 @@ struct OptionParameter
291317
public string Value;
292318
public bool BooleanSwitch;
293319
}
320+
321+
internal static string BuildHelpParameter(MethodInfo[] methods)
322+
{
323+
var sb = new StringBuilder();
324+
foreach (var method in methods.OrderBy(x => x, new CustomSorter()))
325+
{
326+
var command = method.GetCustomAttribute<CommandAttribute>();
327+
if (command != null)
328+
{
329+
sb.AppendLine(string.Join(", ", command.CommandNames) + ": " + command.Description);
330+
}
331+
else
332+
{
333+
sb.AppendLine("argument list:");
334+
}
335+
336+
var parameters = method.GetParameters();
337+
if (parameters.Length == 0)
338+
{
339+
sb.AppendLine("()");
340+
}
341+
342+
foreach (var item in parameters)
343+
{
344+
// -i, -input | [default=foo]...
345+
346+
var option = item.GetCustomAttribute<OptionAttribute>();
347+
348+
if (option != null)
349+
{
350+
if (option.Index != -1)
351+
{
352+
sb.Append("[" + option.Index + "]");
353+
goto WRITE_DESCRIPTION;
354+
}
355+
else
356+
{
357+
sb.Append("-" + option.ShortName.Trim('-') + ", ");
358+
}
359+
}
360+
361+
sb.Append("-" + item.Name);
362+
363+
WRITE_DESCRIPTION:
364+
sb.Append(": ");
365+
366+
if (item.HasDefaultValue)
367+
{
368+
sb.Append("[default=" + (item.DefaultValue?.ToString() ?? "null") + "]");
369+
}
370+
371+
if (option != null && !string.IsNullOrEmpty(option.Description))
372+
{
373+
sb.Append(option.Description);
374+
}
375+
else
376+
{
377+
sb.Append(item.ParameterType.Name);
378+
}
379+
sb.AppendLine();
380+
}
381+
382+
sb.AppendLine();
383+
}
384+
385+
return sb.ToString();
386+
}
387+
388+
class CustomSorter : IComparer<MethodInfo>
389+
{
390+
public int Compare(MethodInfo x, MethodInfo y)
391+
{
392+
var xc = x.GetCustomAttribute<CommandAttribute>();
393+
var yc = y.GetCustomAttribute<CommandAttribute>();
394+
395+
if (xc != null)
396+
{
397+
return 1;
398+
}
399+
if (yc != null)
400+
{
401+
return -1;
402+
}
403+
404+
return x.Name.CompareTo(y.Name);
405+
}
406+
}
294407
}
295408
}

src/MicroBatchFramework/BatchEngineHostBuilderExtensions.cs

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static IHostBuilder UseBatchEngine(this IHostBuilder hostBuilder, string[
3232
var (t, mi) = GetTypeFromAssemblies(args[1]);
3333
if (mi != null)
3434
{
35-
Console.WriteLine(BuildHelpParameter(new[] { mi }));
35+
Console.WriteLine(BatchEngine.BuildHelpParameter(new[] { mi }));
3636
}
3737
else
3838
{
@@ -103,7 +103,7 @@ public static IHostBuilder UseBatchEngine<T>(this IHostBuilder hostBuilder, stri
103103
{
104104
if (!hasHelp)
105105
{
106-
Console.WriteLine(BuildHelpParameter(method));
106+
Console.WriteLine(BatchEngine.BuildHelpParameter(method));
107107
hostBuilder.ConfigureServices(services =>
108108
{
109109
services.AddOptions<ConsoleLifetimeOptions>().Configure(x => x.SuppressStatusMessages = true);
@@ -132,7 +132,7 @@ public static IHostBuilder UseBatchEngine<T>(this IHostBuilder hostBuilder, stri
132132

133133
if (!hasHelp && args.Length == 1 && args[0].Equals(HelpCommand, StringComparison.OrdinalIgnoreCase))
134134
{
135-
Console.WriteLine(BuildHelpParameter(method));
135+
Console.WriteLine(BatchEngine.BuildHelpParameter(method));
136136
hostBuilder.ConfigureServices(services =>
137137
{
138138
services.AddOptions<ConsoleLifetimeOptions>().Configure(x => x.SuppressStatusMessages = true);
@@ -178,73 +178,6 @@ static void ShowMethodList()
178178
}
179179
}
180180

181-
static string BuildHelpParameter(MethodInfo[] methods)
182-
{
183-
var sb = new StringBuilder();
184-
foreach (var method in methods.OrderBy(x => x, new CustomSorter()))
185-
{
186-
var command = method.GetCustomAttribute<CommandAttribute>();
187-
if (command != null)
188-
{
189-
sb.AppendLine(string.Join(", ", command.CommandNames) + ": " + command.Description);
190-
}
191-
else
192-
{
193-
sb.AppendLine("argument list:");
194-
}
195-
196-
var parameters = method.GetParameters();
197-
if (parameters.Length == 0)
198-
{
199-
sb.AppendLine("()");
200-
}
201-
202-
foreach (var item in parameters)
203-
{
204-
// -i, -input | [default=foo]...
205-
206-
var option = item.GetCustomAttribute<OptionAttribute>();
207-
208-
if (option != null)
209-
{
210-
if (option.Index != -1)
211-
{
212-
sb.Append("[" + option.Index + "]");
213-
goto WRITE_DESCRIPTION;
214-
}
215-
else
216-
{
217-
sb.Append("-" + option.ShortName.Trim('-') + ", ");
218-
}
219-
}
220-
221-
sb.Append("-" + item.Name);
222-
223-
WRITE_DESCRIPTION:
224-
sb.Append(": ");
225-
226-
if (item.HasDefaultValue)
227-
{
228-
sb.Append("[default=" + (item.DefaultValue?.ToString() ?? "null") + "]");
229-
}
230-
231-
if (option != null && !string.IsNullOrEmpty(option.Description))
232-
{
233-
sb.Append(option.Description);
234-
}
235-
else
236-
{
237-
sb.Append(item.ParameterType.Name);
238-
}
239-
sb.AppendLine();
240-
}
241-
242-
sb.AppendLine();
243-
}
244-
245-
return sb.ToString();
246-
}
247-
248181
static List<Type> GetBatchTypes()
249182
{
250183
List<Type> batchBaseTypes = new List<Type>();
@@ -315,25 +248,5 @@ static List<Type> GetBatchTypes()
315248

316249
return (null, null);
317250
}
318-
319-
class CustomSorter : IComparer<MethodInfo>
320-
{
321-
public int Compare(MethodInfo x, MethodInfo y)
322-
{
323-
var xc = x.GetCustomAttribute<CommandAttribute>();
324-
var yc = y.GetCustomAttribute<CommandAttribute>();
325-
326-
if (xc != null)
327-
{
328-
return 1;
329-
}
330-
if (yc != null)
331-
{
332-
return -1;
333-
}
334-
335-
return x.Name.CompareTo(y.Name);
336-
}
337-
}
338251
}
339252
}

0 commit comments

Comments
 (0)