This module allows defining placeholder parsers based on a non-supported Syntax
as well as
using the internal Template
type for different purposes.
A Template
includes an ordered list of placeholders and text segments.
Template
s guarantee that
List.length segments == List.length placeholders + 1
and they can be converted back to the same String
representation they were parsed from.
parseTemplate : Syntax -> String -> Result String Template
Parse a String
into a Template
based on a Syntax
.
syntax : Syntax
syntax = { startSymbol = "${", endSymbol = "}" }
parseTemplate syntax "This is ${name}s example" |> Result.map (always ())
--> Ok ()
parseTemplate syntax "This does not ${makeSense"
--> Err "TODO deadEndsToString" -- (Waiting for upstream fix in elm/parser)
getPlaceholderNames : Template -> List String
Get the names of the placeholders in a Template
.
The names are ordered just like they are in the given template string.
parseTemplate { startSymbol = "${", endSymbol = "}" } "${first} ${snd}"
|> Result.map getPlaceholderNames
--> Ok ["first", "snd"]
parseTemplate { startSymbol = "${", endSymbol = "}" } "${blub} ${bla} ${blub}"
|> Result.map getPlaceholderNames
--> Ok ["blub", "bla", "blub"]
getAlphabeticalPlaceholderNames : Template -> List String
Get the names of the placeholders in a Template
sorted in alphabetical order and without duplicates.
parseTemplate { startSymbol = "${", endSymbol = "}" } "${blub} ${bla} ${blub}"
|> Result.map getAlphabeticalPlaceholderNames
--> Ok ["bla", "blub"]
getPlaceholderPositions : Template -> List ( List.NonEmpty.NonEmpty Basics.Int, String )
Get the names of the placeholders in a Template
sorted in alphabetical order together with the positions they appear in.
parseTemplate { startSymbol = "${", endSymbol = "}" } "${blub} ${bla} ${blub}"
|> Result.map getPlaceholderPositions
--> Ok [((1, []),"bla"), ((0, [2]),"blub")]
getSegments : Template -> List.NonEmpty.NonEmpty String
Get the static parts of the Template
as an ordered list.
parseTemplate { startSymbol = "${", endSymbol = "}" } "An ${ex}ample"
|> Result.map getSegments
--> Ok ( "An ", [ "ample" ] )
templateToString : Template -> String
Convert a parsed Template
back to its String
representation.
For any template built with Syntax
s,
templateToString >> parseTemplate s == identity
parseTemplate { startSymbol = "${", endSymbol = "}" } "This is ${name}s example"
|> Result.map templateToString
--> Ok "This is ${name}s example"
mapPlaceholders : (Basics.Int -> String -> String) -> Template -> Template
Change placeholder keys based on index and current key.
parseTemplate { startSymbol = "{", endSymbol = "}" } "{UPPER} case"
|> Result.map (mapPlaceholders (\_ -> String.toLower) >> templateToString)
--> Ok "{upper} case"
{ startSymbol : String
, endSymbol : String
}
A Syntax
tells the templateParser
how to distinguish placeholders from regular text.
At the moment, this can only be configured by setting start and end symbol.
parsePlaceholder1 : Syntax -> String -> Result String (F1 String)
Parse a String
into a function substituting the argument at the position marked by the Syntax
.
exampleOf : Result String (String -> String)
exampleOf = parsePlaceholder1 { startSymbol = "${", endSymbol = "}" } "This is ${name}s example"
Result.map ((|>) "Andy") exampleOf
--> Ok "This is Andys example"
parsePlaceholder1 { startSymbol = "${", endSymbol = "}" } "No placeholder"
--> Err "Expected 1 placeholders, but parsed a total of 0."
parsePlaceholder1 { startSymbol = "${", endSymbol = "}" } "${multiple}${placeholders}"
--> Err "Expected 1 placeholders, but parsed a total of 2."
parsePlaceholder2 : Syntax -> String -> Result String (F2 String)
Parse a String
into a function substituting the arguments at the two positions marked by the Syntax
.
Note that this function and the other parsePlaceholderN
functions always substitute elements in the order
they appear in the template string. This also means that for duplicate placeholder keys, you need to use
the parsePlaceholderAlphN
family of functions instead.
parsePlaceholder2 { startSymbol = "{", endSymbol = "}" } "{greeting} {target}"
|> Result.map (\f -> f "Hello" "World")
--> Ok "Hello World"
parsePlaceholder3 : Syntax -> String -> Result String (F3 String)
Parse a String
into a function substituting the arguments at the three positions marked by the Syntax
.
parsePlaceholder4 : Syntax -> String -> Result String (F4 String)
Parse a String
into a function substituting the arguments at the four positions marked by the Syntax
.
parsePlaceholderAlph1 : Syntax -> String -> Result String (F1 String)
Parse a String
into a function substituting the argument at all positions marked with the same, only key
This differs from parsePlaceholder1
as you can see in the following example:
syntax : Syntax
syntax = { startSymbol = "{", endSymbol = "}" }
parsePlaceholder1 syntax "{greeting} {greeting}"
--> Err "Expected 1 placeholders, but parsed a total of 2."
parsePlaceholderAlph1 syntax "{greeting} {greeting}" |> Result.map ((|>) "Hello")
--> Ok "Hello Hello"
parsePlaceholderAlph2 : Syntax -> String -> Result String (F2 String)
Parse a String
into a function substituting the arguments at all positions marked with the two placeholder keys.
The arguments for the keys are expected in alphabetical order.
This differs from parsePlaceholder2
as you can see in the following example:
syntax : Syntax
syntax = { startSymbol = "{", endSymbol = "}" }
parsePlaceholder2 syntax "{greeting} {friend}" |> Result.map (\f -> f "Hello" "World")
--> Ok "Hello World"
parsePlaceholderAlph2 syntax "{greeting} {friend}" |> Result.map (\f -> f "Hello" "World")
--> Ok "World Hello"
parsePlaceholderAlph3 : Syntax -> String -> Result String (F3 String)
Parse a String
into a function substituting the arguments at all positions marked with the three placeholder keys.
The arguments for the keys are expected in alphabetical order.
parsePlaceholderAlph4 : Syntax -> String -> Result String (F4 String)
Parse a String
into a function substituting the arguments at all positions marked with the four placeholder keys.
The arguments for the keys are expected in alphabetical order.