Skip to content

Commit

Permalink
Version 1.0.0 released
Browse files Browse the repository at this point in the history
Final version of the lib to manage DotEnv files in Delphi, and you can also use the lib to manage environment variables
  • Loading branch information
rafael-figueiredo-alves committed Dec 27, 2022
1 parent 52c19da commit 691ce57
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 50 deletions.
6 changes: 5 additions & 1 deletion Demo/Win32/Debug/.env-example
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
MeuNome=Rafael de Figueiredo Alves
# Comentário

MeuNome=Rafael Alves
DB_USERNAME=${MeuNome}\Developer # teste
Nome3=${MeuNome} - ${DB_USERNAME} - ${APPDATA} OK # teste poderoso
11 changes: 9 additions & 2 deletions Demo/uDemo.pas
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ implementation
{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var teste: string;
teste2: char;
begin
//Pegando váriáveis do Ambiente diretamente pelo nome(string)
Memo1.Lines.Add(DotEnv.Env('appdata'));
Expand All @@ -43,8 +45,13 @@ procedure TForm2.Button1Click(Sender: TObject);
procedure TForm2.Button2Click(Sender: TObject);
begin
//Pegando variáveis do arquivo .env
Memo1.Lines.Add(DotEnv.Env('MeuNome', true));
Memo1.Lines.Add(DotEnv.Env(DB_USERNAME));
Memo1.Lines.Add(DotEnv.Env('MeuNome')); //Usando o nome da variável
Memo1.Lines.Add(DotEnv.Env(DB_USERNAME)); //Usando o enumerado default (procura dentro do arquivo se há uma variável com o nome
Memo1.Lines.Add(DotEnv.Env('Nome3'));

//Forma de Definir caminho do arquivo
//DotEnv.Config('D:\Meus Projetos\DotEnv4Delphi\Demo\Win32\Debug\.env');
//Memo1.Lines.Add(DotEnv.Env('MeuNome'));
end;

end.
232 changes: 185 additions & 47 deletions src/DotEnv4Delphi.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,67 @@

interface

uses System.Generics.Collections;

type
{$Region 'EnumEnvVars'}
TEnvVar = (ALLUSERSPROFILE, APPDATA, CLIENTNAME, COMMONPROGRAMFILES, COMPUTERNAME, COMSPEC, HOMEDRIVE, HOMEPATH, LOGONSERVER,
NUMBER_OF_PROCESSORS, OS, PATH, PATHEXT, PROCESSOR_ARCHITECTURE, PROCESSOR_IDENTIFIER, PROCESSOR_LEVEL,
PROCESSOR_REVISION, PROGRAMFILES, SESSIONNAME, SYSTEMDRIVE, SYSTEMROOT, TEMP, TMP, USERDOMAIN, USERNAME, USERPROFILE,
WINDIR, DB_USERNAME, DBUSERNAME, DBPORT, DB_PORT, PORT, HOSTNAME, DB_HOST, DB_USER, DBHOST, DBUSER, DBPASS, DB_PASS,
PASSWORD, DBPASSWORD, BASE_URL, TOKEN, API_TOKEN);

TDotEnv4Delphi = class
class function Env(const name: string; fromDotEnvFile: Boolean = False): string; overload;
class function Env(const EnvVar: TEnvVar; fromDotEnvFile: Boolean = False): string; overload;
class function GetVersion: string;
{$EndRegion}

{$Region 'DotEnv4Delphi´s interface'}
iDotEnv4Delphi = interface
['{3BF1532F-91B1-4C1F-A40A-CD81F8754451}']
function Config(const OnlyFromEnvFile: Boolean = False): iDotEnv4Delphi; overload;
function Config(const path: string = ''; OnlyFromEnvFile: Boolean = False): iDotEnv4Delphi; overload;
function Env(const name: string): string; overload;
function Env(const EnvVar: TEnvVar): string; overload;
function GetVersion: string;
end;
{$EndRegion}

{$Region 'DotEnv4Delphi´s class declaration'}
TDotEnv4Delphi = class(TInterfacedObject, iDotEnv4Delphi)
private
class var FInstance: iDotEnv4Delphi;
fromDotEnvFile: Boolean;
EnvPath: string;
EnvDict: TDictionary<string, string>;
procedure ReadEnvFile;
function ReadValueFromEnvFile(const key: string): string;
public
constructor Create;
Destructor Destroy; override;
class function New: iDotEnv4Delphi;
function Config(const OnlyFromEnvFile: Boolean = False): iDotEnv4Delphi; overload;
function Config(const path: string = ''; OnlyFromEnvFile: Boolean = False): iDotEnv4Delphi; overload;
function Env(const name: string): string; overload;
function Env(const EnvVar: TEnvVar): string; overload;
function GetVersion: string;
end;
{$EndRegion}

DotEnv = TDotEnv4Delphi;
var
DotEnv: iDotEnv4Delphi;

implementation

uses
System.SysUtils,
System.TypInfo,
System.Generics.Collections, System.Classes;
System.Classes;

{ TDotEnv4Delphi }

function ReadValueFromEnvFile(const key: string): string;
var
EnvFile : TDictionary<string, string>;

procedure PopulateDictionary(const Dict: TDictionary<string, string>);
var
fFile : tstringlist;
EnvFile : string;
position : Integer;
begin
EnvFile := ExtractFilePath(ParamStr(0)) + '.env';
fFile := TStringList.Create;
try
fFile.LoadFromFile(EnvFile);
for position := 0 to fFile.Count - 1 do
begin
if not (fFile.Names[position].ToUpper = EmptyStr) then
Dict.Add(fFile.Names[position].ToUpper, fFile.Values[fFile.Names[position]]);
end;
finally
FreeAndNil(fFile)
end;
end;
function TDotEnv4Delphi.ReadValueFromEnvFile(const key: string): string;
begin
EnvFile := TDictionary<string, string>.create;
try
PopulateDictionary(EnvFile);
EnvFile.TryGetValue(key.ToUpper, Result);
finally
FreeAndNil(EnvFile);
end;
EnvDict.TryGetValue(key.ToUpper, Result);
end;

class function TDotEnv4Delphi.Env(const name: string; fromDotEnvFile: Boolean): string;
function TDotEnv4Delphi.Env(const name: string): string;
begin
if fromDotEnvFile then
begin
Expand All @@ -73,23 +76,158 @@ class function TDotEnv4Delphi.Env(const name: string; fromDotEnvFile: Boolean):
Result := ReadValueFromEnvFile(name);
end;

class function TDotEnv4Delphi.Env(const EnvVar: TEnvVar; fromDotEnvFile: Boolean): string;
function TDotEnv4Delphi.Config(const OnlyFromEnvFile: Boolean): iDotEnv4Delphi;
begin
if fromDotEnvFile then
Result := Self;
fromDotEnvFile := OnlyFromEnvFile;
end;

function TDotEnv4Delphi.Config(const path: string; OnlyFromEnvFile: Boolean): iDotEnv4Delphi;
begin
Result := Self;
fromDotEnvFile := OnlyFromEnvFile;
if (path <> EmptyStr) and (path <> EnvPath) then
begin
Result := ReadValueFromEnvFile(GetEnumName(TypeInfo(TEnvVar), integer(EnvVar)));
Exit;
EnvPath := path;
ReadEnvFile;
end;
end;

Result := GetEnvironmentVariable(GetEnumName(TypeInfo(TEnvVar), integer(EnvVar)));
constructor TDotEnv4Delphi.Create;
begin
EnvDict := TDictionary<string, string>.create;
EnvPath := ExtractFilePath(ParamStr(0)) + '.env';
fromDotEnvFile := False;
ReadEnvFile;
end;

if Result = EmptyStr then
Result := ReadValueFromEnvFile(GetEnumName(TypeInfo(TEnvVar), integer(EnvVar)));
destructor TDotEnv4Delphi.Destroy;
begin
FreeAndNil(EnvDict);
inherited;
end;

function TDotEnv4Delphi.Env(const EnvVar: TEnvVar): string;
begin
Result := Env(GetEnumName(TypeInfo(TEnvVar), integer(EnvVar)));
end;

function TDotEnv4Delphi.GetVersion: string;
begin
Result := '1.0.0';
end;

class function TDotEnv4Delphi.GetVersion: string;
class function TDotEnv4Delphi.New: iDotEnv4Delphi;
begin
if not Assigned(FInstance) then
FInstance := Self.Create;

Result := FInstance;
end;

procedure TDotEnv4Delphi.ReadEnvFile;

function PegarValor(const valor: string): string;

function RemoverComentario(const valor: string): string;
var
positionOfLastQuote: integer;
begin
if (valor.StartsWith('"')) or (valor.StartsWith(#39)) then
begin
positionOfLastQuote := Pos('"', Copy(valor, 2, length(valor) - 1));
if positionOfLastQuote = 0 then
positionOfLastQuote := Pos(#39, Copy(valor, 2, length(valor) - 1));

if positionOfLastQuote > 0 then
begin
if Pos('#', valor) > positionOfLastQuote then
Result := Copy(valor, 1, Pos('#', valor) - 1);
end;
end
else
begin
if Pos('#', valor) > 0 then
Result := Copy(valor, 1, Pos('#', valor) - 1)
else
Result := valor;
end;
end;

function Interpolar(const valor: string): string;
var
PosIni, PosFim : integer;
chave, ValorChave: string;
begin
Result := valor;
if (not valor.StartsWith('"')) and (not valor.StartsWith(#39)) then
begin
while Pos('${', Result) > 0 do
begin
PosIni := Pos('${', Result);
PosFim := Pos('}', Result);
chave := Copy(Result, PosIni + 2, PosFim - (PosIni + 2));
ValorChave := Env(chave);
Result := StringReplace(Result, '${' + chave + '}', ValorChave, [rfReplaceAll]);
end;
end;
end;

function RemoverAspas(const valor: string): string;
var
positionOfLastQuote: integer;
begin
if (valor.StartsWith('"')) or (valor.StartsWith(#39)) then
begin
positionOfLastQuote := Pos('"', Copy(valor, 2, length(valor) - 1));
if positionOfLastQuote = 0 then
positionOfLastQuote := Pos(#39, Copy(valor, 2, length(valor) - 1));

if positionOfLastQuote > 0 then
begin
Result := StringReplace(valor, '"', '', [rfReplaceAll]);
Result := StringReplace(valor, #39, '', [rfReplaceAll]);
end;
end
else
Result := valor;
end;
begin
Result := Trim(RemoverAspas(Interpolar(RemoverComentario(valor))));
end;

procedure PopulateDictionary(const Dict: TDictionary<string, string>);
var
fFile : tstringlist;
EnvFile : string;
position : Integer;
begin
fFile := TStringList.Create;
try
fFile.LoadFromFile(EnvPath);
for position := 0 to fFile.Count - 1 do
begin
if not (fFile.Names[position].ToUpper = EmptyStr) then
begin
Dict.Add(fFile.Names[position].ToUpper, PegarValor(fFile.Values[fFile.Names[position]]));
end;
end;
finally
FreeAndNil(fFile)
end;
end;
begin
if FileExists(EnvPath) then
begin
EnvDict.Clear;
PopulateDictionary(EnvDict);
end;
end;

initialization

begin
Result := '0.0.2-a';
DotEnv := tDotEnv4Delphi.New;
end;

end.

0 comments on commit 691ce57

Please sign in to comment.