Giter Club home page Giter Club logo

argu's Introduction

Argu Build & Tests NuGet Badge

A declarative CLI argument/XML configuration parser / help message generator for F# applications.

Delivered as a netstandard2.0 NuGet package.

Documentation

All documentation and related material can be found here.

Originally created by Eirik Tsarpalis

Maintainers

argu's People

Contributors

0x53a avatar agross avatar bartelink avatar bentayloruk avatar chestercodes avatar cloudroutine avatar ctaggart avatar dependabot[bot] avatar dsyme avatar eiriktsarpalis avatar enricosada avatar forki avatar fpellet avatar gdziadkiewicz avatar haf avatar idealist1508 avatar kleidemos avatar kos59125 avatar lasandell avatar matthid avatar mcon avatar nojaf avatar palladin avatar sergey-tihon avatar somethingawry avatar stmax82 avatar tarmil avatar teadrivendev avatar theimowski avatar vbfox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

argu's Issues

Allow per parser syntax overrides

For example, suppose I want to enforce a syntax like foo=3 bar=v everywhere instead of the default --foo 3 --bar v. Instead of attributing every single case of the union type with EqualsAssignment; AltCommandLine I'd like to do it on the type level or as a configuration argument to UnionArgParser.Create.

May give it a shot if you think it's a good idea.

Signle argument from a group

Hi,

Can you add the support to allow only a single argument from a group?

console.exe --service=service1 // correct
console.exe --module=module1 //correct
console.exe --service=service1 --module=module1 // incorrect as both service and module are present.

Gather unrecognized arguments

I'd like to be able to get a list of all the unrecognized arguments. Think for example of a compiler that takes source file names as plain arguments. A proposal could be something like this:

type Command =
  | [<Unrecognized>] SourceFile of string
  | [<CustomCommandLine "-s">] SomeSwitch

// Example:
[ "foo.fs"; "-s"; "bar.fs" ] => [ SourceFile "foo.fs"; SomeSwitch; SourceFile "bar.fs" ]

A behavior I don't quite get - probably a bug.

Description

I'm trying to achieve the following:

> my.exe do-stuff-1 [--arg1="default 1"] [--arg2="default2"]
> my.exe do-stuff-2 [--arg1="default 1"] [--arg2="default2"] [--arg3="default3"]

Repro steps

The code I am trying to throw on it:

namespace X

open Argu

type AnalyzeArguments = 
    |``Csv-files-location`` of string option
    |OutputPath of string option
with
    interface IArgParserTemplate with
        member s.Usage = 
            match s with
            |``Csv-files-location`` _ -> "Folder which contains XXX database in form of CSV files. Files should be named according to standard convention."
            |OutputPath _ -> "Folder to write analisys results to."

and RandomizeArguments =
    |StatisticFilesLocation of string option
    |OutputPath of string option
with
    interface IArgParserTemplate with
        member s.Usage = 
            match s with
            |StatisticFilesLocation _ -> "Folder which contains results of analize command in the form of json."
            |OutputPath _ -> "Folder to write randomization results to."

and public CliCommands = 
    |[<CliPrefix(CliPrefix.None)>]Analyze of AnalyzeArguments ParseResults
    |[<CliPrefix(CliPrefix.None)>]Randomize of RandomizeArguments ParseResults
with
    interface IArgParserTemplate with
        member s.Usage = 
            match s with
            |Analyze _ -> "Build statistics necessary for XXX data randomization."
            |Randomize _ -> "Produce randomized XXX data."

Expected behavior

Described or close configuration lets all the parameters of the commands to be optional and have default values.

Actual behavior

An exception is thrown here:

let analyze (parseResult : AnalyzeArguments ParseResults) =
    let sourceDir = match parseResult.GetResult<@AnalyzeArguments.``Csv-files-location``@> with Some x -> x |_ -> defaultAnalisysDirectory

Details

Exception message:

Argu.ArguParseException was unhandled
Message: An unhandled exception of type 'Argu.ArguParseException' occurred in Argu.dll
Additional information: ERROR: missing argument '--csv-files-location'.

OPTIONS:

    --csv-files-location [<string>]
                          Folder which contains XXX database in form of CSV
                          files. Files should be named according to standard
                          convention.
    --outputpath [<string>]
                          Folder to write analisys results to.
    --help                display this list of options.

Known workarounds

