Packages
ex_cldr_lists
2.12.2
2.12.2
2.12.1
2.12.0
2.11.1
2.11.0
2.10.2
2.10.1
2.10.0
2.9.0
2.9.0-rc.2
2.9.0-rc.1
2.9.0-rc.0
2.8.0
2.8.0-rc.0
2.7.0
2.7.0-rc.0
2.6.1
2.6.0
2.5.0
2.5.0-rc.0
2.4.0
2.3.0
2.2.2
2.2.1
2.2.0
2.1.0
2.0.2
2.0.1
2.0.0
1.2.0
1.1.0
1.0.0
1.0.0-rc.0
retired
0.3.3
retired
0.3.2
retired
0.3.1
retired
0.3.0
retired
0.2.2
retired
0.2.1
retired
0.2.0
retired
0.1.3
retired
0.1.2
retired
0.1.1
retired
0.1.0
List formatting functions for the Common Locale Data Repository (CLDR) package ex_cldr.
Current section
Files
Jump to
Current section
Files
lib/cldr/pattern.ex
defmodule Cldr.List.Pattern do
@moduledoc """
A list pattern drives list formatting and it defines how to combine
list elements at the beggining, in the middle and at the end of
a list. It also has a special pattern used when the list contains
only two elements.
"""
defstruct [:start, :middle, :end, :two]
@type pattern :: [non_neg_integer() | String.t(), ...]
@type t :: %__MODULE__{
start: pattern(),
middle: pattern(),
end: pattern(),
two: pattern()
}
@valid_options [:start, :middle, :end, :two]
@doc """
Creates a new list format.
A list pattern consists of four string
templates into which list elements are interpolated
when formatting.
The four templates are:
* `:start` used to format the first two
list elements.
* `:middle` is used to format elements in
the middle of the list.
* `:end` is used to format the last two
elements in the list.
* `:two` is used to format a list if
it contains only two elements.
Only the `:start` option is required. It
will be used as the default for any other
option that is not provided.
## Arguments
* `options` is a keyword list of options.
## Options
* `:start` is a pattern template as a string.
This option is required.
* `:middle` is a pattern template as a string.
* `:end` is a pattern template as a string.
* `:two` is a pattern template as a string.
## Returns
`{:ok, pattern}` or
`{:error, reason}`
## Pattern template
A pattern template is a string that contains
two placeholders denoted by `{0}` and `{1}`.
## Example
iex> Cldr.List.Pattern.new(
...> start: "{0}, {1}",
...> middle: "{0}, {1}",
...> end: "{0} and {1}",
...> two: "{0} and {1}"
...> )
{
:ok,
%Cldr.List.Pattern{
end: [0, " and ", 1],
middle: [0, ", ", 1],
start: [0, ", ", 1],
two: [0, " and ", 1]
}
}
"""
def new(options) when is_list(options) do
with {:ok, options} <- validate_options(options) do
start = Keyword.get(options, :start)
struct(__MODULE__, options)
|> put_new(:middle, start)
|> put_new(:end, start)
|> put_new(:two, start)
|> wrap(:ok)
end
end
defp validate_options(options) when is_list(options) do
options =
Enum.reduce_while options, [], fn
{key, string}, acc when key in @valid_options and is_binary(string) ->
case validate_pattern(string) do
{:error, reason} ->
{:halt, {:error, reason}}
{:ok, string} ->
pattern = Cldr.Substitution.parse(string)
{:cont, [{key, pattern} | acc]}
end
{key, value}, _acc when key in @valid_options ->
{:halt, {:error, "Invalid value #{inspect value} found. Option #{inspect key} should be a string"}}
{key, _value}, _acc ->
{:halt, {:error, "Invalid option #{inspect key} found. Valid options are #{inspect @valid_options}"}}
end
case options do
{:error, reason} ->
{:error, reason}
options ->
if Keyword.has_key?(options, :start),
do: {:ok, options},
else: {:error, "Option :start must be provided"}
end
end
defp validate_pattern(string) when is_binary(string) do
if String.contains?(string, "{0}") && String.contains?(string, "{1}") do
{:ok, string}
else
{:error, "Invalid pattern #{inspect string}. A pattern must have two placeholders {0} and {1}"}
end
end
defp put_new(options, key, default) do
if Map.get(options, key), do: options, else: Map.put(options, key, default)
end
defp wrap(term, atom) do
{atom, term}
end
end