Skip to content

Commit c995b53

Browse files
committed
Improve help text output
1 parent 738c89a commit c995b53

File tree

6 files changed

+70
-16
lines changed

6 files changed

+70
-16
lines changed

src/InEngine.Commands/Sample/Minimal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace InEngine.Commands.Sample
1111
*/
1212
public class Minimal : AbstractCommand
1313
{
14-
public void Run()
14+
public override void Run()
1515
{
1616
}
1717
}

src/InEngine.Commands/Sample/RegisterCommands.cs renamed to src/InEngine.Commands/Sample/SampleCommandsPlugin.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
namespace InEngine.Commands.Sample
55
{
6-
public class RegisterCommands : AbstractPlugin
6+
public class SampleCommandsPlugin : AbstractPlugin
77
{
88
[VerbOption("sample:show-progress", HelpText = "A sample command to demonstrate the progress bar.")]
99
public ShowProgress ShowProgress { get; set; }
1010

1111
[VerbOption("sample:say-hello", HelpText = "A sample command to say \"hello\".")]
1212
public SayHello SayHello { get; set; }
1313

14-
[VerbOption("sample:minimal")]
14+
[VerbOption("sample:minimal", HelpText = "A minimal implementation of a command - does nothing.")]
1515
public Minimal Minimal { get; set; }
1616
}
1717
}

src/InEngine.Core/AbstractPlugin.cs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using CommandLine;
35
using CommandLine.Text;
46
using InEngine.Core.Scheduling;
57

68
namespace InEngine.Core
79
{
8-
public class AbstractPlugin : IPlugin
10+
abstract public class AbstractPlugin : IPlugin
911
{
1012
public virtual void Schedule(ISchedule schedule)
1113
{}
@@ -20,9 +22,36 @@ public string GetUsage(string verb)
2022

2123
public virtual string GetUsageWithoutHeader()
2224
{
23-
var helpText = new HelpText();
24-
helpText.AddOptions(this);
25-
return helpText;
25+
var verbs = GetType()
26+
.GetProperties()
27+
.ToList()
28+
.SelectMany(x => {
29+
return x.GetCustomAttributes(typeof(VerbOptionAttribute), true).Select(y => y as VerbOptionAttribute);
30+
});
31+
var maxWidth = 0;
32+
foreach (var verb in verbs)
33+
if (verb.LongName != null && verb.LongName.Length > maxWidth)
34+
maxWidth = verb.LongName.Length;
35+
36+
var helpTextLine = verbs.Select(x => {
37+
var name = (x.LongName ?? "");
38+
var padding = maxWidth - name.Length + 2;
39+
return $" {name}" + string.Join("", Enumerable.Range(0, padding).Select(y => " ")) + (x.HelpText ?? "");
40+
});
41+
42+
return string.Join(Environment.NewLine, helpTextLine);
43+
}
44+
45+
public IList<VerbOptionAttribute> GetVerbOptions()
46+
{
47+
return GetType()
48+
.GetProperties()
49+
.SelectMany(property => {
50+
return property.GetCustomAttributes(typeof(VerbOptionAttribute), true)
51+
.Select(verb => verb as VerbOptionAttribute);
52+
})
53+
.OrderBy(x => x.LongName)
54+
.ToList();
2655
}
2756
}
2857
}

src/InEngine.Core/PluginAssembly.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public List<T> Make<T>() where T : class, IPlugin
3737
{
3838
return Assembly
3939
.GetTypes()
40-
.Where(x => x.IsClass && typeof(T).IsAssignableFrom(x))
40+
.Where(x => x.IsClass && typeof(T).IsAssignableFrom(x) && !x.IsAbstract)
4141
.Select(x => Assembly.CreateInstance(x.FullName) as T)
4242
.ToList();
4343
}
@@ -62,7 +62,7 @@ public static List<PluginAssembly> Load<T>() where T : IPlugin
6262
{
6363
try
6464
{
65-
if (assembly.GetTypes().Any(y => y.IsClass && typeof(T).IsAssignableFrom(y)))
65+
if (assembly.GetTypes().Any(x => x.IsClass && typeof(T).IsAssignableFrom(x) && !x.IsAbstract))
6666
pluginList.Add(new PluginAssembly(assembly));
6767
}
6868
catch (Exception exception)

src/InEngine/ArgumentInterpreter.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,42 @@ public void PrintPluginHelpTextAndExit(PluginAssembly plugin, List<AbstractPlugi
159159
ExitWithSuccess();
160160
}
161161

162-
public void PrintInEngineHelpTextAndExit(List<PluginAssembly> plugins, Options options)
162+
public void PrintInEngineHelpTextAndExit(List<PluginAssembly> pluginAssemblies, Options options)
163163
{
164164
Write.Info(CliLogo);
165165
Write.Text(options.GetUsage(""));
166-
plugins.ForEach(x => {
167-
Write.Warning(x.Name);
168-
x.Plugins.ForEach(y => {
169-
Write.Line(string.Join(Environment.NewLine, y.GetUsageWithoutHeader().Split('\n').Where(s => !string.IsNullOrWhiteSpace(s))))
170-
.Newline();
166+
167+
/*
168+
* Compute the max width of a command verb name to allow for proper padding.
169+
*/
170+
var maxWidth = 0;
171+
pluginAssemblies.ForEach(pluginAssembly => {
172+
pluginAssembly.Plugins.ForEach(plugin => {
173+
foreach (var verb in plugin.GetVerbOptions())
174+
if (verb.LongName != null && verb.LongName.Length > maxWidth)
175+
maxWidth = verb.LongName.Length;
171176
});
172177
});
178+
179+
/*
180+
* Print out each plugin's commands.
181+
*/
182+
pluginAssemblies.ForEach(pluginAssembly => {
183+
Write.Warning(pluginAssembly.Name);
184+
pluginAssembly
185+
.Plugins
186+
.OrderBy(x => x.GetType().Name)
187+
.ToList()
188+
.ForEach(plugin => {
189+
plugin.GetVerbOptions().ToList().ForEach(verb => {
190+
var name = (verb.LongName ?? "");
191+
var padding = new string(' ', maxWidth - name.Length + 2);
192+
Write.InfoText($" {name}")
193+
.Line(padding + (verb.HelpText ?? ""));
194+
});
195+
});
196+
});
197+
173198
ExitWithSuccess();
174199
}
175200
}

src/InEngine/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"InEngine": {
33
"Plugins": [
4-
4+
"InEngine.Commands"
55
],
66
"Mail": {
77
"Host": "localhost",

0 commit comments

Comments
 (0)