Skip to content

Commit 6f3211a

Browse files
committed
v2.0.0-beta7.0
1 parent dd4a420 commit 6f3211a

File tree

6 files changed

+114
-81
lines changed

6 files changed

+114
-81
lines changed

src/FSharp.SystemCommandLine/CommandBuilders.fs

Lines changed: 89 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ open System
55
open System.Threading
66
open System.Threading.Tasks
77
open System.CommandLine
8-
open System.CommandLine.Parsing
98

109
let private def<'T> = Unchecked.defaultof<'T>
1110

@@ -18,6 +17,9 @@ let private parseInput<'V> (handlerInput: ActionInput) (pr: ParseResult) (cancel
1817

1918
type CommandSpec<'Inputs, 'Output> =
2019
{
20+
RootCommand: RootCommand
21+
ParserConfiguration: ParserConfiguration
22+
InvocationConfiguration: InvocationConfiguration
2123
Description: string
2224
Inputs: ActionInput list
2325
Handler: 'Inputs -> 'Output
@@ -29,6 +31,9 @@ type CommandSpec<'Inputs, 'Output> =
2931
}
3032
static member Default =
3133
{
34+
RootCommand = RootCommand()
35+
ParserConfiguration = ParserConfiguration()
36+
InvocationConfiguration = InvocationConfiguration()
3237
Description = "My Command"
3338
Inputs = []
3439
Aliases = []
@@ -43,6 +48,9 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
4348

4449
let newHandler handler spec =
4550
{
51+
RootCommand = spec.RootCommand
52+
ParserConfiguration = spec.ParserConfiguration
53+
InvocationConfiguration = spec.InvocationConfiguration
4654
Description = spec.Description
4755
Inputs = spec.Inputs
4856
Aliases = spec.Aliases
@@ -113,8 +121,6 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
113121
invalidOp "Only 8 inputs are supported."
114122

115123

116-
member val CommandLineConfiguration = new CommandLineConfiguration(new RootCommand()) with get, set
117-
118124
member this.Yield _ =
119125
CommandSpec<unit, 'Output>.Default
120126

@@ -306,126 +312,150 @@ type BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
306312
cmd
307313

308314

309-
/// Builds a `System.CommandLineConfiguration` that can be passed to the `CommandLineParser.Parse` static method.
310-
type CommandLineConfigurationBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
315+
/// Builds a `System.RootCommand` that will be returned to the user for manual execution.
316+
type ManualExecutingRootCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>() =
311317
inherit BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>()
312-
313-
[<CustomOperation("usePipeline"); Obsolete("Please use `configure` instead.")>]
314-
member this.UsePipeline (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> unit) =
315-
subCommand this.CommandLineConfiguration
316-
spec
317-
318-
[<CustomOperation("usePipeline"); Obsolete("Please use `configure` instead.")>]
319-
member this.UsePipeline (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> CommandLineConfiguration) =
320-
this.CommandLineConfiguration <- subCommand this.CommandLineConfiguration
321-
spec
322318

319+
/// Allows modification of the ParserConfiguration.
320+
[<Obsolete("'configure' has been deprecated in favor of 'configureParser' or 'configureInvocation'.")>]
323321
[<CustomOperation("configure")>]
324-
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> unit) =
325-
subCommand this.CommandLineConfiguration
322+
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> unit) =
323+
configure spec.ParserConfiguration
326324
spec
327325

326+
/// Allows modification of the ParserConfiguration.
327+
[<Obsolete("'configure' has been deprecated in favor of 'configureParser' or 'configureInvocation'.")>]
328328
[<CustomOperation("configure")>]
329-
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> CommandLineConfiguration) =
330-
this.CommandLineConfiguration <- subCommand this.CommandLineConfiguration
329+
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> ParserConfiguration) =
330+
{ spec with ParserConfiguration = configure spec.ParserConfiguration }
331+
332+
/// Allows modification of the ParserConfiguration.
333+
[<CustomOperation("configureParser")>]
334+
member this.ConfigureParser (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> unit) =
335+
configure spec.ParserConfiguration
331336
spec
332337

