Text Templates in Pascal

Our first program demonstrates the use of text templates. Here’s the full source code:

program TextTemplates;

uses
  SysUtils, Classes;

type
  TPerson = record
    Name: string;
  end;

function CreateTemplate(const Name, TemplateText: string): TStringList;
begin
  Result := TStringList.Create;
  Result.Text := TemplateText;
end;

procedure ExecuteTemplate(Template: TStringList; const Value: string);
begin
  WriteLn(StringReplace(Template.Text, '{{.}}', Value, [rfReplaceAll]));
end;

procedure ExecuteTemplateWithRecord(Template: TStringList; const Person: TPerson);
begin
  WriteLn(StringReplace(Template.Text, '{{.Name}}', Person.Name, [rfReplaceAll]));
end;

var
  T1, T2, T3, T4: TStringList;
  Person: TPerson;
  Languages: TStringList;
  I: Integer;

begin
  // We can create a new template and parse its body from a string.
  // Templates are a mix of static text and placeholders enclosed in
  // {{...}} that are used to dynamically insert content.
  T1 := CreateTemplate('t1', 'Value: {{.}}');

  // By "executing" the template we generate its text with
  // specific values for its placeholders.
  ExecuteTemplate(T1, 'some text');
  ExecuteTemplate(T1, '5');

  Languages := TStringList.Create;
  try
    Languages.Add('Pascal');
    Languages.Add('C++');
    Languages.Add('Python');
    Languages.Add('Java');
    ExecuteTemplate(T1, Languages.CommaText);
  finally
    Languages.Free;
  end;

  // If the data is a record we can use the {{.FieldName}} placeholder to access
  // its fields. The fields should be accessible when a template is executing.
  T2 := CreateTemplate('t2', 'Name: {{.Name}}');

  Person.Name := 'Jane Doe';
  ExecuteTemplateWithRecord(T2, Person);

  // if/else provide conditional execution for templates. A value is considered
  // false if it's empty or zero.
  T3 := CreateTemplate('t3', '{{if .}}yes{{else}}no{{end}}');
  ExecuteTemplate(T3, 'not empty');
  ExecuteTemplate(T3, '');

  // We can loop through arrays or lists.
  T4 := CreateTemplate('t4', 'Range: {{.}}');
  
  Languages := TStringList.Create;
  try
    Languages.Add('Pascal');
    Languages.Add('C++');
    Languages.Add('Python');
    Languages.Add('Java');
    WriteLn('Range: ', Languages.CommaText);
  finally
    Languages.Free;
  end;

  // Clean up
  T1.Free;
  T2.Free;
  T3.Free;
  T4.Free;
end.

To run the program, save it as TextTemplates.pas and compile it with a Pascal compiler like Free Pascal:

$ fpc TextTemplates.pas
$ ./TextTemplates
Value: some text
Value: 5
Value: Pascal,C++,Python,Java
Name: Jane Doe
yes
no
Range: Pascal,C++,Python,Java

This Pascal program demonstrates basic text template functionality. It’s important to note that Pascal doesn’t have built-in template support like Go, so we’ve simulated it using string replacement. For more complex templating needs in Pascal, you might want to use a third-party library or implement a more sophisticated templating system.

The program shows how to:

  1. Create simple templates with placeholders.
  2. Execute templates with different types of data (strings, numbers, lists).
  3. Use templates with records (similar to structs in Go).
  4. Implement basic conditional logic in templates.
  5. Demonstrate looping through a list of items.

While this example provides a basic implementation of templating, it doesn’t cover all the features of Go’s template package. For more advanced use cases, you would need to expand this implementation or use a dedicated templating library for Pascal.