defmodule LivebookEnv do
@moduledoc """
A tiny utility for importing .env files into Livebooks.
"""
@doc """
Import a .env file into your current Livebook.
Assuming you have a .env file containing `FOOBAR=123`:
## Examples
iex> LivebookEnv.import_dotenv("/Users/alex/myproject/.env)
{:ok, "Imported 1 variable(s): FOOBAR"}
"""
def import_dotenv(envfile_path) do
env = envfile_path
|> File.read!()
|> parse_contents()
System.put_env(env)
{
:ok,
"Imported #{Enum.count(env)}: #{Map.keys(env) |> Enum.join(", ")}"
}
end
# Implementation
@quotes_pattern ~r/^(['"])(.*)\1$/
@pattern ~r/
\A
(?:export\s+)? # optional export
([\w\.]+) # key
(?:\s*=\s*|:\s+?) # separator
( # optional value begin
'(?:\'|[^'])*?' # single quoted value
| # or
"(?:\"|[^"])*?" # double quoted value
| # or
[^#\n]+? # unquoted value
)? # value end
(?:\s*\#.*)? # optional comment
\z
/x
defp parse_contents(contents) do
values = String.split(contents, "\n")
values
|> Enum.flat_map(&Regex.scan(@pattern, &1))
|> trim_quotes_from_values
|> Enum.reduce(Map.new(), &collect_into_map/2)
end
defp collect_into_map([_whole, k, v], env), do: Map.put(env, k, v)
defp trim_quotes_from_values(values) do
values
|> Enum.map(fn values ->
Enum.map(values, &trim_quotes/1)
end)
end
defp trim_quotes(value) do
String.replace(value, @quotes_pattern, "\\2")
end
end