env
Load key/value pairs from a .env file into an in-memory map.
introduce env| Item | Signature | Returns |
|---|---|---|
env_map | module variable, map | everything loaded so far |
discover_dot_file | discover_dot_file(filename?) | None |
get_env | get_env(key) | str or None |
set_env | set_env(key, value) | the stored value |
This module does not touch the real process environment — it is a map that
happens to be populated from a file. For actual environment variables use
os.env_get / os.env_set.
#discover_dot_file(filename?)
Load every KEY=VALUE line of filename into env_map — or, with
no argument, of the file named .env in the current working directory.
Nothing is printed: the file holds secrets.
introduce env
env.discover_dot_file()
println(env.get_env("API_KEY")) // abc123Given .env:
API_KEY=abc123
DEBUG=trueenv.discover_dot_file("config/prod.env")If the file is not there (or, with no argument, no .env is in the current
directory), it fails with No environment file was found file.
Parsing is deliberately simple:
| Input line | Stored as |
|---|---|
API_KEY=abc123 | API_KEY → abc123 |
QUOTED="has spaces" | QUOTED → "has spaces" — quotes are kept |
EQ=a=b | EQ → a=b — only the first = separates key from value |
# comment | ignored |
| blank line | ignored |
Windows line endings (\r\n) are handled.
Strip quotes yourself if your file uses them:
introduce env
introduce strings
env.discover_dot_file()
key := strings.strip(env.get_env("QUOTED"), "\"")#get_env(key)
The value for key, or None. A miss also prints a line to stdout —
Key: NOPE not found in env_map — so it is not silent.
println(env.get_env("API_KEY")) // abc123
println(env.get_env("NOPE"))
// Key: NOPE not found in env_map
// NoneTo check quietly, look at the map directly: has(env.env_map, "NOPE").
#set_env(key, value)
Store a value in the map by hand — useful for defaults before loading a file, or for values that are not in one.
env.set_env("REGION", "us-east-1")
println(env.get_env("REGION")) // us-east-1#env_map
The map itself, readable and writable.
env.discover_dot_file()
println(env.env_map) // {API_KEY: abc123, DEBUG: true}
println(has(env.env_map, "DEBUG")) // TrueModule-level state is shared across every file that imports the module, so one
discover_dot_file() at startup is enough for the whole program.
#Worked example
introduce env
introduce os
introduce strings
// Config precedence: real environment beats .env, .env beats the default.
fun setting(key <str>, fallback <str>) {
from_os := os.env_get(key)
option {
from_os != None -> { from_os }
has(env.env_map, key) -> { strings.strip(env.env_map[key], "\"") }
{ fallback }
}
}
env.discover_dot_file()
println(setting("PORT", "8000"))Reading env_map directly rather than get_env keeps a miss from printing.
See also: os for the real process environment, toml / json for structured configuration files.