Monday, January 10, 2011

Using F# 2.0 Powerpack ArgParser from C#

This is an update of the technique mentioned in an antique post by Robert Pickering which was referenced by Laurent Le Brun last summer. I've taken Laurent's example of F# usage and ported it to C# in the most direct fashion:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FSharp.Core;
using Microsoft.FSharp.Text;
namespace fsgetopt
{
class Program
{
static void Main(string[] args)
{
Action<string> compile = (s => Console.WriteLine("Compiling {0}...", s));
var outputName = "a.out";
var verbose = new FSharpRef<bool>(false);
var warningLevel = 0;
ArgInfo[] specs =
{
new ArgInfo("-o",
ArgType.String (FuncConvert.ToFSharpFunc<string> (x => outputName=x)),
"Name of the output"),
new ArgInfo("-v",
ArgType.Set (verbose),
"Display additional information"),
new ArgInfo("--warn",
ArgType.Int (FuncConvert.ToFSharpFunc<int> (x => warningLevel=x)),
"Set warning level"),
new ArgInfo("--",
ArgType.Rest (FuncConvert.ToFSharpFunc<string> (x => Console.WriteLine("rest has {0}", x))),
"Stop parsing command line"),
};
var after = FuncConvert.ToFSharpFunc<string>(compile);
var opt1 = new FSharpOption<FSharpFunc<string, Unit>>(after);
var opt2 = new FSharpOption<string>("Usage options are:");
ArgParser.Parse(specs, opt1, opt2);
Console.WriteLine("outputName = {0}", outputName);
Console.WriteLine("Verbose = {0}", verbose.Value);
Console.WriteLine("Warning level = {0}", warningLevel);
}
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

It is possible to streamline this to hide most of the messy type names inside utilities.

One thing I've not managed to do is get the lambda associated with the ArgType.Rest to fire, even after setting the default handler opt1 to FSharpOption<T>.None. That -- the default handler -- gets fired every time an otherwise unmatched argument is encountered; the ArgType.Rest handler looks from the code like it should "just work" so I'm a bit baffled ATM.

LATER: Mystery solved

Of course, I was testing this at a PowerShell prompt -- and the shell was swallowing the unquoted "--" string : there was no "rest" to operate on.

2 comments :

Anonymous said...

Good morning.
Where do I find the reference for Microsoft.FSharp.Text?
I am using VS10 and have no experience with F#

Thanks
Jda

Steve Gilham said...

The Microsoft.FSharp.Text types are drawn from the F# powerpack main assembly (FSharp.PowerPack.dll). Despite (because of?) all the goodness it contains, this is a separate install to the core F# language support.