From 02aa1f3069fde08b7acfdfc9f9327ed56ddb9ab3 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 29 Jun 2016 16:11:19 +0300 Subject: [PATCH] rename description --> helpTextMessage --- src/Argu/ArgumentParser.fs | 48 ++++++++++++++++++++------------------ src/Argu/ParseResult.fs | 2 +- src/Argu/Parsers.fs | 40 +++++++++++++++---------------- src/Argu/Types.fs | 5 ++-- src/Argu/UnParsers.fs | 37 +++++++++++++---------------- 5 files changed, 65 insertions(+), 67 deletions(-) diff --git a/src/Argu/ArgumentParser.fs b/src/Argu/ArgumentParser.fs index 4c0ab0c0..7950e7f3 100644 --- a/src/Argu/ArgumentParser.fs +++ b/src/Argu/ArgumentParser.fs @@ -11,13 +11,15 @@ open FSharp.Reflection /// that is an F# discriminated union. It can then be used to parse command line arguments /// or XML configuration. [] -type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, description : string option, +type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, helpTextMessage : string option, _usageStringCharacterWidth : int, errorHandler : IExiter) = /// Gets the help flags specified for the CLI parser member __.HelpFlags = argInfo.HelpParam.Flags /// Gets the help description specified for the CLI parser member __.HelpDescription = argInfo.HelpParam.Description + /// Gets the message that will be displayed at the top of the help text + member __.HelpTextMessage = helpTextMessage /// Returns true if parser corresponds to a subcommand member __.IsSubCommandParser = argInfo.TryGetParent() |> Option.isSome /// If subcommand parser, gets parent argument metadata @@ -39,7 +41,7 @@ type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, des e.Accept { new ITemplateFunc with member __.Invoke<'Template when 'Template :> IArgParserTemplate> () = - new ArgumentParser<'Template>(nu, _programName, description, _usageStringCharacterWidth, errorHandler) :> _ + new ArgumentParser<'Template>(nu, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) :> _ }) |> Seq.toList @@ -50,7 +52,7 @@ type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, des member __.PrintUsage (?message : string, ?programName : string, ?usageStringCharacterWidth : int) : string = let programName = defaultArg programName _programName let usageStringCharacterWidth = defaultArg usageStringCharacterWidth _usageStringCharacterWidth - printUsage argInfo programName usageStringCharacterWidth message |> StringExpr.build + mkUsageString argInfo programName usageStringCharacterWidth message |> StringExpr.build /// /// Prints command line syntax. Useful for generating documentation. @@ -60,7 +62,7 @@ type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, des member __.PrintCommandLineSyntax (?programName : string, ?usageStringCharacterWidth : int) : string = let programName = defaultArg programName _programName let usageStringCharacterWidth = defaultArg usageStringCharacterWidth _usageStringCharacterWidth - printCommandLineSyntax argInfo "" usageStringCharacterWidth programName |> StringExpr.build + mkCommandLineSyntax argInfo "" usageStringCharacterWidth programName |> StringExpr.build /// /// Enables access to the typed API of an ArgumentParser @@ -74,36 +76,36 @@ type ArgumentParser internal (argInfo : UnionArgInfo, _programName : string, des /// or XML configuration. and [] ArgumentParser<'Template when 'Template :> IArgParserTemplate> - internal (argInfo : UnionArgInfo, _programName : string, description : string option, + internal (argInfo : UnionArgInfo, _programName : string, helpTextMessage : string option, _usageStringCharacterWidth : int, errorHandler : IExiter) = - inherit ArgumentParser(argInfo, _programName, description, _usageStringCharacterWidth, errorHandler) + inherit ArgumentParser(argInfo, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) // memoize parser generation for given template type static let argInfoLazy = lazy(preComputeUnionArgInfo<'Template> ()) - let mkUsageString argInfo msgOpt = printUsage argInfo _programName _usageStringCharacterWidth msgOpt |> StringExpr.build + let mkUsageString argInfo msgOpt = mkUsageString argInfo _programName _usageStringCharacterWidth msgOpt |> StringExpr.build let (|ParserExn|_|) (e : exn) = match e with // do not display usage for App.Config parameter errors | ParseError (msg, ErrorCode.AppSettings, _) -> Some(ErrorCode.AppSettings, msg) | ParseError (msg, id, aI) -> Some (id, mkUsageString aI (Some msg)) - | HelpText aI -> Some (ErrorCode.HelpText, mkUsageString aI description) + | HelpText aI -> Some (ErrorCode.HelpText, mkUsageString aI helpTextMessage) | _ -> None /// /// Creates a new parser instance based on supplied F# union template. /// /// Program identifier, e.g. 'cat'. Defaults to the current executable name. - /// Program description placed at the top of the usage string. + /// Message that will be displayed at the top of the help text. /// Text width used when formatting the usage string. Defaults to 80 chars. /// The implementation of IExiter used for error handling. Exception is default. - new (?programName : string, ?description : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter) = + new (?programName : string, ?helpTextMessage : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter) = let usageStringCharacterWidth = defaultArg usageStringCharacterWidth 80 let programName = match programName with Some pn -> pn | None -> currentProgramName.Value let errorHandler = match errorHandler with Some e -> e | None -> new ExceptionExiter() :> _ - new ArgumentParser<'Template>(argInfoLazy.Value, programName, description, usageStringCharacterWidth, errorHandler) + new ArgumentParser<'Template>(argInfoLazy.Value, programName, helpTextMessage, usageStringCharacterWidth, errorHandler) /// Parse command line arguments only. /// The command line input. Taken from System.Environment if not specified. @@ -117,11 +119,11 @@ and [] let inputs = match inputs with None -> getEnvironmentCommandLineArgs () | Some args -> args try - let cliResults = parseCommandLine argInfo _programName description _usageStringCharacterWidth errorHandler raiseOnUsage ignoreUnrecognized inputs + let cliResults = parseCommandLine argInfo _programName helpTextMessage _usageStringCharacterWidth errorHandler raiseOnUsage ignoreUnrecognized inputs let ignoreMissing = (cliResults.IsUsageRequested && not raiseOnUsage) || ignoreMissing let results = postProcessResults argInfo ignoreMissing None (Some cliResults) - new ParseResult<'Template>(argInfo, results, _programName, description, _usageStringCharacterWidth, errorHandler) + new ParseResult<'Template>(argInfo, results, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) with ParserExn (errorCode, msg) -> errorHandler.Exit (msg, errorCode) @@ -135,7 +137,7 @@ and [] let appSettingsResults = parseKeyValueConfig configurationReader argInfo let results = postProcessResults argInfo ignoreMissing (Some appSettingsResults) None - new ParseResult<'Template>(argInfo, results, _programName, description, _usageStringCharacterWidth, errorHandler) + new ParseResult<'Template>(argInfo, results, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) with ParserExn (errorCode, msg) -> errorHandler.Exit (msg, errorCode) @@ -155,10 +157,10 @@ and [] try let appSettingsResults = parseKeyValueConfig configurationReader argInfo - let cliResults = parseCommandLine argInfo _programName description _usageStringCharacterWidth errorHandler raiseOnUsage ignoreUnrecognized inputs + let cliResults = parseCommandLine argInfo _programName helpTextMessage _usageStringCharacterWidth errorHandler raiseOnUsage ignoreUnrecognized inputs let results = postProcessResults argInfo ignoreMissing (Some appSettingsResults) (Some cliResults) - new ParseResult<'Template>(argInfo, results, _programName, description, _usageStringCharacterWidth, errorHandler) + new ParseResult<'Template>(argInfo, results, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) with ParserExn (errorCode, msg) -> errorHandler.Exit (msg, errorCode) @@ -187,7 +189,7 @@ and [] /// /// Argument input sequence. member __.ToParseResult (inputs : seq<'Template>) : ParseResult<'Template> = - mkParseResultFromValues argInfo errorHandler _usageStringCharacterWidth _programName description inputs + mkParseResultFromValues argInfo errorHandler _usageStringCharacterWidth _programName helpTextMessage inputs /// /// Gets a subparser associated with specific subcommand instance @@ -198,7 +200,7 @@ and [] let case = argInfo.Cases.[uci.Tag] match case.ParameterInfo with | NestedUnion (_,nestedUnion) -> - new ArgumentParser<'SubTemplate>(nestedUnion, _programName, description, _usageStringCharacterWidth, errorHandler) + new ArgumentParser<'SubTemplate>(nestedUnion, _programName, helpTextMessage, _usageStringCharacterWidth, errorHandler) | _ -> arguExn "internal error when fetching subparser %O." uci /// @@ -226,7 +228,7 @@ and [] /// Prints parameters in command line format. Useful for argument string generation. member __.PrintCommandLineArguments (args : 'Template list) : string [] = - printCommandLineArgs argInfo (Seq.cast args) |> Seq.toArray + mkCommandLineArgs argInfo (Seq.cast args) |> Seq.toArray /// Prints parameters in command line format. Useful for argument string generation. member __.PrintCommandLineArgumentsFlat (args : 'Template list) : string = @@ -237,7 +239,7 @@ and [] /// Print XML comments over every configuration entry. member __.PrintAppSettingsArguments (args : 'Template list, ?printComments : bool) : string = let printComments = defaultArg printComments true - let xmlDoc = printAppSettings argInfo printComments args + let xmlDoc = mkAppSettingsDocument argInfo printComments args use writer = { new System.IO.StringWriter() with member __.Encoding = System.Text.Encoding.UTF8 } xmlDoc.Save writer writer.Flush() @@ -264,11 +266,11 @@ type ArgumentParser with /// which must be an F# Discriminated Union. /// /// Program identifier, e.g. 'cat'. Defaults to the current executable name. - /// Program description placed at the top of the usage string. + /// Message that will be displayed at the top of the help text. /// Text width used when formatting the usage string. Defaults to 80 chars. /// The implementation of IExiter used for error handling. Exception is default. - static member Create<'Template when 'Template :> IArgParserTemplate>(?programName : string, ?description : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter) = - new ArgumentParser<'Template>(?programName = programName, ?description = description, ?errorHandler = errorHandler, ?usageStringCharacterWidth = usageStringCharacterWidth) + static member Create<'Template when 'Template :> IArgParserTemplate>(?programName : string, ?helpTextMessage : string, ?usageStringCharacterWidth : int, ?errorHandler : IExiter) = + new ArgumentParser<'Template>(?programName = programName, ?helpTextMessage = helpTextMessage, ?errorHandler = errorHandler, ?usageStringCharacterWidth = usageStringCharacterWidth) [] diff --git a/src/Argu/ParseResult.fs b/src/Argu/ParseResult.fs index 20bf9df3..ee01190b 100644 --- a/src/Argu/ParseResult.fs +++ b/src/Argu/ParseResult.fs @@ -7,7 +7,7 @@ open FSharp.Quotations type ParseResult<'Template when 'Template :> IArgParserTemplate> internal (argInfo : UnionArgInfo, results : UnionParseResults, programName : string, description : string option, usageStringCharWidth : int, exiter : IExiter) = - let mkUsageString message = printUsage argInfo programName usageStringCharWidth message |> StringExpr.build + let mkUsageString message = mkUsageString argInfo programName usageStringCharWidth message |> StringExpr.build // error handler functions let error hideUsage code msg = diff --git a/src/Argu/Parsers.fs b/src/Argu/Parsers.fs index 7efe2708..84884abd 100644 --- a/src/Argu/Parsers.fs +++ b/src/Argu/Parsers.fs @@ -117,27 +117,27 @@ type CliParseState = } /// parse the next command line argument and append to state -let rec private parseCommandLinePartial (state : CliParseState) (argInfo : UnionArgInfo) (results : CliParseResultAggregator) = +let rec private parseCommandLinePartial (state : CliParseState) (argInfo : UnionArgInfo) (aggregator : CliParseResultAggregator) = state.Reader.BeginCliSegment() match state.Reader.GetNextToken false argInfo with | EndOfStream -> () | HelpArgument _ when state.RaiseOnUsage -> raise <| HelpText argInfo - | HelpArgument _ -> results.IsUsageRequested <- true - | UnrecognizedOrArgument token when state.IgnoreUnrecognizedArgs -> results.AppendUnrecognized token + | HelpArgument _ -> aggregator.IsUsageRequested <- true + | UnrecognizedOrArgument token when state.IgnoreUnrecognizedArgs -> aggregator.AppendUnrecognized token | UnrecognizedOrArgument token -> error argInfo ErrorCode.CommandLine "unrecognized argument: '%s'." token | GroupedParams(_, switches) -> for sw in switches do let caseInfo = argInfo.CliParamIndex.Value.[sw] match caseInfo.ParameterInfo with | Primitives [||] -> - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine sw [||] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine sw [||] + aggregator.AppendResult result | _ -> error argInfo ErrorCode.CommandLine "argument '%s' cannot be grouped with other switches." sw | CliParam(_, name, caseInfo, Some _) when not caseInfo.IsEquals1Assignment -> error argInfo ErrorCode.CommandLine "invalid CLI syntax '%s='." name - | CliParam(_, name, caseInfo, _) when caseInfo.IsFirst && results.ResultCount > 0 -> + | CliParam(_, name, caseInfo, _) when caseInfo.IsFirst && aggregator.ResultCount > 0 -> error argInfo ErrorCode.CommandLine "argument '%s' should precede all other arguments." name | CliParam(token, name, caseInfo, equalityParam) -> @@ -150,8 +150,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union try field.Parser eqp with _ -> error argInfo ErrorCode.CommandLine "argument '%s' is assigned invalid value, should be <%s>." token field.Description - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [| argument |] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [| argument |] + aggregator.AppendResult result | Primitives [|kf;vf|] when caseInfo.IsEquals2Assignment -> match state.Reader.GetNextToken true argInfo with @@ -167,8 +167,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union try vf.Parser valTok with _ -> error argInfo ErrorCode.CommandLine "argument '%s' was given invalid value assignment '%s', should be <%s>." state.Reader.CurrentSegment token vf.Description - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [|k;v|] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [|k;v|] + aggregator.AppendResult result state.Reader.MoveNext() else error argInfo ErrorCode.CommandLine "argument '%s' must be followed by assignment '%s=%s'" caseInfo.Name kf.Description vf.Description @@ -194,8 +194,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union let parseSingleParameter () = let fields = fields |> Array.map parseNextField - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name fields - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name fields + aggregator.AppendResult result if caseInfo.IsRest then while not state.Reader.IsCompleted do @@ -215,8 +215,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union argument :?> 'T |> Some :> obj } - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [| optArgument |] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [| optArgument |] + aggregator.AppendResult result | OptionalParam(existential, field) -> let optArgument = existential.Accept { new IFunc with @@ -229,8 +229,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union | _ -> Option<'T>.None :> obj } - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [| optArgument |] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [| optArgument |] + aggregator.AppendResult result | ListParam(existential, field) -> let listArg = existential.Accept { new IFunc with @@ -252,8 +252,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union Seq.toList args :> obj } - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [| listArg |] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [| listArg |] + aggregator.AppendResult result | NestedUnion (existential, nestedUnion) -> let nestedResults = parseCommandLineInner state nestedUnion @@ -262,8 +262,8 @@ let rec private parseCommandLinePartial (state : CliParseState) (argInfo : Union member __.Invoke<'Template when 'Template :> IArgParserTemplate> () = new ParseResult<'Template>(nestedUnion, nestedResults, state.ProgramName, state.Description, state.UsageStringCharWidth, state.Exiter) :> obj } - let result = mkUnionCase caseInfo results.ResultCount ParseSource.CommandLine name [|result|] - results.AppendResult result + let result = mkUnionCase caseInfo aggregator.ResultCount ParseSource.CommandLine name [|result|] + aggregator.AppendResult result and private parseCommandLineInner (state : CliParseState) (argInfo : UnionArgInfo) = let results = new CliParseResultAggregator(argInfo) diff --git a/src/Argu/Types.fs b/src/Argu/Types.fs index 5b376fe9..dca55059 100644 --- a/src/Argu/Types.fs +++ b/src/Argu/Types.fs @@ -165,8 +165,9 @@ type ProcessExiter() = interface IExiter with member __.Name = "Process Exiter" member __.Exit(msg : string, errorCode : ErrorCode) = - Console.Error.WriteLine (msg) - do Console.Error.Flush() + let writer = if errorCode = ErrorCode.HelpText then Console.Out else Console.Error + writer.WriteLine msg + writer.Flush() exit (int errorCode) /// Abstract key/value configuration reader diff --git a/src/Argu/UnParsers.fs b/src/Argu/UnParsers.fs index 54937a01..b9513603 100644 --- a/src/Argu/UnParsers.fs +++ b/src/Argu/UnParsers.fs @@ -11,7 +11,7 @@ open FSharp.Reflection /// /// print the command line syntax /// -let printCommandLineSyntax (argInfo : UnionArgInfo) (prefix : string) (width : int) (programName : string) = stringExpr { +let mkCommandLineSyntax (argInfo : UnionArgInfo) (prefix : string) (width : int) (programName : string) = stringExpr { do if width < 1 then raise <| new ArgumentOutOfRangeException("width", "must be positive number") let! length0 = StringExpr.currentLength yield prefix @@ -77,7 +77,7 @@ let printCommandLineSyntax (argInfo : UnionArgInfo) (prefix : string) (width : i /// /// print usage string for given arg info /// -let printArgUsage (aI : UnionCaseArgInfo) = stringExpr { +let mkArgUsage (aI : UnionCaseArgInfo) = stringExpr { match aI.CommandLineNames with | [] -> () | param :: altParams -> @@ -128,7 +128,7 @@ let printArgUsage (aI : UnionCaseArgInfo) = stringExpr { /// /// print usage string for given help param /// -let printHelpParam (hp : HelpParam) = stringExpr { +let mkHelpParamUsage (hp : HelpParam) = stringExpr { match hp.Flags with | [] -> () | param :: altParams -> @@ -153,12 +153,12 @@ let printHelpParam (hp : HelpParam) = stringExpr { /// /// print usage string for a collection of arg infos /// -let printUsage (argInfo : UnionArgInfo) (programName : string) width (message : string option) = stringExpr { +let mkUsageString (argInfo : UnionArgInfo) (programName : string) width (message : string option) = stringExpr { match message with | Some msg -> yield msg; yield Environment.NewLine | None -> () - yield! printCommandLineSyntax argInfo "USAGE: " width programName + yield! mkCommandLineSyntax argInfo "USAGE: " width programName let options, subcommands = argInfo.Cases @@ -170,7 +170,7 @@ let printUsage (argInfo : UnionArgInfo) (programName : string) width (message : yield "SUBCOMMANDS:" yield Environment.NewLine; yield Environment.NewLine - for aI in subcommands do yield! printArgUsage aI + for aI in subcommands do yield! mkArgUsage aI match argInfo.HelpParam.Flags with | [] -> () @@ -185,18 +185,16 @@ let printUsage (argInfo : UnionArgInfo) (programName : string) width (message : yield "OPTIONS:" yield Environment.NewLine; yield Environment.NewLine - for aI in options do yield! printArgUsage aI + for aI in options do yield! mkArgUsage aI - yield! printHelpParam argInfo.HelpParam + yield! mkHelpParamUsage argInfo.HelpParam } /// /// print a command line argument for a set of parameters /// -/// -/// -let rec printCommandLineArgs (argInfo : UnionArgInfo) (args : seq) = - let printEntry (t : obj) = seq { +let rec mkCommandLineArgs (argInfo : UnionArgInfo) (args : seq) = + let mkEntry (t : obj) = seq { let tag = argInfo.TagReader.Value t let aI = argInfo.Cases.[tag] let fields = aI.FieldReader.Value t @@ -237,19 +235,16 @@ let rec printCommandLineArgs (argInfo : UnionArgInfo) (args : seq) = | NestedUnion (_, nested) -> yield clname let nestedResult = fields.[0] :?> IParseResult - yield! printCommandLineArgs nested (nestedResult.GetAllResults()) + yield! mkCommandLineArgs nested (nestedResult.GetAllResults()) } - args |> Seq.collect printEntry + args |> Seq.collect mkEntry /// -/// returns an App.Config XElement given a set of config parameters +/// returns an App.Config XDocument given a set of config parameters /// -/// -/// -/// -let printAppSettings (argInfo : UnionArgInfo) printComments (args : 'Template list) = - let printEntry (t : 'Template) : XNode [] = +let mkAppSettingsDocument (argInfo : UnionArgInfo) printComments (args : 'Template list) = + let mkArgumentEntry (t : 'Template) : XNode [] = let tag = argInfo.TagReader.Value (t :> _) let aI = argInfo.Cases.[tag] let getFields () = aI.FieldReader.Value (t :> _) @@ -325,4 +320,4 @@ let printAppSettings (argInfo : UnionArgInfo) printComments (args : 'Template li XDocument( XElement(XName.Get "configuration", - XElement(XName.Get "appSettings", Seq.collect printEntry args))) \ No newline at end of file + XElement(XName.Get "appSettings", Seq.collect mkArgumentEntry args))) \ No newline at end of file