Text Templates in Nim

import os
import strformat
import strutils

# We can create a new template and parse its body from a string.
# Templates are a mix of static text and "actions" enclosed in
# `${}` that are used to dynamically insert content.
proc t1(value: auto): string =
  return fmt"Value is {value}\n"

# By using the `fmt` macro, we can create string templates
# that are checked at compile-time.
let t1Fmt = fmt"Value: {'{'}0{'}'}\n"

# Helper function we'll use below.
proc create(name, t: string): (string) -> string =
  return proc (value: string): string =
    return t.replace("${}", value)

# If the data is an object we can use the `${}` action to access
# its fields. The fields should be accessible when a template is executing.
let t2 = create("t2", "Name: ${}\n")

# The same applies to tables; with tables there is no restriction on the
# case of key names.
import tables

# if/else provide conditional execution for templates. A value is considered
# false if it's the default value of a type, such as 0, an empty string,
# nil, etc.
proc t3(value: string): string =
  if value.len > 0:
    return "yes\n"
  else:
    return "no\n"

# range blocks let us loop through sequences or iterables. Inside
# the range block we can access the current item of the iteration.
proc t4(values: openArray[string]): string =
  result = "Range: "
  for value in values:
    result.add(value & " ")
  result.add("\n")

proc main() =
  echo t1("some text")
  echo t1(5)
  echo t1(@["Nim", "Python", "C++", "C#"])

  echo t1Fmt % "some text"
  echo t1Fmt % $5
  echo t1Fmt % $@["Nim", "Python", "C++", "C#"]

  type Person = object
    name: string

  let jane = Person(name: "Jane Doe")
  echo t2(jane.name)

  var mickey = {"Name": "Mickey Mouse"}.toTable
  echo t2(mickey["Name"])

  echo t3("not empty")
  echo t3("")

  echo t4(["Nim", "Python", "C++", "C#"])

when isMainModule:
  main()

This Nim code demonstrates text templates similar to the Go example. Here’s a breakdown of the changes and explanations:

  1. Nim doesn’t have a built-in template system like Go’s text/template, so we use string interpolation and the strformat module to achieve similar functionality.

  2. The t1 function demonstrates simple string interpolation using Nim’s fmt string formatting.

  3. The create function shows how to create a simple template function that replaces a placeholder with a value.

  4. For struct/object field access, we simply use dot notation in Nim, as demonstrated with the Person object.

  5. For map/table access, we use Nim’s Table type from the tables module.

  6. The t3 function demonstrates conditional logic similar to the if/else in Go templates.

  7. The t4 function shows how to iterate over a sequence, similar to the range functionality in Go templates.

To run this program, save it as text_templates.nim and use the Nim compiler:

$ nim c -r text_templates.nim
Value is some text
Value is 5
Value is @["Nim", "Python", "C++", "C#"]
Value: some text
Value: 5
Value: @["Nim", "Python", "C++", "C#"]
Name: Jane Doe
Name: Mickey Mouse
yes
no
Range: Nim Python C++ C# 

This example demonstrates how to achieve similar template functionality in Nim, even though it doesn’t have a built-in template engine like Go. Nim’s powerful string interpolation and macro system allow for flexible and type-safe template-like operations.