thinkbeforecoding / Fargo

A functional command line argument parser with builtin completion.
33 stars 7 forks source link

Reading a set of arguments as a list? #6

Open Numpsy opened 5 months ago

Numpsy commented 5 months ago

Hi,

I was just having a go at using Fargo in a simple cli application that is currently using FSharp.SystemCommandLine, and I have a question about reading arguments as a collection -

With FSharp.SystemCommandLine I can define one string argument, and then one argument as an array of strings, such that I can take a command line like

command1 fileName property1 property2 propertyN

and have the data parsed into arg1 = fileName arg2 = [property1, property2, propertyN]

Does Fargo have a way to handle that?

I suppose there's a similar question about options - is it possible to have an option with multiple values that get parsed into a collection automatically? (rather than doing something like having one option with a value of "property1;property2..." and splitting it afterwards)

Thanks.

thinkbeforecoding commented 5 months ago

Hi @Numpsy , did you try with listParse ?

If I understand correctly, these are all arguments without names ?

thinkbeforecoding commented 5 months ago

all also returns all remaining tokens: https://github.com/thinkbeforecoding/Fargo/blob/main/src/Fargo/Fargo.fs#L309C4-L314C1

thinkbeforecoding commented 5 months ago

You can define a many operator like this (and I will add it to the library if it solves your problem):

#r "nuget: Fargo.CmdLine"

open Fargo

let cmd = Fargo.cmd "cmd1" null "some command"
let filename = Fargo.arg "filename" "some filename"
let prop = Fargo.arg "prop" "some prop" |> Fargo.reqArg

let many (arg: Arg<'t>)  =
    let rec findAll tokens result usages =
        match tokens with
        | [] -> Ok (List.rev result), [], usages 
        | _ ->
            match arg.Parse(tokens) with
            | Ok v, tokens, us ->
                findAll tokens (v :: result) (Usages.merge usages us)
            | Error e, tokens, us ->
                Error e, tokens, us

    { Parse = fun tokens -> findAll tokens [] Usages.empty
      Complete = fun i tokens -> 
        match arg.Complete i tokens with
        | [x], b -> [ $"{x}..." ], b
        | r -> r }

let cmdLine =
    fargo {
        match! cmd with
        | _ -> 
            let! file = filename
            let! x = many prop
            return file,x
    }

run "myapp" cmdLine [| "myapp";  "cmd1"; "path"; "x"; "y"; "z"  |](fun ct cmd ->
        task {
            // excution of match commands here...
            printfn "%A" cmd
            return 0
        }
    )
Numpsy commented 5 months ago

Yes, they were all arguments without names.

I think all gives me the data I need, and I'll have a go with the 'many' idea.

did you try with listParse

I saw in mentioned in the readme, but wasn't clear about applying it to plain args rather than piped data.

Actually, on that note the docs mention Pipe.orPipe, but I don't see an orPipe, just an orStdIn ?

Numpsy commented 5 months ago

Ok, it looks like many will work, thanks