@@ -7,7 +7,6 @@ open System.CommandLine
77open System.CommandLine .Builder
88open System.CommandLine .Parsing
99
10- type private HI < 'T > = HandlerInput< 'T>
1110type private IC = System.CommandLine.Invocation.InvocationContext
1211let private def < 'T > = Unchecked.defaultof< 'T>
1312
@@ -24,11 +23,14 @@ type CommandSpec<'Inputs, 'Output> =
2423 Inputs: HandlerInput list
2524 Handler: 'Inputs -> 'Output
2625 SubCommands: System .CommandLine .Command list
26+ /// Registers extra inputs that can be parsed via the InvocationContext if more than 8 are required.
27+ ExtraInputs: HandlerInput list
2728 }
2829 static member Default =
2930 {
3031 Description = " My Command"
3132 Inputs = []
33+ ExtraInputs = []
3234 Handler = def< unit -> 'Output> // Support unit -> 'Output handler by default
3335 SubCommands = []
3436 }
@@ -40,6 +42,7 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
4042 {
4143 Description = spec.Description
4244 Inputs = spec.Inputs
45+ ExtraInputs = spec.ExtraInputs
4346 Handler = handler
4447 SubCommands = spec.SubCommands
4548 }
@@ -52,42 +55,52 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
5255 member this.Zero _ =
5356 CommandSpec< unit, 'Output>. Default
5457
58+ /// A description that will be displayed to the command line user.
5559 [<CustomOperation( " description" ) >]
5660 member this.Description ( spec : CommandSpec < 'T , 'U >, description ) =
5761 { spec with Description = description }
5862
63+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
5964 [<CustomOperation( " inputs" ) >]
60- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, a : HI < 'A >) =
65+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, a : HandlerInput < 'A >) =
6166 { newHandler def< 'A -> 'Output> spec with Inputs = [ a ] }
6267
68+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
6369 [<CustomOperation( " inputs" ) >]
64- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >)) =
70+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >)) =
6571 { newHandler def< 'A * 'B -> 'Output> spec with Inputs = [ a; b ] }
6672
73+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
6774 [<CustomOperation( " inputs" ) >]
68- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >)) =
75+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >)) =
6976 { newHandler def< 'A * 'B * 'C -> 'Output> spec with Inputs = [ a; b; c ] }
7077
78+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
7179 [<CustomOperation( " inputs" ) >]
72- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >, d : HI < 'D >)) =
80+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >, d : HandlerInput < 'D >)) =
7381 { newHandler def< 'A * 'B * 'C * 'D -> 'Output> spec with Inputs = [ a; b; c; d ] }
7482
83+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
7584 [<CustomOperation( " inputs" ) >]
76- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >, d : HI < 'D >, e : HI < 'E >)) =
85+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >, d : HandlerInput < 'D >, e : HandlerInput < 'E >)) =
7786 { newHandler def< 'A * 'B * 'C * 'D * 'E -> 'Output> spec with Inputs = [ a; b; c; d; e ] }
7887
88+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
7989 [<CustomOperation( " inputs" ) >]
80- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >, d : HI < 'D >, e : HI < 'E >, f : HI < 'F >)) =
90+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >, d : HandlerInput < 'D >, e : HandlerInput < 'E >, f : HandlerInput < 'F >)) =
8191 { newHandler def< 'A * 'B * 'C * 'D * 'E * 'F -> 'Output> spec with Inputs = [ a; b; c; d; e; f ] }
8292
93+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
8394 [<CustomOperation( " inputs" ) >]
84- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >, d : HI < 'D >, e : HI < 'E >, f : HI < 'F >, g : HI < 'G >)) =
95+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >, d : HandlerInput < 'D >, e : HandlerInput < 'E >, f : HandlerInput < 'F >, g : HandlerInput < 'G >)) =
8596 { newHandler def< 'A * 'B * 'C * 'D * 'E * 'F * 'G -> 'Output> spec with Inputs = [ a; b; c; d; e; f; g ] }
8697
98+ /// A tuple of inputs (max. 8) that must exactly match the handler function inputs.
8799 [<CustomOperation( " inputs" ) >]
88- member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HI < 'A >, b : HI < 'B >, c : HI < 'C >, d : HI < 'D >, e : HI < 'E >, f : HI < 'F >, g : HI < 'G >, h : HI < 'H >)) =
100+ member this.Inputs ( spec : CommandSpec < 'T , 'Output >, ( a : HandlerInput < 'A >, b : HandlerInput < 'B >, c : HandlerInput < 'C >, d : HandlerInput < 'D >, e : HandlerInput < 'E >, f : HandlerInput < 'F >, g : HandlerInput < 'G >, h : HandlerInput < 'H >)) =
89101 { newHandler def< 'A * 'B * 'C * 'D * 'E * 'F * 'G * 'H -> 'Output> spec with Inputs = [ a; b; c; d; e; f; g; h ] }
90102
103+ /// Sets a handler function that takes a tuple of inputs (max. 8). NOTE: This must be set after the inputs.
91104 [<CustomOperation( " setHandler" ) >]
92105 member this.SetHandler ( spec : CommandSpec < 'Inputs , 'Output >, handler : 'Inputs -> 'Output ) =
93106 newHandler handler spec
@@ -97,14 +110,21 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
97110 member this.SetCommand ( spec : CommandSpec < 'Inputs , 'Output >, subCommand : System.CommandLine.Command ) =
98111 { spec with SubCommands = spec.SubCommands @ [ subCommand ] }
99112
113+ /// Adds a sub-command.
100114 [<CustomOperation( " addCommand" ) >]
101115 member this.AddCommand ( spec : CommandSpec < 'Inputs , 'Output >, subCommand : System.CommandLine.Command ) =
102116 { spec with SubCommands = spec.SubCommands @ [ subCommand ] }
103117
118+ /// Adds sub-commands.
104119 [<CustomOperation( " addCommands" ) >]
105120 member this.AddCommands ( spec : CommandSpec < 'Inputs , 'Output >, subCommands : System.CommandLine.Command seq ) =
106121 { spec with SubCommands = spec.SubCommands @ ( subCommands |> Seq.toList) }
107122
123+ /// Registers an additional input that can be manually parsed via the InvocationContext. (Use when more than 8 inputs are required.)
124+ [<CustomOperation( " add" ) >]
125+ member this.Add ( spec : CommandSpec < 'Inputs , 'Output >, extraInput : HandlerInput < 'Value >) =
126+ { spec with ExtraInputs = spec.ExtraInputs @ [ extraInput ] }
127+
108128 /// Sets general properties on the command.
109129 member this.SetGeneralProperties ( spec : CommandSpec < 'T , 'U >) ( cmd : Command ) =
110130 cmd.Description <- spec.Description
@@ -115,6 +135,13 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
115135 | ParsedArgument a -> cmd.AddArgument a
116136 | Context -> ()
117137 )
138+ spec.ExtraInputs
139+ |> Seq.iter ( fun input ->
140+ match input.Source with
141+ | ParsedOption o -> cmd.AddOption o
142+ | ParsedArgument a -> cmd.AddArgument a
143+ | Context -> ()
144+ )
118145
119146 spec.SubCommands |> List.iter cmd.AddCommand
120147 cmd
0 commit comments