Unknown - your advise needed.

Related information

  • Windows 8.1
  • .NET Runtime 4.6.1; F# 4.0
  • Package version: 3.7.0

Is there something like a HasFlag?

I have some flags:

    let force = 
        match results.TryGetResult <@ CLIArguments.Force @> with
        | Some _ -> true
        | None -> false

    let hard = 
        match results.TryGetResult <@ CLIArguments.Hard @> with
        | Some _ -> true
        | None -> false

    let installAfterConvert =
        match results.TryGetResult <@ CLIArguments.No_install @> with
        | Some _ -> false
        | None -> true

I would like to write:

    let force = results.HasFlag <@ CLIArguments.Force @>

    let hard = results.HasFlag <@ CLIArguments.Hard @> 

    let installAfterConvert = results.HasFlag <@ CLIArguments.No_install @>

or something like this.

Is this possible?

feat: TypeProvider for command line understandable by Fishshell

Fishshell does next:

Man Page Completions
Man Page Completions Thumbnail Other shells support programmable completions, but only fish generates them automatically by `parsing` your installed man pages.

Let parse these in F# and createTypeProvider which allow to call many native Unix tools more easily by providing more strongly typed API. So F# will be chosen as scripting tool by more Unix users.

Flip this, given some tool with man page, let generate handler for its options. Allows reimplement tools in F# which satisfy same contract. Or start implementing F# tool with man page as declaration of command line args(see how Spec Flow+Cucumber works), and then move to AOT compiled language when needed.

Not sure that some standard exists to declare command line arguments (like it exists for some remote calls technologies), but 2 implementations going same route may end up in some standard (essentially calling process via command line is in many cases is like remote procedure call).

MissingMethodException for UnionArgParser ctor on F# 3.1 runtime

I get this MissingMethodException when using nuget UnionArgParser in a project targeting the F# 3.1 runtime:

Exception:Thrown: "Method not found: 'Void UnionArgParser.UnionArgParser1..ctor(Microsoft.FSharp.Core.FSharpOption1<System.String>, Microsoft.FSharp.Core.FSharpOption1<System.Reflection.BindingFlags>)'." (System.MissingMethodException) A System.MissingMethodException was thrown: "Method not found: 'Void UnionArgParser.UnionArgParser1..ctor(Microsoft.FSharp.Core.FSharpOption1<System.String>, Microsoft.FSharp.Core.FSharpOption1<System.Reflection.BindingFlags>)'."

v3.6.0 broke binary-compat of the type ProcessExiter

image

see 7c245c1#diff-8458428b4857b46da163c13247e42e94R66

In my case this means I can't use Argu >=3.7 in combination with anything MBrace, because MBrace is currently locked at 3.4: https://github.com/mbraceproject/MBrace.Core/blob/b13cde4cf1325bee908a2312b3d86625eb1eb3d1/paket.lock#L5

