Nvir.Parser behaviour (Nvir v0.13.2)
View SourceA behaviour for environment variables sources parser.
The default implementation used in Nvir is Nvir.Parser.RDB
. It can only
parse classic dotenv files.
Parsing other sources such as YAML files or encrypted files requires to provide your own parser.
See the documentation of the parse_file/1
callback for implementation
guidelines.
Summary
Callbacks
This callback must return a {:ok, variables}
or {:error, reason}
tuple.
Functions
Takes a parsed value returned by the parser implementation, and a resolver for the interpolated variables.
Types
Callbacks
@callback parse_file(path :: String.t()) :: {:ok, [variable()]} | {:error, Exception.t()}
This callback must return a {:ok, variables}
or {:error, reason}
tuple.
The variables
is a list of {key, value}
tuples where:
key
is a stringvalue
is either a string or atemplate
- A
template
is a list ofchunks
- A
chunk
is either a string or a{:var, varname}
tuple.
Templates are used for interpolation. When a variable uses interpolation, the parser must not attempt to read the interpolated variables from environment, but rather return a template instead of a binary value.
Variables used in interpolation within other variables values do not have to exist in the file. Nvir uses a resolver to provide those values to execute the templates.
In this example, the INTRO
variable is defined in the same file, but the
WHO
variable is not. This makes not difference, as the parser must not
require those values.
iex> file_contents = "INTRO=hello\nGREETING=$INTRO $WHO!"
iex> Nvir.Parser.RDB.parse_string(file_contents)
{:ok, [{"INTRO", "hello"}, {"GREETING", [{:var, "INTRO"}, " ", {:var, "WHO"}, "!"]}]}
You can test and debug your parser by using Nvir.Parser.interpolate_var/2
and a simple resolver.
iex> file_contents = "GREETING=$INTRO $WHO!"
iex> {:ok, [{"GREETING", template}]} = Nvir.Parser.RDB.parse_string(file_contents)
iex> resolver = fn
...> "INTRO" -> "Hello"
...> "WHO" -> "World"
...> end
iex> Nvir.Parser.interpolate_var(template, resolver)
"Hello World!"
Expected results examples
Given this file content:
WHO=World
GREETING=Hello $WHO!
The parse_file/1
callback should return the following:
{:ok,
[
{"WHO", "World"},
{"GREETING", ["Hello ", {:var, "WHO"}, "!"]}
]}
With this one using accumulative interpolation:
PATH=/usr/local/bin
PATH=$PATH:/usr/bin
PATH=/home/me/bin:$PATH
The parser should produce the following:
{:ok,
[
{"PATH", "/usr/local/bin"},
{"PATH", [{:var, "PATH"}, ":/usr/bin"]},
{"PATH", ["/home/me/bin:", {:var, "PATH"}]}
]}
Functions
@spec interpolate_var(String.t(), template_resolver()) :: String.t()
Takes a parsed value returned by the parser implementation, and a resolver for the interpolated variables.
A resolver is a function that takes a variable name and returns a string or
nil
.
Example
iex> envfile = """
iex> GREETING=Hello $NAME!
iex> """
iex> {:ok, [{"GREETING", variable}]} = Nvir.Parser.RDB.parse_string(envfile)
iex> resolver = fn "NAME" -> "World" end
iex> Nvir.Parser.interpolate_var(variable, resolver)
"Hello World!"