Pax

#!/usr/bin/env ruby
# frozen_string_literal: true


class Pax
  
  def initialize
    @tmp = {}
    @rxc = Regexp.new('\<%\s*(.*?)\s*%\>', 'm')
    @rxt = Regexp.new('\<@\s(\w+)*\s*@\>')
  end

  def method_missing(name, *args, bnd: TOPLEVEL_BINDING)
    (name.end_with? ?=) ?
      (@tmp[name[..-2].to_sym] = args[0]) :
        (@tmp[name] ? parse(@tmp[name], bnd) : super)
  end

  private
  def parse(mall, bnd)
    m = mall.dup.strip
    m.gsub!(@rxc) {|m| eval("#{$1}", bnd) }
    m.gsub!(@rxt) {|m| parse(@tmp[:"#{$1}"], bnd) }
    m
  end
end

Ox = Pax.new



Ox.pers = %(| <% '%10s' % name %> | <% '%5s' % age %> | <% '%10s' % city %> |)
Ox.line = %(<% puts '-' * 35 %>)

data = [
  %w(Ulla 45 Jönköping),
  %w(Bert 32 Karlstad),
  %w(Lisen 28 Hjo),
  %w(Zoltan 72 Vimmerby)
]

Ox.line
data.each {|pers|
  name, age, city = *pers
  puts Ox.pers bnd: binding
}
Ox.line

# =>  -----------------------------------
# =>  |       Ulla |    45 |  Jönköping |
# =>  |       Bert |    32 |   Karlstad |
# =>  |      Lisen |    28 |        Hjo |
# =>  |     Zoltan |    72 |   Vimmerby |
# =>  -----------------------------------