Fargo icon indicating copy to clipboard operation
Fargo copied to clipboard

Reading a set of arguments as a list?

Open Numpsy opened this issue 1 year ago • 5 comments

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.

Numpsy avatar Jan 29 '24 12:01 Numpsy

Hi @Numpsy , did you try with listParse ?

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

thinkbeforecoding avatar Jan 31 '24 14:01 thinkbeforecoding

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

thinkbeforecoding avatar Jan 31 '24 14:01 thinkbeforecoding

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
        }
    )

thinkbeforecoding avatar Jan 31 '24 15:01 thinkbeforecoding

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 avatar Jan 31 '24 23:01 Numpsy

Ok, it looks like many will work, thanks

Numpsy avatar Jan 31 '24 23:01 Numpsy