Skip to content

Commit

Permalink
Began implementing automatic help text generation
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCahill committed Aug 20, 2023
1 parent 85ddf69 commit d7930e4
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 52 deletions.
8 changes: 4 additions & 4 deletions getopt.net.tests/getopt.net.tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
<PackageReference Include="coverlet.collector" Version="3.2.0"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Expand Down
93 changes: 50 additions & 43 deletions getopt.net/GetOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace getopt.net {

using System.IO;
using System.Text.RegularExpressions;


/// <summary>
/// GetOpt-like class for handling getopt-like command-line arguments in .net.
///
Expand Down Expand Up @@ -61,9 +61,9 @@ public partial class GetOpt {
/// </summary>
public const string ArgSplitRegex = @"([\s]|[=])";

/// <summary>
/// A single "at" character.
/// This character is used when <see cref="AllowParamFiles"/> is enabled, to determine whether or not a param file has been passed to getopt.net.
/// <summary>
/// A single "at" character.
/// This character is used when <see cref="AllowParamFiles"/> is enabled, to determine whether or not a param file has been passed to getopt.net.
/// </summary>
public const char SingleAtSymbol = '@';

Expand Down Expand Up @@ -148,9 +148,9 @@ public string[] AppArgs {
/// </remarks>
public bool AllowWindowsConventions { get; set; } = false;

/// <summary>
/// Gets or sets a value indicating whether or not Powershell-style arguments are allowed.
/// This option doesn't conflict with the GNU/POSIX or Windows-style argument parsing and is simply an addition.
/// <summary>
/// Gets or sets a value indicating whether or not Powershell-style arguments are allowed.
/// This option doesn't conflict with the GNU/POSIX or Windows-style argument parsing and is simply an addition.
/// </summary>
/// <remarks >
/// This option is disabled by default.
Expand All @@ -159,11 +159,11 @@ public string[] AppArgs {
/// </remarks>
public bool AllowPowershellConventions { get; set; } = false;

/// <summary>
/// Gets or sets a value indicating whether or not parameter files are accepted as a valid form of input.
///
/// Parameter files are known from some software, such as GCC.
/// A param file can be passed as <code>@/path/to/file</code>.
/// <summary>
/// Gets or sets a value indicating whether or not parameter files are accepted as a valid form of input.
///
/// Parameter files are known from some software, such as GCC.
/// A param file can be passed as <code>@/path/to/file</code>.
/// </summary>
/// <remarks >
/// Param files must follow certain rules, in order to be accepted by getopt.net.
Expand Down Expand Up @@ -661,47 +661,54 @@ protected bool IsShortOption(string arg) {
arg[1] != SingleDash;
}

/// <summary>
/// Gets a value indicating whether or not a given option is a paramfile option.
/// <see cref="AllowParamFiles"/>.
/// </summary>
/// <remarks >
/// If <paramref name="arg"/> is a valid paramfile option, but the file doesn't exist, <paramref name="paramFile"/> will be set to <code>null</code>.
/// Otherwise, <paramref name="paramFile"/> will be set to the path to the file.
/// </remarks>
/// <param name="arg">The argument to check.</param>
/// <param name="paramFile">An out param containing either null or the path to the file.</param>
/// <summary>
/// Gets a value indicating whether or not a given option is a paramfile option.
/// <see cref="AllowParamFiles"/>.
/// </summary>
/// <remarks >
/// If <paramref name="arg"/> is a valid paramfile option, but the file doesn't exist, <paramref name="paramFile"/> will be set to <code>null</code>.
/// Otherwise, <paramref name="paramFile"/> will be set to the path to the file.
/// </remarks>
/// <param name="arg">The argument to check.</param>
/// <param name="paramFile">An out param containing either null or the path to the file.</param>
/// <returns><code>true</code> if the passed argument is a valid paramfile option. <code>false</code> otherwise.</returns>
protected bool IsParamFileArg(string arg, out string? paramFile) {
paramFile = null; // pre-set this so we don't have to do it everywhere
if (string.IsNullOrEmpty(arg) || !AllowParamFiles || arg.Length < 2) { return false; }

if (arg[0] != SingleAtSymbol) { return false; }

arg = arg.TrimStart('@');

if (File.Exists(arg)) {
paramFile = arg;
}

return true;
protected bool IsParamFileArg(string arg, out string? paramFile) {
paramFile = null; // pre-set this so we don't have to do it everywhere
if (string.IsNullOrEmpty(arg) || !AllowParamFiles || arg.Length < 2) { return false; }

if (arg[0] != SingleAtSymbol) { return false; }

arg = arg.TrimStart('@');

if (File.Exists(arg)) {
paramFile = arg;
}

return true;
}

/// <summary>
/// Reads the incoming param file and adds the contents to <see cref="AppArgs"/>
/// </summary>
/// <param name="paramFile">The file to read.</param>
protected void ReadParamFile(FileInfo paramFile) {
if (paramFile == null || !paramFile.Exists) { return; }

var lastIndex = AppArgs.Length;
var lines = File.ReadAllLines(paramFile.FullName);
Array.Resize(ref m_appArgs, lines.Length + AppArgs.Length);

protected void ReadParamFile(FileInfo paramFile) {
if (paramFile == null || !paramFile.Exists) { return; }

var lastIndex = AppArgs.Length;
var lines = File.ReadAllLines(paramFile.FullName);
Array.Resize(ref m_appArgs, lines.Length + AppArgs.Length);

for (int i = lastIndex, j = 0; i < m_appArgs.Length && j < lines.Length; i++, j++) {
m_appArgs[i] = lines[j];
}
}
}

/// <summary>
/// Gets a <see cref="DescriptionGenerator"/> object with all currently configured <see cref="Options"/>
/// </summary>
/// <returns>A new <see cref="DescriptionGenerator"/> instance.</returns>
public DescriptionGenerator GetDescriptionGenerator() => new DescriptionGenerator(Options);

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (6.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 710 in getopt.net/GetOpt.cs

View workflow job for this annotation

GitHub Actions / build (7.0)

The type or namespace name 'DescriptionGenerator' could not be found (are you missing a using directive or an assembly reference?)
}

}

22 changes: 17 additions & 5 deletions getopt.net/Option.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@ public Option() { }
/// <param name="name">The name of the argument.</param>
/// <param name="argType">The argument type.</param>
/// <param name="value">The value of the option.</param>
public Option(string name, ArgumentType argType, char value): this(name, argType, (int)value) { }
/// <param name="description" >A brief description of the parameter.</param>
public Option(string name, ArgumentType argType, char value, string? description = null): this(name, argType, (int)value, description) { }

/// <summary>
/// Constructs a new instance of this struct with an <see cref="int"/> as the value type.
/// </summary>
/// <param name="name"></param>
/// <param name="argType"></param>
/// <param name="value"></param>
public Option(string name, ArgumentType argType, int value) {
/// <param name="name">The name of the argument.</param>
/// <param name="argType">The argument type.</param>
/// <param name="value">The value of the option.</param>
/// <param name="description" >A brief description of the parameter.</param>
public Option(string name, ArgumentType argType, int value, string? description = null) {
Name = name;
ArgumentType = argType;
Value = value;
Description = description;
}

/// <summary>
Expand All @@ -53,6 +56,15 @@ public Option(string name, ArgumentType argType, int value) {
/// </summary>
public int Value { get; set; }

/// <summary>
/// Gets or sets the description for this option.
/// </summary>
/// This property can be used by the <see cref="DescriptionGenerator"/> to generate automatic descriptions for your
/// application.
///
/// <value>The description for this option.</value>
public string? Description { get; set; }

}
}

File renamed without changes.
25 changes: 25 additions & 0 deletions getopt.net/enums/OptionConvention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;

namespace getopt.net {

/// <summary>
/// An enumeration of all supported option conventions supported by the <see cref="DescriptionGenerator" /> class.
/// </summary>
public enum OptionConvention {
/// <summary>
/// Print the help text using options formatted with POSIX/GNU conventions.
/// </summary>
PosixGnuConvention = 0,

/// <summary>
/// Print the help text using options formatted with Windows conventions.
/// </summary>
WindowsConvention = 1,

/// <summary>
/// Print the help text using options formatted with Powershell conventions.
/// </summary>
PowershellConvention = 2
}
}

20 changes: 20 additions & 0 deletions getopt.net/enums/TextAlignment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace getopt.net {

/// <summary>
/// A simple enumeration for text alignment strategies for generating description texts.
/// </summary>
public enum TextAlignment {

LeftAligned = 0,

RightAligned = 1,

Centred = 2,

Centered = 2,

}
}

6 changes: 6 additions & 0 deletions getopt.net/getopt.net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ Changes
<WarningLevel>4</WarningLevel>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<ItemGroup>
<None Remove="enums\" />
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
<None Include="..\LICENSE">
Expand All @@ -68,4 +71,7 @@ Changes
<Using Include="System.Linq" />
</ItemGroup>

<ItemGroup>
<Folder Include="enums\" />
</ItemGroup>
</Project>

0 comments on commit d7930e4

Please sign in to comment.