Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

liuchong/econf

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

econf

econf loads strongly typed configuration values from environment variables or from files referenced by environment variables. This repository contains three sibling implementations with one shared behavior spec:

  • go/: Go module
  • rust/: Rust workspace with runtime crate and derive macro
  • zig/: Zig package
  • spec/: shared behavior and conformance scenarios

Shared Behavior

For a config type and field, econf builds an environment variable name by converting both names to uppercase snake case and joining them with _.

MyConfig.Host       -> MY_CONFIG_HOST
MyConfig.KeyListNUM -> MY_CONFIG_KEY_LIST_NUM

Each field may be loaded from either:

MY_CONFIG_HOST=value
MY_CONFIG_HOST_FILE=/path/to/file-containing-value

When both are present, *_FILE wins. File contents are trimmed before parsing. Missing or empty values leave the field unchanged. Fields whose names start with _ are skipped.

Supported baseline type families are strings, booleans, signed integers, floats, and slices/vectors of those scalar types. Unsigned integers are intentionally outside the shared baseline.

Go

import econf "github.com/liuchong/econf/go"

type MyConfig struct {
    Host    string
    Port    int
    Enabled bool
    Names   []string
    _secret string
}

func main() {
    cfg := &MyConfig{}
    econf.SetFields(cfg)
}

Go parsing errors panic, matching the original package behavior. See go/README.md.

Rust

use econf::{load, Econf};

#[derive(Default, Econf)]
struct MyConfig {
    host: String,
    port: i32,
    enabled: bool,
    names: Vec<String>,
    _secret: String,
}

fn main() -> econf::Result<()> {
    let mut cfg = MyConfig::default();
    load(&mut cfg)?;
    Ok(())
}

Rust returns Result for parse and file errors. See rust/README.md.

Zig

const std = @import("std");
const econf = @import("econf");

const MyConfig = struct {
    host: []const u8 = "",
    port: i32 = 0,
    enabled: bool = false,
    names: []const []const u8 = &.{},
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    var arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer arena.deinit();
    const allocator = arena.allocator();

    var cfg = MyConfig{};
    try econf.load(&cfg, allocator, .{});
}

Zig returns errors and uses the caller's allocator for loaded strings and slices. See zig/README.md.

Conformance

All implementations cover the same real-world scenarios: scalar fields, file override, string/int/float slices, skipped _ fields, custom separators, and parse errors.

Run the full suite:

./scripts/conformance.sh

See spec/conformance.md for the scenario-to-test mapping.

License

MIT

About

A simple configure tool use ENV or ENV_FILE

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Morty Proxy This is a proxified and sanitized view of the page, visit original site.