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

Env.readFile() #496

Merged
merged 6 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ dictu.ilk
dictu.pdb
test1.du
.vscode/
/.env
21 changes: 21 additions & 0 deletions docs/docs/standard-lib/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,24 @@ Env.set("key", "test");
Env.set("key", nil); // Remove env var
Env.set("key", 10); // set() arguments must be a string or nil.
```

### Env.readFile(string: path -> optional)

To read environment variables from a file this helper method is provided.
By default it will attempt to read `.env` unless a different path is supplied.
Returns a Result type and on success will unwrap to nil.

Note: You are able to have comments in the `.env` file via the use of `#` (both in-line and first character).

```env
# This is a comment
TEST=10
TESTING=100 # In-line comment
```

```cs
Env.readFile(); // <Result Suc>

print(Env.get("TEST")); // 10
print(Env.get("TESTING")); // 100
```
3 changes: 2 additions & 1 deletion scripts/generate.du
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ var files = [
'src/vm/datatypes/lists/list',
'src/vm/datatypes/dicts/dict',
'src/vm/datatypes/result/result',
'src/optionals/unittest/unittest'
'src/optionals/unittest/unittest',
'src/optionals/env/env'
];

for (var i = 0; i < files.len(); i += 1) {
Expand Down
32 changes: 32 additions & 0 deletions src/optionals/env/env-source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#define DICTU_ENV_SOURCE "import Env;\n" \
"\n" \
"def readFile(path='.env') {\n" \
" const SPLIT_DELIMITER = '=';\n" \
" const COMMENT = '#';\n" \
"\n" \
" with(path, 'r') {\n" \
" var line;\n" \
" var lineCount = 0;\n" \
" // When you reach the end of the file, nil is returned\n" \
" while((line = file.readLine()) != nil) {\n" \
" lineCount = lineCount + 1;\n" \
" if (not line or line.startsWith(COMMENT))\n" \
" continue;\n" \
"\n" \
" if (not line.contains('='))\n" \
" return Error('Malformed entry on line {}'.format(lineCount));\n" \
"\n" \
" const [variable, rawValue] = line.split(SPLIT_DELIMITER, 1);\n" \
" // Strip out any in-line comments\n" \
" const value = rawValue.split(COMMENT, 1);\n" \
" const result = Env.set(variable.strip(), value[0].strip());\n" \
"\n" \
" if (not result.success()) {\n" \
" return result;\n" \
" }\n" \
" }\n" \
" }\n" \
"\n" \
" return Success(nil);\n" \
"}\n" \

22 changes: 13 additions & 9 deletions src/optionals/env.c → src/optionals/env/env.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "env.h"

#include "env-source.h"

#ifdef _WIN32
#define unsetenv(NAME) _putenv_s(NAME, "")
int setenv(const char *name, const char *value, int overwrite) {
Expand All @@ -25,7 +27,7 @@ static Value get(DictuVM *vm, int argCount, Value *args) {
runtimeError(vm, "get() arguments must be a string.");
return EMPTY_VAL;
}

char *value = getenv(AS_CSTRING(args[0]));

if (argCount == 2) {
Expand Down Expand Up @@ -77,19 +79,21 @@ static Value set(DictuVM *vm, int argCount, Value *args) {
}

Value createEnvModule(DictuVM *vm) {
ObjString *name = copyString(vm, "Env", 3);
push(vm, OBJ_VAL(name));
ObjModule *module = newModule(vm, name);
push(vm, OBJ_VAL(module));
ObjClosure *closure = compileModuleToClosure(vm, "Env", DICTU_ENV_SOURCE);

if (closure == NULL) {
return EMPTY_VAL;
}

push(vm, OBJ_VAL(closure));

/**
* Define Env methods
*/
defineNative(vm, &module->values, "get", get);
defineNative(vm, &module->values, "set", set);
defineNative(vm, &closure->function->module->values, "get", get);
defineNative(vm, &closure->function->module->values, "set", set);

pop(vm);
pop(vm);

return OBJ_VAL(module);
return OBJ_VAL(closure);
}
31 changes: 31 additions & 0 deletions src/optionals/env/env.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Env;

def readFile(path='.env') {
const SPLIT_DELIMITER = '=';
const COMMENT = '#';

with(path, 'r') {
var line;
var lineCount = 0;
// When you reach the end of the file, nil is returned
while((line = file.readLine()) != nil) {
lineCount = lineCount + 1;
if (not line or line.startsWith(COMMENT))
continue;

if (not line.contains('='))
return Error('Malformed entry on line {}'.format(lineCount));

const [variable, rawValue] = line.split(SPLIT_DELIMITER, 1);
// Strip out any in-line comments
const value = rawValue.split(COMMENT, 1);
const result = Env.set(variable.strip(), value[0].strip());

if (not result.success()) {
return result;
}
}
}

return Success(nil);
}
4 changes: 2 additions & 2 deletions src/optionals/env.h → src/optionals/env/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include <stdlib.h>
#include <string.h>

#include "optionals.h"
#include "../vm/vm.h"
#include "../optionals.h"
#include "../../vm/vm.h"

Value createEnvModule(DictuVM *vm);

Expand Down
2 changes: 1 addition & 1 deletion src/optionals/optionals.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

BuiltinModules modules[] = {
{"Math", &createMathsModule, false},
{"Env", &createEnvModule, false},
{"Env", &createEnvModule, true},
{"JSON", &createJSONModule, false},
{"Log", &createLogModule, false},
{"Path", &createPathModule, false},
Expand Down
2 changes: 1 addition & 1 deletion src/optionals/optionals.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "../vm/util.h"
#include "math.h"
#include "env.h"
#include "env/env.h"
#include "system.h"
#include "json.h"
#include "log.h"
Expand Down
2 changes: 2 additions & 0 deletions src/vm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,7 @@ static DictuInterpretResult run(DictuVM *vm) {

// If we have imported this module already, skip.
if (tableGet(&vm->modules, fileName, &moduleVal)) {
vm->lastModule = AS_MODULE(moduleVal);
push(vm, moduleVal);
DISPATCH();
}
Expand All @@ -1494,6 +1495,7 @@ static DictuInterpretResult run(DictuVM *vm) {
ip = frame->ip;

tableGet(&vm->modules, fileName, &module);
vm->lastModule = AS_MODULE(module);
}

DISPATCH();
Expand Down
5 changes: 5 additions & 0 deletions tests/env/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TEST=10
INLINE=100 # in-line comment
# IGNORE=1000
SPACES = 30
MALFORMED
13 changes: 12 additions & 1 deletion tests/env/env.du
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* end.du
*
* Testing the Env functions:
* - get(), set()
* - get(), set(), readFile()
*
*/
import Env;
Expand All @@ -15,3 +15,14 @@ assert(Env.set("test", "test").success() == true);
assert(Env.get("test") == "test");
assert(Env.set("test", nil).success() == true);
assert(Env.get("test") == nil);

import Path;

const result = Env.readFile(Path.dirname(__file__) + '/.env');
assert(Env.get("TEST") == "10");
assert(Env.get("INLINE") == "100");
assert(Env.get("IGNORE") == nil);
assert(Env.get("MALFORMED") == nil);

assert(not result.success());
assert(result.unwrapError() == "Malformed entry on line 5");