(It uses the ctor here: https://github.com/mbraceproject/MBrace.Core/blob/b13cde4cf1325bee908a2312b3d86625eb1eb3d1/src/MBrace.Thespian/Worker/Configuration.fs#L52)

Edit: I had to downgrade to 3.5. (3.6 also includes the breaking change)

Hidden inherited arguments loses hidden flag

Description

When you mark an argument with as inherited and hidden ([<Inherit;Hidden>]) like here commands inheriting the argument will report the argument in the help output.

Repro steps

  1. Run paket add --help

  2. Observe the output.

Expected behavior

--from-bootstrapper is omitted like with paket --help.

Actual behavior

--from-bootstrapper is reported as an argument.

feat: Positional arguments

Hi,

how would one create the Argu union for:

git push -f origin master
git push origin master -f

The remote (origin) and branch (master) are positional arguments, i.e. the first and second non-option arguments on the command line.

Having two MainCommands (i.e. parameters without dashes) is not supported.

--help param should be accepted everywhere

In Paket we use the Command model where the command is forced to be the first arg.

paket update --help // displays help

but

paket --help update // crasehes

It would be nice if the special --help flag could be used everywhere.

/cc @dnauck

script support

I would like to have the script support. i.g. That should work:

fsi Main.fsx --help

it is not the case with this usage of argu:

let parser = ArgumentParser.Create<Arguments>()
let args = parser.Parse()

Argu has a large number of dependencies for .Net framework

Description

Argu seems to have a large number of dll dependencies for .Net Framework

Repro steps

  1. Add Argu to a project targeting full .net framework using paket

  2. Around 30 dlls added to references

Expected behavior

Should target .Net framework dlls

Actual behavior

I think its because it has a reference to NETStandard.Library. Other NuGet packages such as FsCheck have another All Frameworks section in NuGet.

Known workarounds

None known

Related information

dep

Modelling nested command

I'd like to model something like the following: -

type RunMode = | Simple | Complex | Super

type FilterArg =
| All
| LowValue of minValue:int
| HighValue of productCode:string

type CLIArgs =
| Mode of RunMode
| Filter of FilterArg

In English first, this is what I want: -

  1. Mode is optional.
  2. Filter is optional.
  3. If the user specifies Filter, they can only specify one filter arg.

Out of the box, the above model won't work, because FilterArg is not supported. I get around this but making a sub-command and wrapping as ParseResults<FilterArg>. e.g.

type CLIArgs =
| Mode of RunMode
| Filter of ParseResults<FilterArg>

The problems are: -

  1. It appears that you can't enforce unique + single commands for a subcommand.
  2. You are allowed to enter a command like app.exe filter with no actual filter.
  3. The object model seems set up to work with a "multiple types of filters can be supplied" mode.

I'm working around all this by manually pattern matching on the results myself e.g.

    let filter =
        match results.TryGetResult(<@ Filter @>) |> Option.map (fun f -> f.GetAllResults()) with
        | Some [ filter ] -> filter
        | None -> All
        | Some [] -> failwith "No filter argument supplied."
        | Some _ -> failwith "Too many filter arguments. Only one should be provided."

ideally I would like to model the above constraints within Argu.

Subparser support

Python's 'argparse' (in standard library) supports subparsers that allow you to to specify a command (think "git commit"), and the command line arguments are parsed based on the selected command.

See:

https://docs.python.org/2/library/argparse.html#sub-commands

It would be handy for UnionArgParser to support similar functionality out of the box (for generated "usage" etc).

Unparsed arguments should be available

Description

Please provide a succinct description of your issue.

Repro steps

Please provide the steps required to reproduce the problem

  1. Step A
  2. Step B

Expected behavior

Please provide a description of the behavior you expect.

Actual behavior

Please provide a description of the actual behavior you observe.

Known workarounds

Please provide a description of any known workarounds.

Related information

  • Operating system
  • Branch
  • .NET Runtime, CoreCLR or Mono Version
  • Performance information, links to performance testing scripts

Build: tests failing on mono 3.6, CentOS 6.5, F# 3.1

https://tc-oss.intelliplan.net/viewLog.html?buildId=457&buildTypeId=FSharp_UnionArgParser_Build&tab=buildLog

Snip:

[20:53:15][Step 1/1] 1) System.Exception: NUnit test failed (10).
[20:53:15][Step 1/1] at Fake.NUnitSequential.NUnit (Microsoft.FSharp.Core.FSharpFunc`2 setParams, IEnumerable`1 assemblies) [0x00000] in <filename unknown>:0
[20:53:15][Step 1/1] at [email protected] (Microsoft.FSharp.Core.Unit _arg3) [0x00000] in <filename unknown>:0
[20:53:15][Step 1/1] at Fake.TargetHelper+targetFromTemplate@145[Microsoft.FSharp.Core.Unit].Invoke (Microsoft.FSharp.Core.Unit unitVar0) [0x00000] in <filename unknown>:0
[20:53:15][Step 1/1] at Fake.TargetHelper.runTarget@314 (System.String targetName) [0x00000] in <filename unknown>:0

I've set this up free of charge because I use this software at work and I have an interest in it being stable. If you sign up with a user and e-mail I can make you the administrator of your project which will let you get e-mail when something breaks.

Relevant to fsharp/fsharp#317

Release 1.0?

We are very happy with UnionArgParser and use it in production. Any idea when it may get released in 1.0? I'm asking because in upgrading from 0.8.7 to 0.9.0 I ran into a breaking renaming, which is allowed under the rules of semantic versioning before 1.0, but would like to see this stabilized because we do use it in production.

Parsing IPv6 as argument value

I'm trying to pass an IP address to my service:

--listen "[::]" 

But it's failing with Error parsing '--listen': unexpected split result '[|"["; ""; "]"|]' for string [::].

