You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.5 KiB
Ruby

# frozen_string_literal: true
require_relative 'util'
require 'ostruct'
module Template
REGEX = %r{(?://\$([^\n]*(?:\n|$))|/\*\$(.*?)\*/)}
@cache = {}
@template_stack = []
def self.template inp, vals = nil, c = nil
raise ArgumentError, 'Input is nil' if inp.nil?
return inp unless inp =~ REGEX
raise ArgumentError, 'No vals' if vals.nil? && @template_stack.empty?
@cache[inp] ||= begin
code = +'::Kernel.proc{__tmpl_out = ::String.new;'
prev_pos = 0
while m = inp.match(REGEX, prev_pos)
cur_pos = m.begin 0
unless prev_pos == cur_pos
code << "__tmpl_out << #{inp[prev_pos...cur_pos].inspect};"
end
snip = m.match(1) || m.match(2)
if snip.start_with? '='
code << "__tmpl_out << (#{snip[1..]}).to_s;"
else
code << "#{snip};"
end
prev_pos = cur_pos + m.match(0).size
end
unless prev_pos == inp.size
code << "__tmpl_out << #{inp[prev_pos..].inspect};"
end
code << '__tmpl_out}'
eval code
end
begin
if vals.nil?
@template_stack[-1].instance_eval &@cache[inp]
else
os_vals = OpenStruct.new vals
@template_stack << os_vals
begin
return os_vals.instance_eval &@cache[inp]
ensure
@template_stack.pop
end
end
rescue
Util.print_error "Invalid template #{inp.inspect}: #{$!.full_message}", c
return ''
end
end
end