Skip to content

Consider Access to the source input #16

Open
@AngelMunoz

Description

@AngelMunoz

Hello Jordan 👋 here I am once again!

I was trying to add tests for my commands and I figure out that one may want to access the source input to do multiple kind of operations on them given that the SLC library seems to use the inputs as contextual information to to either request values or to access the machinery under it

After looking at your code I came up with this:

[<AutoOpen>]
module Extensions =

  type HandlerInput<'a> with
    
    // I think these two could be good additions but I'm not
    member this.GetArgument<'T>(): Argument<'T> option =
      match this.Source with
      | ParsedArgument a -> a :?> Argument<'T> |> Some
      | _ -> None

    member this.GetOption<'T>(): Option<'T> option =
      match this.Source with
      | ParsedOption o -> o :?> Option<'T> |> Some
      | _ -> None

    // This is like the one you already have but with ParseResult rather than invocation context
    member this.GetValue(ctx: ParseResult): 'T option =
      match this.Source with
      | ParsedOption o -> o :?> Option<'T> |> ctx.GetValueForOption |> Option.ofNull 
      | ParsedArgument a -> a :?> Argument<'T> |> ctx.GetValueForArgument |> Option.ofNull
      | Context -> None

Note: Option.ofNull comes from FsToolkit.ErrorHandling

And I can use it like this:

module CommandOptions =

  [<Fact>]
  let ``Commands.Setup can parse options`` () =
    let root = RootCommand("Commands.Setup can parse options")
    let skipPrompts = SetupInputs.skipPrompts
    let skipPlaywright = SetupInputs.skipPlaywright

    root.AddCommand(Commands.Setup)
    let result = root.Parse([| "setup"; "-y"; "--skip-playwright"; "false" |])

    Assert.Empty(result.Errors)

    let skipPlaywright: bool option = skipPlaywright.GetValue result |> Option.flatten
    let skipPrompts: bool option = skipPrompts.GetValue result |> Option.flatten

    Assert.True (skipPrompts |> Option.defaultValue false)
    Assert.False (skipPlaywright |> Option.defaultValue true)

In this case I only have access to the ParseResult but to be able to get the value I need access to the source, thankfully you have already a similar function, but it requires the invocation context rather than the parsing results.

For my purposes I think this is just what I need but I'll leave it here in case this seems useful
Feel free to discuss/close as this is not a feature request

Note: I'm aware of your testRootCommand builder in the tests project, would it be worth considering adding it as a test helper package?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions