Skip to content

Commit cfc7815

Browse files
committed
2 parents 75d6dcb + 255ae22 commit cfc7815

File tree

1 file changed

+96
-28
lines changed

1 file changed

+96
-28
lines changed

README.md

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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
206211
open 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

Comments
 (0)