Parameters from ENV

Description

I'd like to use Argu to optionally take configuration from the environment. Do you think you could add that feature?

Currently writing a networked-linux tutorial and figured I wanted to showcase how to build micro-services with F#.

MissingMethodException

I'm trying to use Argu 2.0.0 in my simple f# app, this is probably completely stupid, but I'm getting this:

C:\projects\Merger\bin\Release>.\Merger.exe --help

Unhandled Exception: System.MissingMethodException: Method not found: 'Argu.ArgumentParser`1<!!0> Argu.ArgumentParser.Create(Microsoft.FSharp.Core.FSharpOption`1<System.String>)'.
   at Program.main(String[] args)

Does this make any sense? I have a feeling its a weird build issue.

I obviously have everyhing in place:

C:\projects\Merger\bin\Release>dir Argu.dll
 Volume in drive C is BOOT
 Volume Serial Number is 7865-D5E5

 Directory of C:\projects\Merger\bin\Release

08/01/2016  13:07           130,048 Argu.dll
               1 File(s)        130,048 bytes
               0 Dir(s)  106,731,888,640 bytes free

Any ideas how I could have botched it up?

Argu PrintCommandLineArgumentsFlat does not correctly escape spaces

Description

PrintCommandLineArgumentsFlat does not correctly escape spaces.

Repro steps

Run the following program and pass the generated string to a new process.

open Argu

type CLIArguments =
| [<Mandatory>] Path of string
with
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | Path _ -> "Bla"

[<EntryPoint>]
let main argv =
    let parser = ArgumentParser.Create<CLIArguments>()
    let line = parser.PrintCommandLineArgumentsFlat([ Path("Some string with spaces") ])
    printfn "%s" line
    0 // return an integer exit code

It prints --path 'Some string with spaces' (note the single-quotes).

Expected behavior

I would expect argv to contain two strings: --path and Some string with spaces

Actual behavior

Please provide a description of the actual behavior you observe.

image

Known workarounds

I guess I could use PrintCommandLineArguments, which returns an array, and manually escape that.

Related information

  • Operating system: Windows
  • Branch: Version 3.7 from Nuget
  • .NET Runtime, CoreCLR or Mono Version: full FX
  • Performance information, links to performance testing scripts

Named union args don't show names in usage text

Given arguments like these:

  type Arguments = 
       | [<Mandatory>] Input of string
       | [<Mandatory>] SqlConnection of sqlServer:string * sqlDatabase:string
       | SqlCredentials of sqlUser:string * sqlPassword:string
  with
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | Input _ -> "The input file to read"
            | SqlConnection _ -> "The sql server and database."
            | SqlCredentials _ -> "User and password for the database. If not given, Windows authentication is assumed."

The usage text becomes this:

        --input <string>: The input file to read
        --sqlconnection <string> <string>: The sql server and database.
        [--sqlcredentials <string> <string>]: User and password for the database.
If not given, Windows authentication is assumed.
        --help [-h|/h|/help|/?]: display this list of options.

In the tutorial it seems like sqlServer and sqlDatabase should be displayed in the usage, but they are not.

Allow to wordwrap PrintUsage

I call subParser.PrintUsage(hideSyntax=true) and get:

image

Tried to wordwrap that thing but failed. Maybe you can do it directly in Argu?

Here is a function for wordwrapping

let breakLine(text:string, pos:int, max:int) =
    // Find last whitespace in line
    let mutable i = max - 1
    while i >= 0 && not (Char.IsWhiteSpace(text.[pos + i])) do
        i <- i - 1

    if i < 0 then
        max // No whitespace found; break at maximum length
    else 
        // Find start of whitespace
        while i >= 0 && Char.IsWhiteSpace(text.[pos + i]) do
            i <- i - 1
        // Return length of text before whitespace
        i + 1

