Current section
Files
Jump to
Current section
Files
lib/envy.ex
defmodule Envy do
@moduledoc """
Provides explicit and auto loading of env files.
## Example
The following will set the `FOO` environment variable with the value of `bar`.
```
foo=bar
```
You can define comments with `#` but can't use `#` in values without wrapping
the value in double quotes.
```
foo="#bar" # Comment
```
"""
@doc """
Loads the `.env` and the `Mix.env` specific env file.
eg: If `Mix.env` is `test` then envy will attempt to load `.env.test`.
"""
def auto_load do
Application.ensure_started(:mix)
current_env = Mix.env |> to_string |> String.downcase
[".env", ".env.#{current_env}"] |> load
end
@doc """
Loads a list of env files.
"""
def load(env_files) do
for path <- env_files do
if File.exists?(path) do
File.read!(path) |> parse
end
end
end
@doc """
Parses env formatted file.
"""
def parse(content) do
content |> get_pairs |> load_env
end
defp get_pairs(content) do
content
|> String.split("\n")
|> Enum.reject(&blank_entry?/1)
|> Enum.reject(&comment_entry?/1)
|> Enum.map(&parse_line/1)
end
defp parse_line(line) do
[key, value] = line
|> String.strip
|> String.split("=")
[key, parse_value(value)]
end
defp parse_value(value) do
if String.starts_with?(value, "\"") do
unquote_string(value)
else
value |> String.split("#", parts: 2) |> List.first
end
end
defp unquote_string(value) do
value
|> String.split(~r{(?<!\\)"}, parts: 3)
|> Enum.drop(1)
|> List.first
|> String.replace(~r{\\"}, ~S("))
end
defp load_env(pairs) when is_list(pairs) do
Enum.each(pairs, fn([key, value]) ->
System.put_env(String.upcase(key), value)
end)
end
defp blank_entry?(string) do
string == ""
end
defp comment_entry?(string) do
String.match?(string, ~r(^\s*#))
end
end