338+
/// Allows modification of the ParserConfiguration.
339+
[<CustomOperation("configureParser")>]
340+
member this.ConfigureParser (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> ParserConfiguration) =
341+
{ spec with ParserConfiguration = configure spec.ParserConfiguration }
342+
333343
/// Executes a Command with a handler that returns unit.
334344
member this.Run (spec: CommandSpec<'Inputs, unit>) =
335-
this.CommandLineConfiguration.RootCommand
345+
spec.RootCommand
336346
|> this.SetGeneralProperties spec
337347
|> this.SetHandlerUnit spec
338348
|> ignore
339-
this.CommandLineConfiguration
349+
spec.RootCommand
340350

341351
/// Executes a Command with a handler that returns int.
342352
member this.Run (spec: CommandSpec<'Inputs, int>) =
343-
this.CommandLineConfiguration.RootCommand
353+
spec.RootCommand
344354
|> this.SetGeneralProperties spec
345355
|> this.SetHandlerInt spec
346356
|> ignore
347-
this.CommandLineConfiguration
357+
spec.RootCommand
348358

349359
/// Executes a Command with a handler that returns a Task<unit>.
350360
member this.Run (spec: CommandSpec<'Inputs, Task<unit>>) =
351-
this.CommandLineConfiguration.RootCommand
361+
spec.RootCommand
352362
|> this.SetGeneralProperties spec
353363
|> this.SetHandlerTask spec
354364
|> ignore
355-
this.CommandLineConfiguration
365+
spec.RootCommand
356366

357367
/// Executes a Command with a handler that returns a Task<int>.
358368
member this.Run (spec: CommandSpec<'Inputs, Task<int>>) =
359-
this.CommandLineConfiguration.RootCommand
369+
spec.RootCommand
360370
|> this.SetGeneralProperties spec
361371
|> this.SetHandlerTaskInt spec
362372
|> ignore
363-
this.CommandLineConfiguration
373+
spec.RootCommand
364374

365375

366376
/// Builds and executes a `System.CommandLine.RootCommand`.
367377
type RootCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(args: string array) =
368378
inherit BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>()
369-
370-
[<CustomOperation("usePipeline"); Obsolete("Please use `configure` instead.")>]
371-
member this.UsePipeline (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> unit) =
372-
subCommand this.CommandLineConfiguration
373-
spec
374379

375-
[<CustomOperation("usePipeline"); Obsolete("Please use `configure` instead.")>]
376-
member this.UsePipeline (spec: CommandSpec<'Inputs, 'Output>, subCommand: CommandLineConfiguration -> CommandLineConfiguration) =
377-
this.CommandLineConfiguration <- subCommand this.CommandLineConfiguration
378-
spec
379-
380-
/// Allows modification of the CommandLineConfiguration.
380+
/// Allows modification of the ParserConfiguration.
381+
[<Obsolete("'configure' has been deprecated in favor of 'configureParser' or 'configureInvocation'.")>]
381382
[<CustomOperation("configure")>]
382-
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: CommandLineConfiguration -> unit) =
383-
configure this.CommandLineConfiguration
383+
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> unit) =
384+
configure spec.ParserConfiguration
384385
spec
385386

386-
/// Allows modification of the CommandLineConfiguration.
387+
/// Allows modification of the ParserConfiguration.
388+
[<Obsolete("'configure' has been deprecated in favor of 'configureParser' or 'configureInvocation'.")>]
387389
[<CustomOperation("configure")>]
388-
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: CommandLineConfiguration -> CommandLineConfiguration) =
389-
this.CommandLineConfiguration <- configure this.CommandLineConfiguration
390+
member this.Configure (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> ParserConfiguration) =
391+
{ spec with ParserConfiguration = configure spec.ParserConfiguration }
392+
393+
/// Allows modification of the ParserConfiguration.
394+
[<CustomOperation("configureParser")>]
395+
member this.ConfigureParser (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> unit) =
396+
configure spec.ParserConfiguration
390397
spec
398+
399+
/// Allows modification of the ParserConfiguration.
400+
[<CustomOperation("configureParser")>]
401+
member this.ConfigureParser (spec: CommandSpec<'Inputs, 'Output>, configure: ParserConfiguration -> ParserConfiguration) =
402+
{ spec with ParserConfiguration = configure spec.ParserConfiguration }
403+
404+
/// Allows modification of the InvocationConfiguration.
405+
[<CustomOperation("configureInvocation")>]
406+
member this.ConfigureInvocation (spec: CommandSpec<'Inputs, 'Output>, configure: InvocationConfiguration -> unit) =
407+
configure spec.InvocationConfiguration
408+
spec
409+
410+
/// Allows modification of the InvocationConfiguration.
411+
[<CustomOperation("configureInvocation")>]
412+
member this.ConfigureInvocation (spec: CommandSpec<'Inputs, 'Output>, configure: InvocationConfiguration -> InvocationConfiguration) =
413+
{ spec with InvocationConfiguration = configure spec.InvocationConfiguration }
391414

392415
/// Executes a Command with a handler that returns unit.
393416
member this.Run (spec: CommandSpec<'Inputs, unit>) =
394417
let rootCommand =
395-
this.CommandLineConfiguration.RootCommand
418+
spec.RootCommand
396419
|> this.SetGeneralProperties spec
397420
|> this.SetHandlerUnit spec
398421

399-
rootCommand.Parse(args, this.CommandLineConfiguration).Invoke()
422+
rootCommand
423+
.Parse(args, spec.ParserConfiguration)
424+
.Invoke(spec.InvocationConfiguration)
400425

401426
/// Executes a Command with a handler that returns int.
402427
member this.Run (spec: CommandSpec<'Inputs, int>) =
403428
let rootCommand =
404-
this.CommandLineConfiguration.RootCommand
429+
spec.RootCommand
405430
|> this.SetGeneralProperties spec
406431
|> this.SetHandlerInt spec
407432

408-
rootCommand.Parse(args, this.CommandLineConfiguration).Invoke()
433+
rootCommand
434+
.Parse(args, spec.ParserConfiguration)
435+
.Invoke(spec.InvocationConfiguration)
409436

410437
/// Executes a Command with a handler that returns a Task<unit> or Task<int>.
411438
member this.Run (spec: CommandSpec<'Inputs, Task<unit>>) =
412439
let rootCommand =
413-
this.CommandLineConfiguration.RootCommand
440+
spec.RootCommand
414441
|> this.SetGeneralProperties spec
415442
|> this.SetHandlerTask spec
416443

417-
rootCommand.Parse(args, this.CommandLineConfiguration).InvokeAsync()
444+
rootCommand
445+
.Parse(args, spec.ParserConfiguration)
446+
.InvokeAsync(spec.InvocationConfiguration)
418447

419448
/// Executes a Command with a handler that returns a Task<unit> or Task<int>.
420449
member this.Run (spec: CommandSpec<'Inputs, Task<int>>) =
421450
let rootCommand =
422-
this.CommandLineConfiguration.RootCommand
451+
spec.RootCommand
423452
|> this.SetGeneralProperties spec
424453
|> this.SetHandlerTaskInt spec
425454

426-
rootCommand.Parse(args, this.CommandLineConfiguration).InvokeAsync()
455+
rootCommand
456+
.Parse(args, spec.ParserConfiguration)
457+
.InvokeAsync(spec.InvocationConfiguration)
427458

428-
429459
/// Builds a `System.CommandLine.Command`.
430460
type CommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(name: string) =
431461
inherit BaseCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>()
@@ -460,14 +490,15 @@ type CommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(name: string) =
460490
|> this.SetHandlerTaskInt spec
461491

462492

463-
/// Builds a `System.CommandLineConfiguration` that can be passed to the `CommandLineParser.Parse` static method using computation expression syntax.
464-
let commandLineConfiguration<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output> =
465-
CommandLineConfigurationBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>()
466-
467-
/// Builds and executes a `System.CommandLine.RootCommand` using computation expression syntax.
493+
/// Builds a self-invoking `System.CommandLine.RootCommand`.
468494
let rootCommand<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(args: string array)=
469495
RootCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(args)
470496

471-
/// Builds a `System.CommandLine.Command` using computation expression syntax.
497+
/// Builds a `System.CommandLine.Command`.
472498
let command<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output> (name: string) =
473499
CommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>(name)
500+
501+
module ManualInvocation =
502+
/// Builds a `System.CommandLine.RootCommand` that will be returned to the user for manual invocation.
503+
let rootCommand<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output> =
504+
ManualExecutingRootCommandBuilder<'A, 'B, 'C, 'D, 'E, 'F, 'G, 'H, 'Output>()

src/FSharp.SystemCommandLine/FSharp.SystemCommandLine.fsproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
55
<GenerateDocumentationFile>true</GenerateDocumentationFile>
6-
<Version>2.0.0-beta5.11</Version>
6+
<Version>2.0.0-beta7.0</Version>
77
<Description>F# computation expressions for working with the System.CommandLine API.</Description>
88
<Authors>Jordan Marr</Authors>
99
<PackageTags>F# fsharp System.CommandLine cli</PackageTags>
@@ -18,7 +18,7 @@
1818
</ItemGroup>
1919

2020
<ItemGroup>
21-
<PackageReference Include="System.CommandLine" Version="2.0.0-beta5.25306.1" />
21+
<PackageReference Include="System.CommandLine" Version="2.0.0-beta7.25380.108" />
2222
</ItemGroup>
2323

2424
<ItemGroup>

src/TestConsole/Program.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ let main _ =
1010

1111
//ProgramAlt1.run ()
1212
//ProgramNoArgs.run ()
13-
ProgramNestedSubCommands.run () |> Async.AwaitTask |> Async.RunSynchronously // Also contains global options
13+
//ProgramNestedSubCommands.run () |> Async.AwaitTask |> Async.RunSynchronously // Also contains global options
1414
//ProgramSubCommand.run ()
1515
//ProgramTask.run ()
1616
//ProgramTokenReplacer.SCL.run ()
17-
//ProgramTokenReplacer.run ()
17+
ProgramTokenReplacer.run ()
1818
//ProgramExtraInputs.run ()
1919
//ProgramAppendWords.run ()

src/TestConsole/ProgramNestedSubCommands.fs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,24 @@ let ioCmd =
6969
addCommands [ deleteCmd; listCmd ]
7070
}
7171

72+
open ManualInvocation
73+
7274
let main (argv: string[]) =
73-
let cfg =
74-
commandLineConfiguration {
75+
let rootCmd =
76+
rootCommand {
7577
description "Sample app for System.CommandLine"
7678
noAction
7779
addInputs Global.options
7880
addCommand ioCmd
7981
}
8082

81-
let parseResult = cfg.Parse(argv)
83+
let parseResult = rootCmd.Parse(argv)
8284

8385
let loggingEnabled = Global.enableLogging.GetValue parseResult
8486
printfn $"ROOT: Logging enabled: {loggingEnabled}"
8587

8688
use cts = new CancellationTokenSource()
87-
let parseResult = cfg.Parse(argv)
88-
parseResult.InvokeAsync(cts.Token)
89+
parseResult.InvokeAsync(cancellationToken = cts.Token)
8990

9091
let run () =
9192
"io list \"c:/data/\" --enable-logging" |> Utils.args |> main

src/TestConsole/ProgramTokenReplacer.fs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ module SCL =
1010
printfn $"The value for --package is: %s{package}"
1111

1212
let main (argv: string[]) =
13-
let cfg = new CommandLineConfiguration(new RootCommand())
14-
cfg.ResponseFileTokenReplacer <- null // in beta5, you must set ResponseFileTokenReplacer to null to skip @ processing
15-
let cmd = cfg.RootCommand
16-
13+
let cmd = RootCommand()
14+
let cfg = ParserConfiguration(ResponseFileTokenReplacer = null) // Set to null to skip "@" processing
1715
cmd.Description <- "My sample app"
1816
cmd.Add(packageOpt)
1917
cmd.SetAction(action)
2018

21-
cmd.Parse(argv, cfg).Invoke()
19+
let parseResult = cmd.Parse(argv, cfg)
20+
parseResult.Invoke()
2221

2322
let run () =
2423
"--package @shoelace-style/shoelace" |> Utils.args |> main
@@ -47,10 +46,10 @@ let getCmd =
4746
let main argv =
4847
rootCommand argv {
4948
description "Can be called with a leading @ package"
50-
configure (fun cfg ->
49+
configureParser (fun cfg ->
5150
// Skip @ processing
5251
cfg.ResponseFileTokenReplacer <- null
53-
)
52+
)
5453
noAction
5554
addCommand getCmd
5655
}

0 commit comments

Comments
 (0)