let wordwrap (s:string,width:int,newDelimiter:string) =
    let s = s.Replace("\r\n","\n").Replace("\r","\n")
    let sb = new StringBuilder()

    // Lucidity check
    if width < 1 then s else

    // Parse each line of text
    let mutable pos = 0
    let mutable next = 0

    while pos < s.Length do
        // Find end of line
        let mutable eol = s.IndexOf( '\n', pos )

        if eol = -1 then
            next <- s.Length
            eol <- s.Length
        else
            next <- eol + 1

        // Copy this line of text, breaking into smaller lines as needed
        if eol > pos then
            while eol > pos do 
                let mutable len = eol - pos

                if len > width then
                    len <- breakLine( s, pos, width)

                sb.Append( s, pos, len ) |> ignore
                sb.Append( newDelimiter ) |> ignore

                // Trim whitespace following break
                pos <- pos + len

                while pos < eol && Char.IsWhiteSpace( s.[pos] ) do
                    pos <- pos + 1

        else 
            sb.Append( newDelimiter ) |> ignore // Empty line

        pos <- next


    sb.ToString()

SubCommands from a config file

Is it possible to read SubCommands from the .config file? I’ve tried to use PrintAppSettingsArguments to see how structure the xml but it seems to skip over any SubCommands:

type SubCommand =
    | Command of string
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | _ -> ""

type Arguments = 
    | Mode of string
    | Sub_Command of ParseResults<SubCommand>
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | _ -> ""

let argumentParser = ArgumentParser.Create<Arguments>()
let arguments = argumentParser.Parse([|"--mode"; "mode1"; "--sub-command"; "--command"; "command1"|])
let cli = argumentParser.PrintCommandLineArgumentsFlat(arguments.GetAllResults())
let config = argumentParser.PrintAppSettingsArguments(arguments.GetAllResults(), false)

printfn "cli: %s" cli
printfn "config: %s" config

Output:

cli: --mode mode1 --sub-command --command command1
config: <?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="mode" value="mode1" />
  </appSettings>
</configuration>

Attribute First is not printed correctly on help screen

Description

When i do myprogram.exe --help i get the following output

USAGE: DogCatapult.exe [--help] [--comment [<comment>]] [--status [<status>]] <id>´

but the annotation for id is:

[<MainCommand; ExactlyOnce; First>] Issue of id:string

The first is not represented in the help text but when trying to parse it is recognized.

DogCatapult.exe -c "Test" ABC-123
ERROR: argument '<id>' should precede all other arguments.
USAGE: DogCatapult.exe [--help] [--comment [<comment>]] [--status [<status>]] <id>

Q: Should calling --help throw an exception?

According to the Usage() --help is a valid command line parameter. This makes me think that I can call it to get help menu.

// get usage text
let usage = parser.Usage()
// output:
//    --working-directory <string>: specify a working directory.
//    --listener <host:string> <port:int>: specify a listener (hostname : port).
//    --log-level <int>: set the log level.
//    --detach: detach daemon from console.
//    --help [-h|/h|/help|/?]: display this list of options.

However, test 3 states that calling --help throws an exception.

    let ``03. Help String`` () =
        fun () -> parser.ParseCommandLine [| "--help" |] |> ignore
        |> should throw typeof<ArgumentException>

Is documentation correct?

Marking any fields as mandatory breaks the --help option

Once you've added any mandatory fields, you can no longer call your executable with just the --help option as it causes a parsing error.

I'll try and put together a pull request over the next week or so if no one else get's there first.

ignore unrecognized arguments

Please add the option to ignore unrecognized arguments when parsing.

In my scenario I wrap a console app and I would like to pass through the arguments that I don't care about.

Best,

Ido

New library name?

I think that the library would definitely benefit from having a better name. Could anybody of the more creatively minded members of the community make a suggestion?

Who uses UnionArgParser?

I have created a new section in the mains docs page. If you have used and enjoyed UnionArgParser, why not list your own project and/or testimonial? You can either directly submit a pull request here or reply here and I will add it myself.

Support for obsolete arguments

To phase out the non-GNU parameter style of Paket we need to mark certain argument styles as obsolete.

Let's take paket add for example.

  • The current style is this: paket add nuget foo group Main version 1.0 --force
  • We would like to support this: paket add foo --group Main --version 1.0 --force

While we want to support the new style in the next major Paket version the old syntax should still be supported (for tooling like Ionide). Additionally, the old style should not be printed in the --help text. If someone uses the old style a warning should be issued to stderr (during parsing).

It seems we would require a new attribute (or attribute flag of CustomCommandLineAttribute?) to mark certain argument styles obsolete.

Currently, even before the GNU-style conversion, there are some arguments that are marked as obsolete in the help text, so I think it would be beneficial to have something like this.

