Skip to content

Commit

Permalink
Added support for param files (#28)
Browse files Browse the repository at this point in the history
* Added support for Powershell-convention options.

* Updated project file

* Updated changelog

* Updated README

* Began adding support for param files

* Began implementing support for param files.

* Adding paramfile parsing.

* Added tests for paramfile parsing. For some reason, TestParseParamFile() causes the test case to crash.

* I fixed the infinite recursion. Whoops.

* Updated reference implementations to add support for Powershell and Windows conventions.
Also added support for paramfile args.

* Added comment clarifying test.

* Updated changelog, README and project file.

* Fixed compiler warnings.
Added support for net46 and 60 to reference implementations.

* Fixed merge error

---------

Signed-off-by: SimonC <[email protected]>
Co-authored-by: Simon Cahill <[email protected]>
  • Loading branch information
SimonCahill and Simon Cahill committed Apr 20, 2023
1 parent 1bd2a34 commit 7a14012
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 31 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.cs]

# Default severity for analyzer diagnostics with category 'Style'
dotnet_analyzer_diagnostic.category-Style.severity = none
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# getop.net changelog

# v0.8.0

Version 0.8.0 introduces a non-breaking change which enables support for paramfiles!

Some applications, notably GCC, use paramfiles as a way to pass a large amount of options and arguments to an application.
Paramfiles are line-separated lists of arguments and can be enabled by setting `AllowParamFiles = true`.
Each line in the paramfile will be parsed as if it were passed directly to getopt.net!
To allow Powershell or Windows conventions, you will still need to enable `AllowWindowsConventions` or `AllowPowershellConventions` respectively.

## Changes
- Added support for paramfiles
- Updated reference implementations

# v0.7.0

Version 0.7.0 introduces a non-breaking change which enables support for Powershell-style options!
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ There are several methods of installing and using getopt.net in your project.
- `-myoption argument`
- `-myoption` `argument`

### Support for paramfiles

Some applications, such as GCC, allow passing of paramfile arguments.
A paramfile is a line-separated text file which contains one option (and argument) per line.
Each line of the paramfile is parsed as if it were passed to getopt.net directly.

Syntax:
```
myapp @/path/to/paramfile
```

### The standard getopt shortopt-string format is supported:

