goodtouch

goodtouch

SmartIndentationEngine — Clean indentation for EEx templates

Over the last few days I built a small custom EEx engine that tackles a frustration I’ve had for a while trying to get proper indentation with EEx templates. I thought some of you might find it useful too.

I’ve been doing a lot of Codegen lately and when writing EEx templates with loops and conditionals, I often end up facing a choice between:

  • Messy template code to get properly formatted output
  • Clean template code but with weird (or even invalid) spacing in the output

This library attempts to fix this by extending EEx.SmartEngine with a special <%| tag that injects some context-aware string manipulation into the AST to ensure that the output is indented in a way that makes sense (at least to me :sweat_smile:).

It also provides a ~TT sigil for convenience and supports including (and re-indenting) “partial” templates.

Quick Example

defmodule Template.DockerCompose do
  import SmartIndentationEngine.Template

  def render(assigns) do
    ~TT"""
    services:
      <%| for {name, config} <- @services do %>
        <%= name %>:
          <%= include :service, config: config %>
      <% end %>
    """
  end
  
  def service(assigns) do
    ~TT"""
    image: <%= @config.image %>
    ports:
      <%| for port <- @config.ports do %>
        - <%= port %>
      <% end %>
    # ...
    """
  end
end

Template.DockerCompose.render(
  services: %{
    livebook: %{
      image: "ghcr.io/livebook-dev/livebook:0.15.5",
      ports: [8080, 8081]
    }
  }
)

This will produce the following output:

services:
  livebook:
    image: ghcr.io/livebook-dev/livebook:0.15.5
    ports:
      - 8080
      - 8081
    # ...

Give It a Try!

I just published it on Hex: smart_indentation_engine.

If you’re working with EEx templates, I’d love for you to try it out. Let me know what you think, if you encounter any issues, edge cases, or if you have ideas for improvements!

Where Next?

Popular in Libraries Top

achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
tmbb
I’ve decided to create this topic to discuss optimization possibilities for something like Phoenix LiveView. I’ve created this topic unde...
New
RobertDober
Earmark is a pure-Elixir Markdown converter. It is intended to be used as a library (just call Earmark.as_html), but can also be used as...
239 11851 134
New
marcuslankenau
I feel kind of stuck with the absence of a proper xml library for Elixir. Currently I use SweetXML which was ok for me more or less to pa...
New
mindok
What is ContEx? A pure Elixir server-side data plotting/charting library outputting SVG. It has nice barcharts in particular and works g...
New
Crowdhailer
Raxx is an alternative to Plug and is inspired by projects such as Rack(Ruby) and Ring(Clojure). 1.0-rc.1 is now available. To use it re...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
Crowdhailer
I have been updating a library that allows you to pipe between functions that use the erlang result tuple convention. Assuming you have...
New
Qqwy
Hello everyone, I wrote a small library today called MapDiff. It returns a map listing the (smallest amount of) changes to get from map...
New
ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New

Other popular topics Top

belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

Sub Categories:

We're in Beta

About us Mission Statement