I tried compiling Argu with VS 2017 but it failed with Argu.fsproj : error MSB4057: The target "Build" does not exist in the project..

// @forki

Regex attribute thoughts

I was thinking of getting to know the UnionArgParser code in order to add a RegexValidatorAttribute that would be used to check an argument in its string form, before parsing to the expected primitive type. I am award of the post-processing example but thought a regex attribute might be a nice addition.

Thoughts?

Nullary subcommands

Currently the only way to create a subcommand is by passing an argument of type ParseResults<_> to the union case. But it would also be useful to have nullary subcommands, ie. subcommands that do not take any argument. For example:

type MainArgs =
    // A classic subcommand
    | Push of ParseResults<PushArgs>
    // A nullary subcommand
    | [<SubCommand>] Version

and PushArgs = ...

[<SubCommand>] would be practically equivalent to [<Last>], except it would also be returned by TryGetSubCommand() and listed as a subcommand in the usage.

ArumentParser.Parse cannot process configs of assembly

ArumentParser.ParseAppSettings cannot process xml file or assembly but seems that ArumentParser.Parse can process only xml file. Assembly processing may be useful if I want to use command line and default App.config for argument specification.

Incorrect usage printed for EqualsAssignment parameters

Given a program "azmon",

type Arguments =
    | [<EqualsAssignment>] Source of string
    | [<EqualsAssignment>] Sink of string
    | Stop
with
    interface IArgParserTemplate with
        member s.Usage =
            match s with
                | Source _ -> "Publish events from a named event source"
                | Sink _ -> "Only support HTTP URLs at the moment"
                | Stop -> "Stop listening to events (affects ALL running azmon processes)"

gives usage

    --source <string>: Publish events from a named event source
    --sink <string>: Only support HTTP URLs at the moment
    --stop: Stop listening to events (affects ALL running azmon processes)
    --help [-h|/h|/help|/?]: display this list of options.

which suggests that I can run azmon --source Thing. However, this raises a NullReferenceException (*) because I should say azmon --source=Thing (because of the [<EqualsAssignment>]).

So the usage string should actually say `--source=``.

(*) Stack trace:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at Nessos.UnionArgParser.Parsers.parseCommandLinePartial$cont@78[Template](CliParseState`1 state, FSharpRef`1 position, String name, FSharpOption`1 equalityParam, FSharpOption`1 matchVa
lue, Unit unitVar) in c:\Users\eirik\Development\nessos\UnionArgParser\src\UnionArgParser\Parsers.fs:line 87
   at Nessos.UnionArgParser.Parsers.parsePartial@122[Template](CliParseState`1 state) in c:\Users\eirik\Development\nessos\UnionArgParser\src\UnionArgParser\Parsers.fs:line 125
   at Nessos.UnionArgParser.UnionArgParser`1.Parse(FSharpOption`1 inputs, FSharpOption`1 xmlConfigurationFile, FSharpOption`1 errorHandler, FSharpOption`1 ignoreMissing, FSharpOption`1 ign
oreUnrecognized, FSharpOption`1 raiseOnUsage) in c:\Users\eirik\Development\nessos\UnionArgParser\src\UnionArgParser\UnionArgParser.fs:line 136
   at azmon.main(String[] argv) in C:\Users\frsheara\Documents\git\azmon\src\azmon\Program.fs:line 57

Does not work in F# 3.1 project

It compiles but in runtime, I get:

System.MissingMethodException: Method not found: 'Void UnionArgParser.UnionArgParser`1..ctor(Microsoft.FSharp.Core.FSharpOption`1<System.String>, Microsoft.FSharp.Core.FSharpOption`1<System.Reflection.BindingFlags>)'.
   at <StartupCode$Skrapa>.$Skrapa..cctor()

arguments syntax

Will it be possible to add the support for the '=' syntax?

console.exe --directory=c:\test --listen=192.168.1.2:9090

Best,

Ido

Type Support Beyond Primitives

I hacked together a workaround of the restriction that only primitive types can be used in the argument parser so that any type 'T with the static member Parse:string->'T would be viable.

It lets you write arg parsers like :

type BOOM (str) =
    override __.ToString() = str
    static member Parse str =
        match str:string with
        | "boom" | "Boom" -> BOOM str
        | "BOOM" -> BOOM "GOES THE DYNAMITE"
        | _      -> failwith "can't go BOOM"

