F # / Argu - Как отобразить справку для двухуровневого дерева команд без исключения - PullRequest
0 голосов
/ 08 января 2019

У меня есть двухуровневое дерево команд F # / Argu. Его сокращенная версия выглядит так:

[<CliPrefix(CliPrefix.Dash)>]
type RunContGenArgs =
    | [<Unique>] [<EqualsAssignment>] [<AltCommandLine("-ql")>] MaxQueueLength of int

with
    interface IArgParserTemplate with
        member this.Usage =
            match this with
            | MaxQueueLength _ -> "max queue length."
and
    [<CliPrefix(CliPrefix.None)>]
    ContGenArguments =
        | [<Unique>] [<AltCommandLine("run")>]      RunContGen of ParseResults<RunContGenArgs>
    with
        interface IArgParserTemplate with
            member this.Usage =
                match this with
                | RunContGen _ -> "run Continuous Generation."

который я затем использую следующим образом:

[<EntryPoint>]
let main argv =
    let parser = ArgumentParser.Create<ContGenArguments>(programName = "ContGen.exe")
    let results = parser.Parse argv

    match results.GetAllResults() |> ContGenTask.tryCreate with
    | Some task -> task.run()
    | None ->
        printfn "%s" (parser.PrintUsage())
        -1

Если я запускаю команду как ContGen.exe run help, то она правильно отображает справку для команды run. Однако затем происходит сбой с ужасным исключением:

Unhandled Exception: Argu.ArguParseException: USAGE: ContGen.exe runcontgen [help] [-maxqueuelength=<int>]
OPTIONS:
    -maxqueuelength, -ql=<int>
                          max queue length.
    help                  display this list of options.
   at Argu.ExceptionExiter.Argu-IExiter-Exit[a](String msg, ErrorCode errorCode) in C:\Users\eirik.tsarpalis\devel\public\Argu\src\Argu\Types.fs:line 62
   at Argu.ArgumentParser\`1.Parse(FSharpOption\`1 inputs, FSharpOption\`1 configurationReader, FSharpOption\`1 ignoreMissing, FSharpOption\`1 ignoreUnrecognized, FSharpOption\`1 raiseOnUsage) in C:\Users\eirik.tsarpalis\devel\public\Argu\src\Argu\ArgumentParser.fs:line 180
   at Program.main(String[] argv) in C:\GitHub\ClmFSharp\Clm\ContGen\Program.fs:line 8

Если я изменю let results = parser.Parse argv на let results = parser.Parse(argv, raiseOnUsage = false), то он не аварийно завершит работу, но не отобразит никакого справочного сообщения. И затем, поскольку команда run может выполняться без каких-либо аргументов второго уровня, программа просто продолжает работать вместо отображения справки и выхода.

Однако мне нужно ContGen.exe run help, просто отобразить сообщение справки и выйти. Как я могу этого достичь? Благодаря.

1 Ответ

0 голосов
/ 08 января 2019

Это несколько своеобразное поведение Аргу; вам нужно предоставить своего собственного возбудителя, чтобы исключение не создавалось там.

Что-то вроде этого:

type NonThrowingExiter() =
    interface IExiter with
        member __.Name = "Exiter" // I don't know what this is used for; I have never seen it appear anywhere
        member __.Exit (msg, code) =
            if code = ErrorCode.HelpText then
                printfn "%s" msg
                exit 0
            else
                printfn "%s" msg // Maybe have code to color the console output red here
                exit 1

To use this, create your `ArgumentParser` like this:

let argumentParser =
    Argu.ArgumentParser.Create<ContGenArguments>(helpTextMessage = "Help requested",
                                                 errorHandler = NonThrowingExiter())

(Конечно, для этого вам не нужно создавать класс; объектное выражение сделает то же самое.)

...