Class: XRB::Template

Inherits:
Object
  • Object
show all
Defined in:
lib/xrb/template.rb

Overview

An evaluatable text-format that can be used to generate output.

Defined Under Namespace

Classes: Assembler

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buffer, binding: BINDING) ⇒ Template

Initialize a new template.



96
97
98
99
100
101
102
# File 'lib/xrb/template.rb', line 96

def initialize(buffer, binding: BINDING)
	@buffer = buffer
	@binding = binding
	
	@code = nil
	@compiled = nil
end

Class Method Details

.buffer(binding) ⇒ Object



50
51
52
# File 'lib/xrb/template.rb', line 50

def self.buffer(binding)
	binding.local_variable_get(OUT)
end

.capture(*arguments, output: nil, &block) ⇒ Object

Capture the output of a block from within a template.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/xrb/template.rb', line 33

def self.capture(*arguments, output: nil, &block)
	scope = block.binding
	previous_output = scope.local_variable_get(OUT)
	
	output ||= previous_output.class.new(encoding: previous_output.encoding)
	scope.local_variable_set(OUT, output)
	
	begin
		block.call(*arguments)
	ensure
		scope.local_variable_set(OUT, previous_output)
	end
	
	return output.to_str
end

.load(string, *arguments, **options) ⇒ Object

Load a template from a string.



89
90
91
# File 'lib/xrb/template.rb', line 89

def self.load(string, *arguments, **options)
	self.new(Buffer.new(string), **options).freeze
end

.load_file(path, **options) ⇒ Object

Load a template from a file.



84
85
86
# File 'lib/xrb/template.rb', line 84

def self.load_file(path, **options)
	self.new(FileBuffer.new(path), **options).freeze
end

Instance Method Details

#codeObject

The compiled code for the template.



116
117
118
# File 'lib/xrb/template.rb', line 116

def code
	@code ||= compile!
end

#compiled(scope = @binding.dup) ⇒ Object

The compiled template as a proc.



123
124
125
# File 'lib/xrb/template.rb', line 123

def compiled(scope = @binding.dup)
	@compiled ||= eval("\# frozen_string_literal: true\nproc{|#{OUT}|;#{code}}", scope, @buffer.path, 0).freeze
end

#freezeObject

Compile and freeze the template.



106
107
108
109
110
111
112
# File 'lib/xrb/template.rb', line 106

def freeze
	return self if frozen?
	
	compiled
	
	super
end

#to_buffer(scope) ⇒ Object

Renders the template to a buffer.



140
141
142
# File 'lib/xrb/template.rb', line 140

def to_buffer(scope)
	Buffer.new(to_string(scope), path: @buffer.path)
end

#to_proc(scope = @binding.dup) ⇒ Object

Convert the template to a proc that can be called with an output object. The proc renders the template using to_string and writes the output to the given output object. The output should implement << and close_write(error = nil) methods.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/xrb/template.rb', line 148

def to_proc(scope = @binding.dup)
	proc do |output|
		to_string(scope, output)
	rescue Exception => error
		# I find this a bit ugly but we only use this code path on errors, so it's not performance critical.
		if output.method(:close_write).arity != 0
			# Inform the output that an error occured and the output was not generated correctly.
			output.close_write(error)
			output = nil
		end
		
		raise
	ensure
		output&.close_write
	end
end

#to_string(scope = Object.new, output = nil) ⇒ Object

Renders the template to a string.



131
132
133
134
135
136
137
# File 'lib/xrb/template.rb', line 131

def to_string(scope = Object.new, output = nil)
	builder = Builder.new(output, encoding: code.encoding)
	
	scope.instance_exec(builder, &compiled)
	
	return builder.output
end