`:` denotes a **required** argument!
Expand Down
29 changes: 26 additions & 3 deletions getopt.net.reference.cs/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace getopt.net.reference.cs {
using System;

namespace getopt.net.reference.cs {

using System.IO;

internal class Program {

Expand All @@ -10,7 +14,10 @@ internal class Program {
new Option("version", ArgumentType.None, 'v'),
new Option("file", ArgumentType.Required, 'f')
},
ShortOpts = "hvf:t;" // the last option isn't an error!
ShortOpts = "hvf:t;", // the last option isn't an error!
AllowParamFiles = true,
AllowWindowsConventions = true,
AllowPowershellConventions = true
};

var optChar = 0;
Expand Down Expand Up @@ -60,16 +67,32 @@ internal class Program {
myapp -f /path/to/file
myapp --file=/path/to/file
myapp --file /path/to/file

myapp @/path/to/paramfile # load all args from param file

Arguments:
--help, -h Displays this menu and exits
/help, /h Displays this menu and exits (Windows conventions)
-help, -h Displays this menu and exits (Powershell conventions)

--version, -v Displays the version and exits
/version, /v Displays the version and exits (Windows conventions)
-version, -v Displays the version and exits (Powershell conventions)

--file=<>, -f<> Reads the file back to stdout.
--file <>, -f<> Reads the file back to stdout.
--file:<>, -f<> Reads the file back to stdout. (Windows arg conventions)
/file=<>, /f<> Reads the file back to stdout. (Windows opt and GNU/POSIX arg conventions)
/file <>, /f<> Reads the file back to stdout. (Windows opt and GNU/POSIX arg conventions)
/file:<>, /f<> Reads the file back to stdout. (Windows conventions)
-file=<>, -f<> Reads the file back to stdout. (Powershell opt and GNU/POSIX arg conventions)
-file <>, -f<> Reads the file back to stdout. (Powershell opt and GNU/POSIX arg conventions)
-file:<>, -f<> Reads the file back to stdout. (Powershell opt and Windows arg conventions)
""");
}

static void PrintVersion() {
Console.WriteLine("myapp v1.0.0");
Console.WriteLine("myapp v0.8.0");
}
}
}
5 changes: 3 additions & 2 deletions getopt.net.reference.cs/getopt.net.reference.cs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFrameworks>net6.0;net7.0;net46;</TargetFrameworks>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>myapp</AssemblyName>
<LangVersion>11</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
29 changes: 24 additions & 5 deletions getopt.net.reference.vb/Program.vb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ Module Program
Dim getopt = New GetOpt With {
.AppArgs = args,
.Options = _progOptions,
.ShortOpts = _progShortOptions
.ShortOpts = _progShortOptions,
.AllowParamFiles = True,
.AllowPowershellConventions = True,
.AllowWindowsConventions = True
}

Dim optChar = 0
Expand Down Expand Up @@ -76,14 +79,30 @@ Usage:
myapp --file=/path/to/file
myapp --file /path/to/file

myapp @/path/to/paramfile # load all args from param file

Arguments:
--help, -h Displays this text and exits
--version, -v Displays the version and exits
--file=[file], -f Reads a file and outputs its contents
--help, -h Displays this menu and exits
/help, /h Displays this menu and exits (Windows conventions)
-help, -h Displays this menu and exits (Powershell conventions)

--version, -v Displays the version and exits
/version, /v Displays the version and exits (Windows conventions)
-version, -v Displays the version and exits (Powershell conventions)

--file=<>, -f<> Reads the file back to stdout.
--file <>, -f<> Reads the file back to stdout.
--file:<>, -f<> Reads the file back to stdout. (Windows arg conventions)
/file=<>, /f<> Reads the file back to stdout. (Windows opt and GNU/POSIX arg conventions)
/file <>, /f<> Reads the file back to stdout. (Windows opt and GNU/POSIX arg conventions)
/file:<>, /f<> Reads the file back to stdout. (Windows conventions)
-file=<>, -f<> Reads the file back to stdout. (Powershell opt and GNU/POSIX arg conventions)
-file <>, -f<> Reads the file back to stdout. (Powershell opt and GNU/POSIX arg conventions)
-file:<>, -f<> Reads the file back to stdout. (Powershell opt and Windows arg conventions)
")
End Sub

Sub PrintVersion()
Console.WriteLine("myapp (VB) v1.0.0")
Console.WriteLine("myapp (VB) v0.8.0")
End Sub
End Module
2 changes: 1 addition & 1 deletion getopt.net.reference.vb/getopt.net.reference.vb.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>getopt.net.reference.vb</RootNamespace>
<TargetFramework>net7.0</TargetFramework>
<TargetFrameworks>net6.0;net7.0;net46;</TargetFrameworks>
<AssemblyName>myapp</AssemblyName>
</PropertyGroup>

Expand Down
5 changes: 3 additions & 2 deletions getopt.net.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getopt.net.tests", "getopt.
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B994D393-9D31-4B65-BCCB-3FF2ACC910C3}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
CHANGELOG.md = CHANGELOG.md
Doxyfile = Doxyfile
LICENSE = LICENSE
Expand All @@ -17,9 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reference_Implementation", "Reference_Implementation", "{C10BBB00-F878-49DA-A820-096033490427}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "getopt.net.reference.vb", "getopt.net.reference.vb\getopt.net.reference.vb.vbproj", "{37B43EE5-B988-486E-BED9-AA6A5835DC0D}"
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "getopt.net.reference.vb", "getopt.net.reference.vb\getopt.net.reference.vb.vbproj", "{37B43EE5-B988-486E-BED9-AA6A5835DC0D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "getopt.net.reference.cs", "getopt.net.reference.cs\getopt.net.reference.cs.csproj", "{A367E857-0105-4824-B3B7-1334C6C21236}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getopt.net.reference.cs", "getopt.net.reference.cs\getopt.net.reference.cs.csproj", "{A367E857-0105-4824-B3B7-1334C6C21236}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
64 changes: 64 additions & 0 deletions getopt.net.tests/GetOptTests_Inherited.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,70 @@ public class GetOptTests_Inherited: GetOpt {
Assert.IsNull(ShortOptRequiresArg('z'));
}

[TestMethod]
public void TestIsParamFileArg() {
var tmpFile = Path.GetTempFileName();
AllowParamFiles = true;
Assert.IsTrue(IsParamFileArg($"@{tmpFile}", out var paramFile));
Assert.IsNotNull(paramFile);
Assert.IsFalse(string.IsNullOrEmpty(paramFile));
Assert.AreEqual(tmpFile, paramFile);

Assert.IsFalse(IsParamFileArg("--long-opt", out paramFile));
Assert.IsNull(paramFile);

AllowParamFiles = false;
Assert.IsFalse(IsParamFileArg($"@{tmpFile}", out paramFile));
Assert.IsNull(paramFile);
}

[TestMethod]
public void TestParseParamFile() {
var tmpFile = Path.GetTempFileName();
File.WriteAllLines(tmpFile, new[] {
"-1234", "--long"
});
AllowParamFiles = true;
AppArgs = new[] { $"@{ tmpFile }", "--test" };
ShortOpts = string.Empty;
Options = new[] {
new Option("first", ArgumentType.None, '1'),
new Option("second", ArgumentType.None, '2'),
new Option("third", ArgumentType.None, '3'),
new Option("fourth", ArgumentType.None, '4'),
new Option("long", ArgumentType.None, '5'),
new Option("test", ArgumentType.None, 't')
};

ReadParamFile(new FileInfo(tmpFile));
Assert.AreEqual(4, AppArgs.Length);

// NOTE: GetNextOpt calls ReadParamFile too! AppArgs will now contain double the amount of args written to the file :)
char optChar = (char)GetNextOpt(out var optArg);
Assert.AreEqual('t', optChar);
Assert.IsNull(optArg);

optChar = (char)GetNextOpt(out optArg);
Assert.AreEqual('1', optChar);
Assert.IsNull(optArg);

optChar = (char)GetNextOpt(out optArg);
Assert.AreEqual('2', optChar);
Assert.IsNull(optArg);

optChar = (char)GetNextOpt(out optArg);
Assert.AreEqual('3', optChar);
Assert.IsNull(optArg);

optChar = (char)GetNextOpt(out optArg);
Assert.AreEqual('4', optChar);
Assert.IsNull(optArg);

optChar = (char)GetNextOpt(out optArg);
Assert.AreEqual('5', optChar);
Assert.IsNull(optArg);
}

}

}
Loading

0 comments on commit 7a14012

Please sign in to comment.