type POW (str) =
    override __.ToString() = str
    static member Parse str =
        match str:string with
        | "pow" | "Pow" | "POW" -> POW str
        | "explode" -> POW "MUSIC MAKES YOU LOSE CONTROL"
        | _     -> failwith "got no POW"


let trickyDict = 
    parserDict [ 
        mkComplexParser<BOOM> () 
        mkComplexParser<POW> () 
    ]

type CLIArguments =
    | Listener of host:string * port:int
    | Detach | Boom of BOOM | Pow of POW 
with 
    interface IArgParserTemplate with
        member s.Usage =
            match s with
            | Listener _ -> "specify a listener (hostname : port)."
            | Detach _   -> "detach daemon from console."
            | Boom _     -> "when I say boom"
            | Pow _      -> "you say pow"

let parser  = ArgumentParser.Create<CLIArguments>(parserDict=trickyDict)
let usage   = parser.Usage() |> printfn "%A"
let results = parser.Parse([| "--detach" ; "--listener" ; "localhost" ; "8080"; "--pow";"explode";"--boom";"BOOM"|]);;

results.GetAllResults() |> List.iter (printfn "%A")
printfn "%A" <| results.Contains <@ Boom @>;;
(*
    > Listener ("localhost",8080)
    Detach
    Boom GOES THE DYNAMITE
    Pow MUSIC MAKES YOU LOSE CONTROL
    true
*)

let results' = parser.Parse([| "--detach" ; "--listener" ; "localhost" ; "8080"; "--pow";"pow";"--boom";"boom"|])
results'.GetAllResults() |> List.iter (printfn "%A");;
(*
    >
    Listener ("localhost",8080)
    Detach
    Boom boom
    Pow pow
*)

Here's a gist with a rough overview of what I changed to implement this

I was hoping for some feedback about whether you're open to adding this functionality before I submitted a PR.

If you're open to this addition, is there a different type of implementation you'd prefer? I had to change a bunch of access restrictions to make ParserInfo available and I wasn't sure if there was some important reason why it shouldn't be exposed that I overlooked.

( the actual PR won't be this silly 😉 )

Parser throws on missing mandatory argument when usage is requested

type Args =
    | [<Mandatory>] X of string
with 
    interface IArgParserTemplate with 
        member this.Usage = ""

let parser = UnionArgParser.Create<Args>()

parser.Parse(raiseOnUsage = false, inputs = [|"--help"|])

throws

System.ArgumentException: missing parameter '--x'.

    --x <string>: 
    --help [-h|/h|/help|/?]: display this list of options.

   at Nessos.UnionArgParser.ExceptionExiter.Nessos-UnionArgParser-IExiter-Exit[b](String msg, FSharpOption`1 _arg1) in c:\Users\eirik\Development\nessos\UnionArgParser\src\UnionArgParser\Types.fs:line 28
   at Nessos.UnionArgParser.UnionArgParser`1.Parse(FSharpOption`1 inputs, FSharpOption`1 xmlConfigurationFile, FSharpOption`1 errorHandler, FSharpOption`1 ignoreMissing, FSharpOption`1 ignoreUnrecognized, FSharpOption`1 raiseOnUsage) in c:\Users\eirik\Development\nessos\UnionArgParser\src\UnionArgParser\UnionArgParser.fs:line 136

Question:

Is there a way to support a verb syntax? e.g. by nested DUs or something.

We have a tool that needs verbs like

git pull blabla

Is this possible? Or what would need to change to support that (I might be able to give it upstream, if I knew what needs extension)

Support for .NET 3.5

The current Nuget package does not have any lib folder for .NET 3.5, which leaves us poor souls condemned to the past, to also be deprived of this wonderful library. Is .NET 3.5 possible or is there a reason you don't have it?

Parsing discriminated union cases containing Option types

| Url of string * string option

This currently throws an exception saying that Option is not supported. It would be sometimes handy if I could use such an union for parsing and be given a tuple with the second value of None if it was only possible to retrieve a single string or Some of string otherwise.

Usage string should display brackets for optional parameters

It is customary to display optional parameters with brackets:

        --input <string>: The input file to read
        --sqlconnection <string> <string>: The sql server and database.
        [--sqlcredentials <string> <string>]: User and password for the database.
If not given, Windows authentication is assumed.
        --help [-h|/h|/help|/?]: display this list of options.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.