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

feat: simplified dotenv! usage and added dotenv_override! macro #107

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 3 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Start of .env file
# Comment line with single ' quote
# Comment line with double " quote
# Comment line, starts with space with double " quote
# Comment line, starts with space with double " quote

USER=dotenv!
CODEGEN_TEST_VAR1="hello!"
CODEGEN_TEST_VAR2="'quotes within quotes'"
CODEGEN_TEST_VAR3="double quoted with # hash in value"
Expand All @@ -11,7 +12,7 @@ CODEGEN_TEST_VAR5=not_quoted_with_#_hash_in_value
CODEGEN_TEST_VAR6=not_quoted_with_comment_beheind # var6 comment
CODEGEN_TEST_VAR7=not\ quoted\ with\ escaped\ space
CODEGEN_TEST_VAR8="double quoted with comment beheind" # var7 comment
CODEGEN_TEST_VAR9="Variable starts with a whitespace"
CODEGEN_TEST_VAR9="Variable starts with a whitespace"
CODEGEN_TEST_VAR10= "Value starts with a whitespace after ="
CODEGEN_TEST_VAR11 ="Variable ends with a whitespace before ="
CODEGEN_TEST_MULTILINE1="First Line
Expand Down
11 changes: 11 additions & 0 deletions dotenv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ fn main() {

The `dotenv!` macro provided by `dotenvy_macro` crate can be used.

```rs
use dotenvy_macro::dotenv;

fn main() {
// load environment variables from .env file
dotenvy_macro::dotenv!();

env!("PATH");
}
```

## Minimum supported Rust version

Currently: **1.68.0**
Expand Down
62 changes: 13 additions & 49 deletions dotenv_codegen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,29 @@
#![forbid(unsafe_code)]

use quote::quote;
use std::env::{self, VarError};
use syn::{parse::Parser, punctuated::Punctuated, spanned::Spanned, Token};

#[proc_macro]
pub fn dotenv(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
dotenv_inner(input.into()).into()
}

fn dotenv_inner(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
pub fn dotenv(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
if let Err(err) = dotenvy::dotenv() {
let msg = format!("Error loading .env file: {}", err);
return quote! {
compile_error!(#msg);
};
}
.into();
}

match expand_env(input) {
Ok(stream) => stream,
Err(e) => e.to_compile_error(),
}
quote! {}.into()
}

fn expand_env(input_raw: proc_macro2::TokenStream) -> syn::Result<proc_macro2::TokenStream> {
let args = <Punctuated<syn::LitStr, Token![,]>>::parse_terminated
.parse(input_raw.into())
.expect("expected macro to be called with a comma-separated list of string literals");

let mut iter = args.iter();

let var_name = iter
.next()
.ok_or_else(|| syn::Error::new(args.span(), "dotenv! takes 1 or 2 arguments"))?
.value();
let err_msg = iter.next();

if iter.next().is_some() {
return Err(syn::Error::new(
args.span(),
"dotenv! takes 1 or 2 arguments",
));
#[proc_macro]
pub fn dotenv_override(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
if let Err(err) = dotenvy::dotenv_override() {
let msg = format!("Error loading .env file: {}", err);
return quote! {
compile_error!(#msg);
}
.into();
}

match env::var(&var_name) {
Ok(val) => Ok(quote!(#val)),
Err(e) => Err(syn::Error::new(
var_name.span(),
err_msg.map_or_else(
|| match e {
VarError::NotPresent => {
format!("environment variable `{}` not defined", var_name)
}

VarError::NotUnicode(s) => format!(
"environment variable `{}` was not valid unicode: {:?}",
var_name, s
),
},
|lit| lit.value(),
),
)),
}
quote! {}.into()
}
15 changes: 5 additions & 10 deletions dotenv_codegen/tests/basic_dotenv_macro.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
#[test]
fn dotenv_works() {
assert_eq!(dotenvy_macro::dotenv!("CODEGEN_TEST_VAR1"), "hello!");
dotenvy_macro::dotenv!();
assert_eq!(env!("CODEGEN_TEST_VAR1"), "hello!");
}

#[test]
fn two_argument_form_works() {
assert_eq!(
dotenvy_macro::dotenv!(
"CODEGEN_TEST_VAR2",
"err, you should be running this in the 'dotenv_codegen' \
directory to pick up the right .env file."
),
"'quotes within quotes'"
);
fn dotenv_override_works() {
dotenvy_macro::dotenv_override!();
assert_eq!(env!("USER"), "dotenv!");
}