# Runtime (Polyglot)

```fsharp
#r "nuget: fsharp.control.asyncseq, 3.2.1"
#r "nuget: system.reactive, 6.0.1-preview.1"
#r "nuget: system.reactive.linq, 6.0.1-preview.1"
#r "nuget: argu, 6.2.4"
```

`#!import ../../lib/fsharp/Notebooks.livemd`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/Testing.livemd`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/Common.fs`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/CommonFSharp.fs`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/Async.fs`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/AsyncSeq.fs`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/Runtime.fs`

<!-- livebook:{"break_markdown":true} -->

`#!import ../../lib/fsharp/FileSystem.fs`

```fsharp
#if !INTERACTIVE
open Lib
#endif
```

```fsharp
open Common
```

```fsharp
///- --test

open SpiralFileSystem.Operators
```

## parseArgs

```fsharp
let inline parseArgs<'T when 'T :> Argu.IArgParserTemplate> args =
    let assemblyName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name
    let errorHandler : Argu.IExiter =
        if assemblyName = "fsi" // a notebook cell (Kino runs F# cells on dotnet fsi): report the error, don't exit
        then Argu.ExceptionExiter ()
        else Argu.ProcessExiter (function Argu.ErrorCode.HelpText -> None | _ -> Some System.ConsoleColor.Red)

    let parser =
        Argu.ArgumentParser.Create<'T> (
            programName = $"{assemblyName}{SpiralPlatform.get_executable_suffix ()}",
            errorHandler = errorHandler
        )

    parser.ParseCommandLine args
```

```fsharp
///- --test

[<RequireQualifiedAccess>]
type Arguments =
    | [<Argu.ArguAttributes.MainCommand; Argu.ArguAttributes.ExactlyOnce; Argu.ArguAttributes.Last>]
        Paths of paths : string list

    interface Argu.IArgParserTemplate with
        member s.Usage =
            match s with
            | Paths _ -> nameof Paths
```

```fsharp
///- --test

Argu.ArgumentParser.Create<Arguments>().PrintUsage ()
```

```fsharp
///- --test

fun () -> parseArgs<Arguments> [||] |> ignore
|> _throwsC (fun ex _ ->
    SpiralSm.format_exception ex
    |> _stringContains "Argu.ArguParseException: ERROR: missing parameter '<paths>...'."
)
```

```fsharp
let inline parseAllArgs<'T when 'T :> Argu.IArgParserTemplate> args =
    args
    |> parseArgs<'T>
    |> fun results -> results.GetAllResults ()
```

```fsharp
///- --test

[<RequireQualifiedAccess>]
type Arguments =
    | [<Argu.ArguAttributes.MainCommand; Argu.ArguAttributes.ExactlyOnce; Argu.ArguAttributes.Last>]
        Paths of paths : string list

    interface Argu.IArgParserTemplate with
        member s.Usage =
            match s with
            | Paths _ -> nameof Paths

parseAllArgs<Arguments> [| "a b"; "c" |]
|> _assertEqual [ Arguments.Paths [ "a b"; "c" ] ]
```

```fsharp
let inline parseArgsMap<'T when 'T :> Argu.IArgParserTemplate> args =
    args
    |> parseAllArgs<'T>
    |> List.groupBy CommonFSharp.getUnionCaseName<'T>
    |> Map.ofList
```

```fsharp
///- --test

parseArgsMap<Arguments> [| "a b"; "c" |]
|> _assertEqual (
    [ nameof Arguments.Paths, [ Arguments.Paths [ "a b"; "c" ] ] ]
    |> Map.ofList
)
```
