Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Env.readFile() #473

Closed
1 task done
Jason2605 opened this issue Oct 19, 2021 · 2 comments · Fixed by #496
Closed
1 task done

[FEATURE] Env.readFile() #473

Jason2605 opened this issue Oct 19, 2021 · 2 comments · Fixed by #496
Labels
feature request Discussion about a new feature

Comments

@Jason2605
Copy link
Member

Jason2605 commented Oct 19, 2021

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem?

I currently use a utility function to read env vars from an .env file, however, I feel this is functionality that will be used enough that it warrants something built-in to accomplish this.

Describe the solution you'd like

import Env;

Env.readFile(".env");

Maybe even the default argument is ".env"

import Env;

Env.readFile(); // Implicitly reads ".env"

Describe alternatives you've considered

import Env;

def readEnv(path) {
    with(path, "r") {
        var line;
        // When you reach the end of the file, nil is returned
        while((line = file.readLine()) != nil) {
            if (!line)
                continue;

            var [variable, value] = line.split("=");
            Env.set(variable, value);
        }
    }
}

Additional context

The above implementation is a bit naive and could do with some work, for example, if an env var value contains a = it's going to cause issues.

@Jason2605 Jason2605 added the feature request Discussion about a new feature label Oct 19, 2021
@briandowns
Copy link
Contributor

I've been using this in a few projects and it's been working well so far.

import Env;
import System;

const ENV_FILE_NAME = ".env";
const COMMENT_CHAR = "#";
const SEPERATOR = "=";

/**
 * load loads all entries in the local .env unless
 * a path is provided and then that file is loaded.
 */
def load(path) {
    var full_path = "";

    if (path == "") {
        full_path = ENV_FILE_NAME;
    } else {
        full_path = path;
    }

    var data = {};

    with(full_path, "r") {
        var line;
        var line_num = 0;

        while((line = file.readLine()) != nil) {
            line_num += 1;

            if (line.startsWith(COMMENT_CHAR)) {
                continue;
            }

            if (line.contains(SEPERATOR)) {
                var comp_count = line.split(SEPERATOR).len();
                if (comp_count == 2) {
                    var key = line.split(SEPERATOR)[0].strip();
                    var value = line.split(SEPERATOR)[1].strip();
                    
                    data[key] = value;
                } else {
                    return Error("error: line {} malformed entry".format(line_num)); 
                }
            }
        }
    }

    if (data.len() == 0) {
        return success(1);
    }

    var keys = data.keys();
    for (var i = 0; i < keys.len(); i += 1) {
        Env.set(keys[i], data[keys[i]]);
    }

    return Success(0);
}

// main
{
    var res = load("").match(
        def (result) => result,
        def (error) => {
            print(error);
            System.exit(1);
        }
    );

    var thread_count = Env.get("threads");
    print("thread count: {}".format(thread_count));

    var x = Env.get("x");
    print("x: {}".format(x));

    System.exit(0);
}

@Jason2605
Copy link
Member Author

It's a nice proposal, however, will suffer from the same issue where if the value contains the delimiter you're going to get a malformed output. I think a neat approach to solving this is to actually extend .split() so that you can pass an optional second parameter with the amount of times a split will occur.

"test=test=test".split("="); // ["test", "test", "test"]
"test=test=test".split("=", 1); // ["test", "test=test"]

This was referenced Dec 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Discussion about a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants