diff --git a/src/Cli/Program.elm b/src/Cli/Program.elm index d73eb7e..1b23408 100644 --- a/src/Cli/Program.elm +++ b/src/Cli/Program.elm @@ -310,9 +310,11 @@ run (Config { optionsParsers }) argv versionMessage = ++ (validationErrors |> List.map (\{ name, invalidReason } -> - "`" + "Invalid " + ++ "`--" ++ name - ++ "` failed a validation. " + ++ "` option." + ++ "\n" ++ invalidReason ) |> String.join "\n" diff --git a/src/Cli/Validate.elm b/src/Cli/Validate.elm index 1d9a86b..e139fff 100644 --- a/src/Cli/Validate.elm +++ b/src/Cli/Validate.elm @@ -1,4 +1,4 @@ -module Cli.Validate exposing (predicate, ValidationResult(..), regex) +module Cli.Validate exposing (predicate, ValidationResult(..), regex, regexWithExpectation) {-| This module contains helper functions for performing validations (see the "validate..." functions in `Cli.Option`). @@ -83,3 +83,40 @@ regex regexPattern checkString = else Invalid ("Must be of form /" ++ regexPattern ++ "/") + +{-| A helper for regex validations with an additional expectation message. + + programConfig : Program.Config String + programConfig = + Program.config + |> Program.add + (OptionsParser.build identity + |> OptionsParser.with + (Option.requiredKeywordArg "name" + |> Option.validate + (Cli.Validate.regexWithExpectation "I expected this to be" "^[A-Z][A-Za-z_]*") + ) + ) + +If the validation fails, the user gets output like this: + +```shell +$ ./greet --name john +Validation errors: + +`name` failed a validation. I expected this to be matching "^[A-Z][A-Za-z_]*" but got 'john' +Value was: +"john" +``` + +-} +regexWithExpectation : String -> String -> String -> ValidationResult +regexWithExpectation expectation regexPattern checkString = + case regex regexPattern checkString of + Valid -> + Valid + + Invalid _ -> + Invalid (expectation ++ " matching \"" ++ regexPattern ++ "\", but got '" ++ checkString ++ "'") + + diff --git a/tests/OptionsParserTests.elm b/tests/OptionsParserTests.elm index f8177c7..00426fc 100644 --- a/tests/OptionsParserTests.elm +++ b/tests/OptionsParserTests.elm @@ -280,6 +280,32 @@ all = |> OptionsParser.end ) [ { name = "name", invalidReason = "Must be 3 characters long" } ] + , test "fails with expectation when regexWithExpectation validation function fails" <| + \() -> + expectValidationErrors [ "--scalar-codecs", "src/ModuleName" ] + (OptionsParser.build identity + |> OptionsParser.with + (Option.optionalKeywordArg "scalar-codecs" + |> Option.validateIfPresent + (\moduleName -> + Validate.regexWithExpectation "I expected an Elm module name" "^[A-Z][A-Za-z_]*(\\.[A-Z][A-Za-z_]*)*$" moduleName) + ) + |> OptionsParser.end + ) + [ { name = "scalar-codecs", invalidReason = "I expected an Elm module name matching \"^[A-Z][A-Za-z_]*(\\.[A-Z][A-Za-z_]*)*$\", but got 'src/ModuleName'" } ] + , test "succeeds when regexWithExpectation validation function passes" <| + \() -> + expectMatch [ "--scalar-codecs", "ModuleName" ] + (OptionsParser.build identity + |> OptionsParser.with + (Option.optionalKeywordArg "scalar-codecs" + |> Option.validateIfPresent + (\moduleName -> + Validate.regexWithExpectation "I expected an Elm module name" "^[A-Z][A-Za-z_]*(\\.[A-Z][A-Za-z_]*)*$" moduleName) + ) + |> OptionsParser.end + ) + (Just "ModuleName") , test "succeeds when validation function passes" <| \() -> expectMatch [ "--name", "Bob" ]