@@ -39,6 +39,8 @@ let main argv =
3939 }
4040```
4141
42+ 💥WARNING: You must declare ` inputs ` before ` setHandler ` or else the type checking will not work properly and you will get a build error!💥
43+
4244``` batch
4345> unzip.exe "c:\test\stuff.zip"
4446 Result: Unzipping stuff.zip to c:\test
@@ -131,6 +133,8 @@ let main argv =
131133 rootCommand argv {
132134 description "File System Manager"
133135 setHandler id
136+ // if using async task sub commands, setHandler to `Task.FromResult`
137+ // setHandler Task.FromResult
134138 addCommand listCmd
135139 addCommand deleteCmd
136140 }
@@ -199,44 +203,108 @@ let main argv =
199203 |> Async.RunSynchronously
200204```
201205
202-
203- ### Async App with a Partially Applied Dependency
206+ ### Example using Microsoft.Extensions.Hosting
204207
205208``` F#
209+ open System
210+ open System.IO
206211open FSharp.SystemCommandLine
207- open System.CommandLine.Builder
208- open System.Threading.Tasks
209-
210- type WordService() =
211- member _.Join(separator: string, words: string array) =
212- task {
213- do! Task.Delay(1000)
214- return System.String.Join(separator, words)
215- }
212+ open Microsoft.Extensions.Hosting
213+ open Microsoft.Extensions.Logging
214+ open Microsoft.Extensions.Configuration
215+ open Microsoft.Extensions.DependencyInjection
216+ open Serilog
217+
218+ let buildHost (argv: string[]) =
219+ Host.CreateDefaultBuilder(argv)
220+ .ConfigureHostConfiguration(fun configHost ->
221+ configHost.SetBasePath(Directory.GetCurrentDirectory()) |> ignore
222+ configHost.AddJsonFile("appsettings.json", optional = false) |> ignore
223+ )
224+ .ConfigureLogging(fun logging ->
225+ logging.AddConsole() |> ignore
226+ logging.AddSerilog() |> ignore
227+ )
228+ .ConfigureServices(fun services ->
229+ // Serilog configuration
230+ let logger =
231+ LoggerConfiguration()
232+ .WriteTo.File(path = "logs/log.txt")
233+ .CreateLogger()
234+
235+ services.AddLogging(fun builder ->
236+ builder
237+ .SetMinimumLevel(LogLevel.Information)
238+ .AddSerilog(logger, dispose = true) |> ignore
239+ ) |> ignore
240+ )
241+ .Build()
216242
217- let app (svc: WordService ) (words : string array, separator: string ) =
243+ let exportHandler (logger: ILogger ) (connStr : string, outputDir: DirectoryInfo, startDate: DateTime, endDate: DateTime ) =
218244 task {
219- let! result = svc.Join(separator, words )
220- result |> printfn "Result: %s"
245+ logger.LogInformation($"Querying from {startDate.ToShortDateString()} to {endDate.ToShortDateString()}" )
246+ // Do export stuff...
221247 }
222-
223- [<EntryPoint>]
224- let main argv =
225- let words = Input.Option<string array>(["--word"; "-w"], Array.empty, "A list of words to be appended")
226- let separator = Input.Option<string>(["--separator"; "-s"], ", ", "A character that will separate the joined words.")
227248
228- // Initialize app dependencies
229- let svc = WordService()
249+ [<EntryPoint>]
250+ let main argv =
251+ let host = buildHost argv
252+ let logger = host.Services.GetService<ILogger<_>>()
253+ let cfg = host.Services.GetService<IConfiguration>()
254+
255+ let connStr = Input.Option<string>(
256+ aliases = ["-c"; "--connection-string"],
257+ defaultValue = cfg["ConnectionStrings:DB"],
258+ description = "Database connection string")
259+
260+ let outputDir = Input.Option<DirectoryInfo>(
261+ aliases = ["-o";"--output-directory"],
262+ defaultValue = DirectoryInfo(cfg["DefaultOutputDirectory"]),
263+ description = "Output directory folder.")
264+
265+ let startDate = Input.Option<DateTime>(
266+ name = "--start-date",
267+ defaultValue = DateTime.Today.AddDays(-7),
268+ description = "Start date (defaults to 1 week ago from today)")
269+
270+ let endDate = Input.Option<DateTime>(
271+ name = "--end-date",
272+ defaultValue = DateTime.Today,
273+ description = "End date (defaults to today)")
230274
231275 rootCommand argv {
232- description "Appends words together"
233- inputs (words, separator)
234- usePipeline (fun builder ->
235- CommandLineBuilder() // Pipeline is initialized with .UseDefaults() by default,
236- .UseTypoCorrections(3) // but you can override it here if needed.
237- )
238- setHandler (app svc) // Partially apply app dependencies
276+ description "Data Export"
277+ inputs (connStr, outputDir, startDate, endDate)
278+ setHandler (exportHandler logger)
239279 }
240280 |> Async.AwaitTask
241281 |> Async.RunSynchronously
242282```
283+
284+ ### Creating a Root Command Parser
285+
286+ If you want to manually invoke your root command, use the ` rootCommandParser ` CE (because the ` rootCommand ` CE is auto-executing).
287+
288+ ``` F#
289+ open FSharp.SystemCommandLine
290+ open System.CommandLine.Parsing
291+
292+ let app (words: string array, separator: string option) =
293+ let separator = separator |> Option.defaultValue ", "
294+ System.String.Join(separator, words) |> printfn "Result: %s"
295+ 0
296+
297+ [<EntryPoint>]
298+ let main argv =
299+ let words = Input.Option(["--word"; "-w"], Array.empty, "A list of words to be appended")
300+ let separator = Input.OptionMaybe(["--separator"; "-s"], "A character that will separate the joined words.")
301+
302+ let parser =
303+ rootCommandParser {
304+ description "Appends words together"
305+ inputs (words, separator)
306+ setHandler app
307+ }
308+
309+ parser.Parse(argv).Invoke()
310+ ```
0 commit comments