lydown 0.12.4 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -1
- data/bin/lydown +2 -0
- data/lib/lydown.rb +6 -2
- data/lib/lydown/cache.rb +5 -1
- data/lib/lydown/cli.rb +1 -1
- data/lib/lydown/cli/commands.rb +7 -11
- data/lib/lydown/cli/compiler.rb +5 -0
- data/lib/lydown/cli/proofing.rb +2 -2
- data/lib/lydown/cli/repl.rb +1 -1
- data/lib/lydown/cli/support.rb +0 -33
- data/lib/lydown/defaults.yml +50 -8
- data/lib/lydown/inverso.rb +84 -0
- data/lib/lydown/lilypond.rb +76 -10
- data/lib/lydown/ly_lib/lib.ly +140 -127
- data/lib/lydown/parsing/lydown.treetop +25 -12
- data/lib/lydown/parsing/nodes.rb +55 -19
- data/lib/lydown/rendering.rb +72 -1
- data/lib/lydown/rendering/base.rb +21 -0
- data/lib/lydown/rendering/command.rb +53 -0
- data/lib/lydown/rendering/layout.rb +83 -0
- data/lib/lydown/rendering/lyrics.rb +1 -1
- data/lib/lydown/rendering/markup.rb +23 -0
- data/lib/lydown/rendering/movement.rb +7 -4
- data/lib/lydown/rendering/music.rb +35 -29
- data/lib/lydown/rendering/notes.rb +75 -41
- data/lib/lydown/rendering/repeats.rb +27 -0
- data/lib/lydown/rendering/settings.rb +36 -9
- data/lib/lydown/rendering/skipping.rb +10 -2
- data/lib/lydown/rendering/staff.rb +38 -31
- data/lib/lydown/rendering/voices.rb +1 -1
- data/lib/lydown/templates.rb +8 -8
- data/lib/lydown/templates/layout.rb +40 -0
- data/lib/lydown/templates/lilypond_doc.rb +95 -0
- data/lib/lydown/templates/movement.rb +188 -0
- data/lib/lydown/templates/multi_voice.rb +25 -0
- data/lib/lydown/templates/part.rb +146 -0
- data/lib/lydown/templates/variables.rb +43 -0
- data/lib/lydown/translation/ripple.rb +1 -1
- data/lib/lydown/translation/ripple/nodes.rb +51 -2
- data/lib/lydown/translation/ripple/ripple.treetop +87 -10
- data/lib/lydown/version.rb +1 -1
- data/lib/lydown/work.rb +19 -2
- data/lib/lydown/work_context.rb +10 -2
- metadata +12 -8
- data/lib/lydown/cli/installer.rb +0 -175
- data/lib/lydown/templates/lilypond_doc.erb +0 -34
- data/lib/lydown/templates/movement.erb +0 -118
- data/lib/lydown/templates/multi_voice.erb +0 -16
- data/lib/lydown/templates/part.erb +0 -118
- data/lib/lydown/templates/variables.erb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e53564b3a5ed77a00ed654832969bb2002936153
|
4
|
+
data.tar.gz: 306631f5b426ae1ae60ce2e078e20496f2220dad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c7bd65c2523aab457281ca7626ee0b22402cb3c58a361b9d325f9e63afea6ee8c47a9672a18c206d0c7f0cc718d88e2eb92d3a03bbdf8edab17ff7ceaa11b99
|
7
|
+
data.tar.gz: 6284022bcc43a640c6fc099dc92bc21675938ab186b9bc63fc8272c17afd32af1ffe996b03184743348c8cf959e84760b633621a2b5bfc43423470fb9052ac20
|
data/README.md
CHANGED
@@ -12,8 +12,10 @@ Lydown is a language and compiler for creating music scores, parts and snippets.
|
|
12
12
|
- [The lydown syntax](#the-lydown-syntax)
|
13
13
|
- [Notes and durations](#notes-and-durations)
|
14
14
|
- [Accidentals](#accidentals)
|
15
|
-
- [Octaves](#
|
15
|
+
- [Octaves](#octaves)
|
16
|
+
- [Grace notes](#grace-notes)
|
16
17
|
- [Barlines](#barlines)
|
18
|
+
- [Repeats with alternatives](#repeats-with-alternatives)
|
17
19
|
- [Rests](#rests)
|
18
20
|
- [Beams, slurs and ties](#beams-slurs-and-ties)
|
19
21
|
- [Articulation and expression marks](#articulation-and-expression-marks)
|
@@ -279,6 +281,23 @@ c''' // third octave
|
|
279
281
|
For the following notes, the octave markers <code>'</code> and <code>,</code> are used for jumping between octaves, using the same rules as
|
280
282
|
lilypond's [relative mode](http://www.lilypond.org/doc/v2.18/Documentation/notation/writing-pitches#relative-octave-entry):
|
281
283
|
|
284
|
+
### Grace notes
|
285
|
+
|
286
|
+
Grace notes are signified by appending a grace kind after the the duration value:
|
287
|
+
|
288
|
+
```lydown
|
289
|
+
// grace
|
290
|
+
6°d8edcd2c
|
291
|
+
|
292
|
+
// appoggiatura
|
293
|
+
6^d8cbag
|
294
|
+
|
295
|
+
// acciaccatura
|
296
|
+
6`dc8bcde
|
297
|
+
```
|
298
|
+
|
299
|
+
The grace holds until the next change of duration.
|
300
|
+
|
282
301
|
### Barlines
|
283
302
|
|
284
303
|
Just like in lilypond, barlines are taken care of automatically according to the time signature. Final bar lines and repeat bar lines can be entered explicitly by using shorthand syntax:
|
@@ -294,6 +313,19 @@ When entering unmetered music, an invisible barline can be added in order to pro
|
|
294
313
|
cdef ?| gag
|
295
314
|
```
|
296
315
|
|
316
|
+
### Repeats with alternatives
|
317
|
+
|
318
|
+
Repeats with alternatives can be written by using the following syntax:
|
319
|
+
|
320
|
+
```lydown
|
321
|
+
|:*2 // start a repeat
|
322
|
+
|* // start a volta
|
323
|
+
*| // end the repeat
|
324
|
+
|
325
|
+
// example: 2 repeats
|
326
|
+
|:*2 1c d |* e f |* g a *| b c
|
327
|
+
```
|
328
|
+
|
297
329
|
### Rests and silences
|
298
330
|
|
299
331
|
Normal rests are written [like in lilypond](http://www.lilypond.org/doc/v2.18/Documentation/notation/writing-rests#rests):
|
@@ -814,6 +846,14 @@ To place includes at the beginning of the lilypond document, includes should be
|
|
814
846
|
|
815
847
|
Pathnames are relative to the lydown source file.
|
816
848
|
|
849
|
+
## Requiring packages
|
850
|
+
|
851
|
+
[Lyp](https://github.com/noteflakes/lyp) packages can be loaded by using `-include` settings, usually in `work.ld`:
|
852
|
+
|
853
|
+
```lydown
|
854
|
+
- require: better-slurs
|
855
|
+
```
|
856
|
+
|
817
857
|
### Including templates
|
818
858
|
|
819
859
|
In addition to including normal lilypond files, Lydown also supports the rendering of templates into the generated lilypond doc, by using the <code>.ely</code> extension. The templates should be written using Ruby's [ERB](http://www.stuartellis.eu/articles/erb/) syntax, and are supplied with the lydown context object as <code>self</code>. A trivial example:
|
data/bin/lydown
CHANGED
data/lib/lydown.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
1
3
|
require 'lydown/core_ext'
|
2
4
|
require 'lydown/cache'
|
3
5
|
|
4
6
|
module Lydown
|
5
7
|
require 'yaml'
|
6
|
-
|
7
|
-
|
8
|
+
|
9
|
+
DEFAUTLS_FILENAME = File.expand_path('lydown/defaults.yml', File.dirname(__FILE__))
|
10
|
+
DEFAULTS = YAML.load(IO.read(DEFAUTLS_FILENAME)).deep!
|
8
11
|
end
|
9
12
|
|
10
13
|
require 'lydown/errors'
|
11
14
|
require 'lydown/parsing'
|
12
15
|
require 'lydown/templates'
|
16
|
+
require 'lydown/inverso'
|
13
17
|
require 'lydown/rendering'
|
14
18
|
require 'lydown/lilypond'
|
15
19
|
require 'lydown/work_context'
|
data/lib/lydown/cache.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'digest/md5'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module Cache
|
4
5
|
class << self
|
@@ -46,8 +47,11 @@ module Cache
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
50
|
+
CACHE_DIR = "/tmp/lydown/cache"
|
51
|
+
FileUtils.mkdir_p(CACHE_DIR)
|
52
|
+
|
49
53
|
def filename(cache_key)
|
50
|
-
"
|
54
|
+
"#{CACHE_DIR}/#{cache_key}"
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
data/lib/lydown/cli.rb
CHANGED
data/lib/lydown/cli/commands.rb
CHANGED
@@ -2,12 +2,16 @@ require 'thor'
|
|
2
2
|
|
3
3
|
module Lydown::CLI
|
4
4
|
class Commands < Thor
|
5
|
+
package_name "lydown"
|
6
|
+
map "-v" => :version
|
7
|
+
class_option :verbose, aliases: '-V', :type => :boolean, desc: 'show verbose output'
|
8
|
+
|
5
9
|
desc "version", "show Lydown version"
|
6
10
|
def version
|
7
11
|
require 'lydown/version'
|
8
12
|
$stderr.puts "Lydown version #{Lydown::VERSION}"
|
9
13
|
|
10
|
-
lilypond_version = Lydown::
|
14
|
+
lilypond_version = Lydown::Lilypond.detect_lilypond_version(false)
|
11
15
|
if lilypond_version
|
12
16
|
$stderr.puts "Lilypond version #{lilypond_version}"
|
13
17
|
end
|
@@ -37,7 +41,8 @@ module Lydown::CLI
|
|
37
41
|
desc: 'Open output file after compilation'
|
38
42
|
method_option :separate, type: :boolean, aliases: '-S',
|
39
43
|
desc: 'Create separate file for each movement'
|
40
|
-
method_option :verbose, type: :boolean
|
44
|
+
method_option :verbose, aliases: '-V', type: :boolean
|
45
|
+
method_option :edition, aliases: '-e', type: :string
|
41
46
|
def compile(*args)
|
42
47
|
path = args.first || '.'
|
43
48
|
|
@@ -46,8 +51,6 @@ module Lydown::CLI
|
|
46
51
|
return send($1)
|
47
52
|
end
|
48
53
|
|
49
|
-
Lydown::CLI::Support.detect_lilypond_version(true)
|
50
|
-
|
51
54
|
require 'lydown'
|
52
55
|
|
53
56
|
opts = Lydown::CLI::Support.copy_options(options)
|
@@ -88,8 +91,6 @@ module Lydown::CLI
|
|
88
91
|
enum: %w{pdf png ly}
|
89
92
|
method_option :include_parts, aliases: '-i', desc: 'Include parts (comma separated)'
|
90
93
|
def proof(*args)
|
91
|
-
Lydown::CLI::Support.detect_lilypond_version(true)
|
92
|
-
|
93
94
|
require 'lydown'
|
94
95
|
|
95
96
|
opts = Lydown::CLI::Support.copy_options(options)
|
@@ -115,11 +116,6 @@ module Lydown::CLI
|
|
115
116
|
Lydown::CLI::Translation.process(opts)
|
116
117
|
end
|
117
118
|
|
118
|
-
desc "install [PACKAGE] [VERSION]", "install a package"
|
119
|
-
def install(*args)
|
120
|
-
Lydown::CLI::Installer.install(*args)
|
121
|
-
end
|
122
|
-
|
123
119
|
def method_missing(method, *args)
|
124
120
|
args = ["compile", method.to_s] + args
|
125
121
|
self.class.start(args)
|
data/lib/lydown/cli/compiler.rb
CHANGED
@@ -165,6 +165,11 @@ module Lydown::CLI::Compiler
|
|
165
165
|
|
166
166
|
def output_filename(opts)
|
167
167
|
fn = opts[:output_filename].dup
|
168
|
+
|
169
|
+
if opts[:edition]
|
170
|
+
fn << "-#{opts[:edition]}"
|
171
|
+
end
|
172
|
+
|
168
173
|
if opts[:movements] && opts[:movements].size == 1
|
169
174
|
fn << "-#{opts[:movements].first}"
|
170
175
|
end
|
data/lib/lydown/cli/proofing.rb
CHANGED
@@ -3,7 +3,7 @@ require 'directory_watcher'
|
|
3
3
|
module Lydown::CLI::Proofing
|
4
4
|
class << self
|
5
5
|
def start_proofing(opts)
|
6
|
-
$stderr.puts "Proof mode: #{
|
6
|
+
$stderr.puts "Proof mode: #{opts[:source_filename]} -> #{opts[:output_filename]}"
|
7
7
|
|
8
8
|
trap("INT") {return}
|
9
9
|
watch(opts)
|
@@ -65,7 +65,7 @@ module Lydown::CLI::Proofing
|
|
65
65
|
if dir =~ /^\.\/(.+)$/
|
66
66
|
dir = $1
|
67
67
|
end
|
68
|
-
if dir =~ /#{base}\/([^\/]+)/
|
68
|
+
if File.expand_path(dir) =~ /#{base}\/([^\/]+)/
|
69
69
|
mvt = $1
|
70
70
|
else
|
71
71
|
mvt = nil
|
data/lib/lydown/cli/repl.rb
CHANGED
@@ -9,7 +9,7 @@ module Lydown::CLI::REPL
|
|
9
9
|
require 'lydown/version'
|
10
10
|
puts "Lydown version #{Lydown::VERSION}"
|
11
11
|
|
12
|
-
lilypond_version = Lydown::
|
12
|
+
lilypond_version = Lydown::Lilypond.detect_lilypond_version(true)
|
13
13
|
if lilypond_version
|
14
14
|
puts "Lilypond version #{lilypond_version}"
|
15
15
|
end
|
data/lib/lydown/cli/support.rb
CHANGED
@@ -49,39 +49,6 @@ module Lydown::CLI::Support
|
|
49
49
|
opts[:path] = parent_dir
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
MINIMAL_LILYPOND_VERSION = Gem::Version.new('2.18')
|
54
|
-
|
55
|
-
# detect the lilypond version. If lilypond is not found, or the version is
|
56
|
-
# less than the minimal supported version, display an error message.
|
57
|
-
def self.detect_lilypond_version(exit_on_error)
|
58
|
-
msg = `lilypond --version`
|
59
|
-
version = nil
|
60
|
-
if msg.lines.first =~ /LilyPond ([\d\.]+)/
|
61
|
-
version = $1
|
62
|
-
end
|
63
|
-
unless version && Gem::Version.new(version) >= MINIMAL_LILYPOND_VERSION
|
64
|
-
display_lilypond_version_error_msg(version)
|
65
|
-
exit!(1) if exit_on_error
|
66
|
-
version = nil
|
67
|
-
end
|
68
|
-
version
|
69
|
-
rescue => e
|
70
|
-
display_lilypond_version_error_msg(nil)
|
71
|
-
exit!(1) if exit_on_error
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.display_lilypond_version_error_msg(version)
|
75
|
-
if version
|
76
|
-
STDERR.puts "ERROR: The installed lilypond (version #{version}) is too old.
|
77
|
-
You can install lilypond by running `lydown install lilypond` or by
|
78
|
-
downloading a recent version from http://lilypond.org/"
|
79
|
-
else
|
80
|
-
STDERR.puts "ERROR: No copy of lilypond found.
|
81
|
-
You can install lilypond by running `lydown install lilypond` or by
|
82
|
-
downloading a recent version from http://lilypond.org/"
|
83
|
-
end
|
84
|
-
end
|
85
52
|
end
|
86
53
|
|
87
54
|
|
data/lib/lydown/defaults.yml
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
layout:
|
2
|
+
paper: A4 portrait
|
3
|
+
staff_size: 6mm
|
4
|
+
margin_inner: 12mm
|
5
|
+
margin_outer: 18mm
|
6
|
+
margin_top: 10mm
|
7
|
+
margin_bottom: 10mm
|
8
|
+
margin_top_content: 24mm
|
9
|
+
margin_bottom_content: 24mm
|
5
10
|
parts:
|
11
|
+
layout:
|
12
|
+
staff_size: 7mm
|
6
13
|
soprano:
|
7
14
|
clef: treble
|
8
15
|
beaming: manual
|
@@ -102,6 +109,12 @@ parts:
|
|
102
109
|
violino2:
|
103
110
|
clef: treble
|
104
111
|
midi_instrument: violin
|
112
|
+
violon1:
|
113
|
+
clef: treble
|
114
|
+
midi_instrument: violin
|
115
|
+
violon2:
|
116
|
+
clef: treble
|
117
|
+
midi_instrument: violin
|
105
118
|
violini:
|
106
119
|
clef: treble
|
107
120
|
midi_instrument: violin
|
@@ -132,6 +145,15 @@ parts:
|
|
132
145
|
gamba2:
|
133
146
|
clef: alto
|
134
147
|
midi_instrument: viola
|
148
|
+
viole:
|
149
|
+
clef: alto
|
150
|
+
midi_instrument: viola
|
151
|
+
viole1:
|
152
|
+
clef: alto
|
153
|
+
midi_instrument: viola
|
154
|
+
viole2:
|
155
|
+
clef: alto
|
156
|
+
midi_instrument: viola
|
135
157
|
fagott:
|
136
158
|
clef: bass
|
137
159
|
midi_instrument: bassoon
|
@@ -176,13 +198,33 @@ parts:
|
|
176
198
|
midi_instrument: flute
|
177
199
|
flute2:
|
178
200
|
midi_instrument: flute
|
201
|
+
trumpet:
|
202
|
+
midi_instrument: trumpet
|
203
|
+
tromba:
|
204
|
+
midi_instrument: trumpet
|
205
|
+
trumpet1:
|
206
|
+
midi_instrument: trumpet
|
207
|
+
trumpet2:
|
208
|
+
midi_instrument: trumpet
|
209
|
+
trumpet3:
|
210
|
+
midi_instrument: trumpet
|
211
|
+
tromba1:
|
212
|
+
midi_instrument: trumpet
|
213
|
+
tromba2:
|
214
|
+
midi_instrument: trumpet
|
215
|
+
tromba3:
|
216
|
+
midi_instrument: trumpet
|
217
|
+
|
179
218
|
score:
|
219
|
+
layout:
|
220
|
+
staff_size: 4.8mm
|
180
221
|
order:
|
222
|
+
- [trumpet, tromba, trumpet1, trumpet2, trumpet3, tromba1, tromba2, tromba3]
|
181
223
|
- [flute, flauto1, flauto2, flauto3, flute1, flute2, flute3]
|
182
224
|
- [oboe, oboe1, oboe2, oboe3]
|
183
|
-
- [violino, violino1, violino2, violino3, violin1, violin2, violin3]
|
184
|
-
-
|
185
|
-
- [gamba, gamba1, gamba2]
|
225
|
+
- [violino, violino1, violino2, violino3, violin1, violin2, violin3, viola, violon1, violon2]
|
226
|
+
- [viola1, viola2]
|
227
|
+
- [gamba, viole, gamba1, gamba2, viole1, viole2]
|
186
228
|
- [soprano1, soprano2, soprano, alto1, alto2, alto, tenore1, tenore2, tenore, basso1, basso2, basso]
|
187
|
-
- continuo
|
229
|
+
- [fagotto, continuo, "basse-continue"]
|
188
230
|
end_barline: "|."
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Inverso
|
2
|
+
class Template
|
3
|
+
EMIT_DELIMITER = '`'.freeze
|
4
|
+
EMIT_RE = /#{EMIT_DELIMITER}(((?!#{EMIT_DELIMITER}).)*)#{EMIT_DELIMITER}/m
|
5
|
+
|
6
|
+
INTERPOLATION_START = "{{".freeze
|
7
|
+
INTERPOLATION_END = "}}".freeze
|
8
|
+
INTERPOLATION_RE = /#{INTERPOLATION_START}([^\?\/](?:(?!#{INTERPOLATION_END}).)*)#{INTERPOLATION_END}/m
|
9
|
+
|
10
|
+
IF_START = "{{?".freeze
|
11
|
+
IF_END = "{{/}}".freeze
|
12
|
+
IF_RE = /\{\{\?((?:(?!#{INTERPOLATION_END}).)*)#{INTERPOLATION_END}((?:(?!#{IF_END}).)*)#{IF_END}/m
|
13
|
+
|
14
|
+
ESCAPED_QUOTE = '\\"'.freeze
|
15
|
+
QUOTE = '"'.freeze
|
16
|
+
|
17
|
+
# From the metaid gem
|
18
|
+
def metaclass; class << self; self; end; end
|
19
|
+
|
20
|
+
def initialize(templ)
|
21
|
+
templ = templ.gsub(EMIT_RE) {|m| convert_literal($1)}
|
22
|
+
method_str = <<EOF
|
23
|
+
define_method(:render) do |_ = {}, env = {}|
|
24
|
+
_.each {|k, v| metaclass.instance_eval {define_method(k) {v}}}
|
25
|
+
__buffer__ = env[:buffer] ||= ''
|
26
|
+
__emit__ = env[:emit] ||= lambda {|*args| args.each {|s| __buffer__ << s}}
|
27
|
+
__render_l__ = env[:render] ||= lambda {|n, o| Template.render(n, o, env)}
|
28
|
+
metaclass.instance_eval "define_method(:__render__) {|n, o| __render_l__[n, o]}"
|
29
|
+
begin
|
30
|
+
#{templ}
|
31
|
+
end
|
32
|
+
__buffer__.gsub(/^\s+$/, '').gsub(/\n+/m, "\n")
|
33
|
+
end
|
34
|
+
EOF
|
35
|
+
|
36
|
+
metaclass.instance_eval method_str
|
37
|
+
end
|
38
|
+
|
39
|
+
def convert_interpolation(s)
|
40
|
+
s.gsub(INTERPOLATION_RE) do
|
41
|
+
code = $1.gsub(ESCAPED_QUOTE, QUOTE)
|
42
|
+
"\#{#{code}}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def convert_literal(s)
|
47
|
+
# look for interpolated values, wrap them with #{}
|
48
|
+
s = s.inspect.gsub(INTERPOLATION_RE) do
|
49
|
+
code = $1.gsub(ESCAPED_QUOTE, QUOTE)
|
50
|
+
"\#{#{code}}"
|
51
|
+
end
|
52
|
+
|
53
|
+
s = s.gsub(IF_RE) do
|
54
|
+
test, code = $1, $2
|
55
|
+
test = test.strip.gsub(ESCAPED_QUOTE, QUOTE)
|
56
|
+
"\#\{if #{test}; \"#{code}\"; end}"
|
57
|
+
end
|
58
|
+
|
59
|
+
"__emit__[#{s}]"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Global template registry
|
63
|
+
@@templates = {}
|
64
|
+
|
65
|
+
def self.load_templates(path)
|
66
|
+
Dir["#{path}/*.rb"].each do |fn|
|
67
|
+
File.basename(fn) =~ /^(.+)\.rb$/
|
68
|
+
name = $1
|
69
|
+
set(name, IO.read(fn))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.set(name, templ)
|
74
|
+
@@templates[name.to_sym] = new(templ)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.render(name, arg = {}, env = {})
|
78
|
+
raise unless @@templates[name.to_sym]
|
79
|
+
@@templates[name.to_sym].render(arg, env)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
Inverso::Template.load_templates(File.expand_path('templates', File.dirname(__FILE__)))
|